diff options
Diffstat (limited to 'nanohttp/nanohttp-ssl.c')
-rw-r--r-- | nanohttp/nanohttp-ssl.c | 258 |
1 files changed, 158 insertions, 100 deletions
diff --git a/nanohttp/nanohttp-ssl.c b/nanohttp/nanohttp-ssl.c index 79506ea..b9e4af1 100644 --- a/nanohttp/nanohttp-ssl.c +++ b/nanohttp/nanohttp-ssl.c @@ -1,5 +1,5 @@ /****************************************************************** -* $Id: nanohttp-ssl.c,v 1.24 2006/04/17 12:26:17 mrcsys Exp $ +* $Id: nanohttp-ssl.c,v 1.25 2006/04/26 17:48:30 mrcsys Exp $ * * CSOAP Project: A http client/server library in C * Copyright (C) 2001-2005 Rochester Institute of Technology @@ -87,43 +87,47 @@ static int enabled = 0; int (*_hssl_verify_cert) (X509 * cert) = _hssl_dummy_verify_cert; static void -_hssl_superseed (void) +_hssl_superseed(void) { int buf[256], i; - srand (time (NULL)); + srand(time(NULL)); for (i = 0; i < 256; i++) { - buf[i] = rand (); + buf[i] = rand(); } - RAND_seed ((unsigned char *) buf, sizeof (buf)); + RAND_seed((unsigned char *) buf, sizeof(buf)); return; } static char * -_hssl_get_error(SSL *ssl, int ret) +_hssl_get_error(SSL * ssl, int ret) { switch (SSL_get_error(ssl, ret)) { - case SSL_ERROR_NONE: - return "None"; - case SSL_ERROR_ZERO_RETURN: - return "Zero return"; - case SSL_ERROR_WANT_READ: - return "Want read"; - case SSL_ERROR_WANT_WRITE: - return "Want write"; - case SSL_ERROR_WANT_X509_LOOKUP: - return "Want x509 lookup"; - case SSL_ERROR_SYSCALL: - return "Syscall failed"; - case SSL_ERROR_SSL: - return "SSL error"; - default: - return "Unkown error"; + case SSL_ERROR_NONE: + return "None"; + case SSL_ERROR_ZERO_RETURN: + return "Zero return"; + case SSL_ERROR_WANT_READ: + return "Want read"; + case SSL_ERROR_WANT_WRITE: + return "Want write"; + case SSL_ERROR_WANT_X509_LOOKUP: + return "Want x509 lookup"; + case SSL_ERROR_SYSCALL: + if (ERR_get_error() == 0 && ret == -1) + { + return strerror(errno); + } + return "Syscall failed"; + case SSL_ERROR_SSL: + return "SSL error"; + default: + return "Unkown error"; } } @@ -144,45 +148,46 @@ _hssl_password_callback(char *buf, int num, int rwflag, void *userdata) int -verify_sn (X509 * cert, int who, int nid, char *str) +verify_sn(X509 * cert, int who, int nid, char *str) { char name[256]; char buf[256]; - memset (name, '\0', 256); - memset (buf, '\0', 256); + memset(name, '\0', 256); + memset(buf, '\0', 256); if (who == CERT_SUBJECT) { - X509_NAME_oneline (X509_get_subject_name (cert), name, 256); + X509_NAME_oneline(X509_get_subject_name(cert), name, 256); } else { - X509_NAME_oneline (X509_get_issuer_name (cert), name, 256); + X509_NAME_oneline(X509_get_issuer_name(cert), name, 256); } buf[0] = '/'; - strcat (buf, OBJ_nid2sn (nid)); - strcat (buf, "="); - strcat (buf, str); + strcat(buf, OBJ_nid2sn(nid)); + strcat(buf, "="); + strcat(buf, str); return strstr(name, buf) ? 1 : 0; } void -hssl_set_hssl_verify_cert( int func(X509 * cert) ){ - _hssl_verify_cert = func; +hssl_set_hssl_verify_cert(int func(X509 * cert)) +{ + _hssl_verify_cert = func; } static int _hssl_dummy_verify_cert(X509 * cert) { - /* TODO: Make sure that the client is providing a client cert, - or that the Module is providing the Module cert */ + /* TODO: Make sure that the client is providing a client cert, or that the + Module is providing the Module cert */ /* connect to anyone */ - log_verbose1 ("Validating certificate."); + log_verbose1("Validating certificate."); return 1; } @@ -196,18 +201,41 @@ _hssl_cert_verify_callback(int prev_ok, X509_STORE_CTX * ctx) return 1; } */ - log_verbose2 ("Cert depth = %d", X509_STORE_CTX_get_error_depth(ctx) ); + log_verbose2("Cert depth = %d", X509_STORE_CTX_get_error_depth(ctx)); if (X509_STORE_CTX_get_error_depth(ctx) == 0) { return _hssl_verify_cert(X509_STORE_CTX_get_current_cert(ctx)); } else { - log_verbose1 ("Cert ok (prev)"); + log_verbose1("Cert ok (prev)"); return prev_ok; } } +void +hssl_set_certificate(char *c) +{ + certificate = c; +} + +void +hssl_set_certpass(char *c) +{ + certpass = c; +} + +void +hssl_set_ca(char *c) +{ + ca_list = c; +} + +void +hssl_enable(void) +{ + enabled = 1; +} static void _hssl_parse_arguments(int argc, char **argv) @@ -215,21 +243,21 @@ _hssl_parse_arguments(int argc, char **argv) int i; - for (i=1; i<argc; i++) + for (i = 1; i < argc; i++) { - if (!strcmp(argv[i-1], NHTTP_ARG_CERT)) + if (!strcmp(argv[i - 1], NHTTP_ARG_CERT)) { certificate = argv[i]; } - else if (!strcmp(argv[i-1], NHTTP_ARG_CERTPASS)) + else if (!strcmp(argv[i - 1], NHTTP_ARG_CERTPASS)) { certpass = argv[i]; } - else if (!strcmp(argv[i-1], NHTTP_ARG_CA)) + else if (!strcmp(argv[i - 1], NHTTP_ARG_CA)) { ca_list = argv[i]; } - else if (!strcmp(argv[i-1], NHTTP_ARG_HTTPS)) + else if (!strcmp(argv[i - 1], NHTTP_ARG_HTTPS)) { enabled = 1; } @@ -246,7 +274,7 @@ _hssl_library_init(void) if (!initialized) { - log_verbose1 ("Initializing library"); + log_verbose1("Initializing library"); SSL_library_init(); @@ -272,24 +300,27 @@ _hssl_server_context_init(void) if (!(context = SSL_CTX_new(SSLv23_method()))) { - log_error1 ("Cannot create SSL context"); - return herror_new("_hssl_server_context_init", HSSL_ERROR_CONTEXT, "Unable to create SSL context"); + log_error1("Cannot create SSL context"); + return herror_new("_hssl_server_context_init", HSSL_ERROR_CONTEXT, + "Unable to create SSL context"); } - if (!(SSL_CTX_use_certificate_file (context, certificate, SSL_FILETYPE_PEM))) + if (!(SSL_CTX_use_certificate_file(context, certificate, SSL_FILETYPE_PEM))) { - log_error2 ("Cannot read certificate file: \"%s\"", certificate); + log_error2("Cannot read certificate file: \"%s\"", certificate); SSL_CTX_free(context); - return herror_new("_hssl_server_context_init", HSSL_ERROR_CERTIFICATE, "Unable to use SSL certificate \"%s\"", certificate); + return herror_new("_hssl_server_context_init", HSSL_ERROR_CERTIFICATE, + "Unable to use SSL certificate \"%s\"", certificate); } SSL_CTX_set_default_passwd_cb(context, _hssl_password_callback); if (!(SSL_CTX_use_PrivateKey_file(context, certificate, SSL_FILETYPE_PEM))) { - log_error2 ("Cannot read key file: \"%s\"", certificate); - SSL_CTX_free(context); - return herror_new("_hssl_server_context_init", HSSL_ERROR_PEM, "Unable to use private key"); + log_error2("Cannot read key file: \"%s\"", certificate); + SSL_CTX_free(context); + return herror_new("_hssl_server_context_init", HSSL_ERROR_PEM, + "Unable to use private key"); } if (ca_list != NULL && *ca_list != '\0') @@ -297,15 +328,17 @@ _hssl_server_context_init(void) if (!(SSL_CTX_load_verify_locations(context, ca_list, NULL))) { SSL_CTX_free(context); - log_error2 ("Cannot read CA list: \"%s\"", ca_list); - return herror_new("_hssl_server_context_init", HSSL_ERROR_CA_LIST, "Unable to read certification authorities \"%s\""); + log_error2("Cannot read CA list: \"%s\"", ca_list); + return herror_new("_hssl_server_context_init", HSSL_ERROR_CA_LIST, + "Unable to read certification authorities \"%s\""); } - SSL_CTX_set_client_CA_list (context, SSL_load_client_CA_file (ca_list)); - log_verbose1 ("Certification authority contacted"); + SSL_CTX_set_client_CA_list(context, SSL_load_client_CA_file(ca_list)); + log_verbose1("Certification authority contacted"); } - SSL_CTX_set_verify(context, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, _hssl_cert_verify_callback); + SSL_CTX_set_verify(context, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, + _hssl_cert_verify_callback); log_verbose1("Certificate verification callback registered"); SSL_CTX_set_mode(context, SSL_MODE_AUTO_RETRY); @@ -366,12 +399,12 @@ hssl_enabled(void) herror_t -hssl_client_ssl(hsocket_t *sock) +hssl_client_ssl(hsocket_t * sock) { SSL *ssl; int ret; - log_verbose1 ("Starting SSL client initialization"); + log_verbose1("Starting SSL client initialization"); if (!(ssl = SSL_new(context))) { @@ -379,46 +412,49 @@ hssl_client_ssl(hsocket_t *sock) return herror_new("hssl_client_ssl", HSSL_ERROR_CLIENT, "SSL_new failed"); } - SSL_set_fd (ssl, sock->sock); + SSL_set_fd(ssl, sock->sock); if ((ret = SSL_connect(ssl)) <= 0) { herror_t err; - log_error2 ("SSL connect error (%s)", _hssl_get_error(ssl, -1)); - err = herror_new("hssl_client_ssl", HSSL_ERROR_CONNECT, "SSL_connect failed (%s)", _hssl_get_error(ssl, ret)); - SSL_free (ssl); + log_error2("SSL connect error (%s)", _hssl_get_error(ssl, -1)); + err = + herror_new("hssl_client_ssl", HSSL_ERROR_CONNECT, + "SSL_connect failed (%s)", _hssl_get_error(ssl, ret)); + SSL_free(ssl); return err; } - /* SSL_connect should take care of this for us. - if (SSL_get_peer_certificate(ssl) == NULL) - { - log_error1("No certificate provided"); - SSL_free(ssl); - return herror_new("hssl_client_ssl", HSSL_ERROR_CERTIFICATE, "No certificate provided"); - } + /* SSL_connect should take care of this for us. if + (SSL_get_peer_certificate(ssl) == NULL) { log_error1("No certificate + provided"); SSL_free(ssl); return herror_new("hssl_client_ssl", + HSSL_ERROR_CERTIFICATE, "No certificate provided"); } - if (SSL_get_verify_result(ssl) != X509_V_OK) - { - log_error1("Certificate did not verify"); - SSL_free(ssl); - return herror_new("hssl_client_ssl", HSSL_ERROR_CERTIFICATE, "Verfiy certificate failed"); - } */ + if (SSL_get_verify_result(ssl) != X509_V_OK) { log_error1("Certificate + did not verify"); SSL_free(ssl); return herror_new("hssl_client_ssl", + HSSL_ERROR_CERTIFICATE, "Verfiy certificate failed"); } */ + + log_verbose1("SSL client initialization completed"); - log_verbose1 ("SSL client initialization completed"); - sock->ssl = ssl; - + return H_OK; } +long +hssl_bio_read(BIO * b, char *out, int outl) +{ + + return hsocket_select_read(b->num, out, outl);; +} herror_t -hssl_server_ssl(hsocket_t *sock) +hssl_server_ssl(hsocket_t * sock) { SSL *ssl; int ret; + BIO *sbio; if (!enabled) return H_OK; @@ -428,18 +464,33 @@ hssl_server_ssl(hsocket_t *sock) if (!(ssl = SSL_new(context))) { log_warn1("SSL_new failed"); - return herror_new("hssl_server_ssl", HSSL_ERROR_SERVER, "Cannot create SSL object"); + return herror_new("hssl_server_ssl", HSSL_ERROR_SERVER, + "Cannot create SSL object"); } - SSL_set_fd(ssl, sock->sock); + /* SSL_set_fd(ssl, sock->sock); */ + + sbio = BIO_new_socket(sock->sock, BIO_NOCLOSE); + + if (sbio == NULL) + { + log_error1("BIO_new_socket failed"); + return NULL; + } + // BIO_set_callback(sbio, hssl_bio_cb); + sbio->method->bread = hssl_bio_read; + SSL_set_bio(ssl, sbio, sbio); + if ((ret = SSL_accept(ssl)) <= 0) { herror_t err; - log_error2 ("SSL_accept failed (%s)", _hssl_get_error(ssl, ret)); + log_error2("SSL_accept failed (%s)", _hssl_get_error(ssl, ret)); - err = herror_new("hssl_server_ssl", HSSL_ERROR_SERVER, "SSL_accept failed (%s)", _hssl_get_error(ssl, ret)); - SSL_free (ssl); + err = + herror_new("hssl_server_ssl", HSSL_ERROR_SERVER, + "SSL_accept failed (%s)", _hssl_get_error(ssl, ret)); + SSL_free(ssl); return err; } @@ -451,21 +502,20 @@ hssl_server_ssl(hsocket_t *sock) void -hssl_cleanup(hsocket_t *sock) +hssl_cleanup(hsocket_t * sock) { if (sock->ssl) { - SSL_shutdown (sock->ssl); - SSL_free (sock->ssl); + SSL_shutdown(sock->ssl); + SSL_free(sock->ssl); sock->ssl = NULL; } return; } - herror_t -hssl_read(hsocket_t *sock, char *buf, size_t len, size_t *received) +hssl_read(hsocket_t * sock, char *buf, size_t len, size_t * received) { int count; @@ -474,12 +524,15 @@ hssl_read(hsocket_t *sock, char *buf, size_t len, size_t *received) if (sock->ssl) { if ((count = SSL_read(sock->ssl, buf, len)) == -1) - return herror_new("SSL_read", HSOCKET_ERROR_RECEIVE, "SSL_read failed (%s)", _hssl_get_error(sock->ssl, count)); + return herror_new("SSL_read", HSOCKET_ERROR_RECEIVE, + "SSL_read failed (%s)", _hssl_get_error(sock->ssl, + count)); } else { - if ((count = recv(sock->sock, buf, len, 0)) == -1) - return herror_new("hssl_read", HSOCKET_ERROR_RECEIVE, "recv failed (%s)", strerror(errno)); + if ((count = hsocket_select_read(sock->sock, buf, len)) == -1) + return herror_new("hssl_read", HSOCKET_ERROR_RECEIVE, + "recv failed (%s)", strerror(errno)); } *received = count; @@ -488,7 +541,7 @@ hssl_read(hsocket_t *sock, char *buf, size_t len, size_t *received) herror_t -hssl_write(hsocket_t *sock, const char *buf, size_t len, size_t *sent) +hssl_write(hsocket_t * sock, const char *buf, size_t len, size_t * sent) { int count; @@ -497,12 +550,15 @@ hssl_write(hsocket_t *sock, const char *buf, size_t len, size_t *sent) if (sock->ssl) { if ((count = SSL_write(sock->ssl, buf, len)) == -1) - return herror_new("SSL_write", HSOCKET_ERROR_SEND, "SSL_write failed (%s)", _hssl_get_error(sock->ssl, count)); + return herror_new("SSL_write", HSOCKET_ERROR_SEND, + "SSL_write failed (%s)", _hssl_get_error(sock->ssl, + count)); } else { if ((count = send(sock->sock, buf, len, 0)) == -1) - return herror_new("hssl_write", HSOCKET_ERROR_SEND, "send failed (%s)", strerror(errno)); + return herror_new("hssl_write", HSOCKET_ERROR_SEND, "send failed (%s)", + strerror(errno)); } *sent = count; @@ -512,24 +568,26 @@ hssl_write(hsocket_t *sock, const char *buf, size_t len, size_t *sent) #else herror_t -hssl_read(hsocket_t *sock, char *buf, size_t len, size_t *received) +hssl_read(hsocket_t * sock, char *buf, size_t len, size_t * received) { int count; - if ((count = recv(sock->sock, buf, len, 0)) == -1) - return herror_new("hssl_read", HSOCKET_ERROR_RECEIVE, "recv failed (%s)", strerror(errno)); + if ((count = hsocket_select_read(sock->sock, buf, len)) == -1) + return herror_new("hssl_read", HSOCKET_ERROR_RECEIVE, "recv failed (%s)", + strerror(errno)); *received = count; return H_OK; } herror_t -hssl_write(hsocket_t *sock, const char *buf, size_t len, size_t *sent) +hssl_write(hsocket_t * sock, const char *buf, size_t len, size_t * sent) { int count; if ((count = send(sock->sock, buf, len, 0)) == -1) - return herror_new("hssl_write", HSOCKET_ERROR_SEND, "send failed (%s)", strerror(errno)); + return herror_new("hssl_write", HSOCKET_ERROR_SEND, "send failed (%s)", + strerror(errno)); *sent = count; return H_OK; } |