diff options
author | Darren Krahn <dkrahn@google.com> | 2015-08-13 17:01:56 -0700 |
---|---|---|
committer | Darren Krahn <dkrahn@google.com> | 2015-08-18 13:08:44 -0700 |
commit | 98eba18fb11e5d2d4f7cdadd03c24f69ee2bd32e (patch) | |
tree | 344b95b6b6d09dd829974a6b73e4a9121d8eadbe | |
parent | 3b641bc5341bd35a4b798224d4c637c65d78ada0 (diff) | |
download | libmicrohttpd-98eba18fb11e5d2d4f7cdadd03c24f69ee2bd32e.tar.gz |
Add HTTPS support using BoringSSL.
Upstream implements HTTPS using GnuTLS but BoringSSL is preferred. This
CL removes all use of GnuTLS in src/microhttpd and implements HTTPS with
BoringSSL.
Bug: 23153045
Change-Id: Ibbe17e5e7b87fee32832bda30591f93ff023a807
-rw-r--r-- | Android.mk | 4 | ||||
-rw-r--r-- | MHD_config.h | 18 | ||||
-rw-r--r-- | src/include/microhttpd.h | 28 | ||||
-rw-r--r-- | src/microhttpd/connection.c | 8 | ||||
-rw-r--r-- | src/microhttpd/connection_https.c | 16 | ||||
-rw-r--r-- | src/microhttpd/daemon.c | 564 | ||||
-rw-r--r-- | src/microhttpd/internal.h | 55 |
7 files changed, 313 insertions, 380 deletions
@@ -24,11 +24,15 @@ LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/src/include LOCAL_C_INCLUDES := \ $(LOCAL_PATH)/src/include \ $(LOCAL_PATH)/src/microhttpd \ + external/boringssl/include \ + +LOCAL_SHARED_LIBRARIES := libssl libcrypto LOCAL_SRC_FILES := \ src/microhttpd/base64.c \ src/microhttpd/basicauth.c \ src/microhttpd/connection.c \ + src/microhttpd/connection_https.c \ src/microhttpd/daemon.c \ src/microhttpd/digestauth.c \ src/microhttpd/internal.c \ diff --git a/MHD_config.h b/MHD_config.h index d439b527..185ea3be 100644 --- a/MHD_config.h +++ b/MHD_config.h @@ -58,7 +58,7 @@ #define HAVE_FSEEKO 1 /* Define to 1 if you have the <gcrypt.h> header file. */ -#define HAVE_GCRYPT_H 1 +/* #undef HAVE_GCRYPT_H */ /* Define to 1 if you have `gmtime_s' function (only for W32). */ /* #undef HAVE_GMTIME_S */ @@ -109,25 +109,25 @@ #define HAVE_NETINET_TCP_H 1 /* Define to 1 if you have the <openssl/engine.h> header file. */ -/* #undef HAVE_OPENSSL_ENGINE_H */ +#define HAVE_OPENSSL_ENGINE_H 1 /* Define to 1 if you have the <openssl/err.h> header file. */ -/* #undef HAVE_OPENSSL_ERR_H */ +#define HAVE_OPENSSL_ERR_H 1 /* Define to 1 if you have the <openssl/evp.h> header file. */ -/* #undef HAVE_OPENSSL_EVP_H */ +#define HAVE_OPENSSL_EVP_H 1 /* Define to 1 if you have the <openssl/pem.h> header file. */ -/* #undef HAVE_OPENSSL_PEM_H */ +#define HAVE_OPENSSL_PEM_H 1 /* Define to 1 if you have the <openssl/rand.h> header file. */ -/* #undef HAVE_OPENSSL_RAND_H */ +#define HAVE_OPENSSL_RAND_H 1 /* Define to 1 if you have the <openssl/rsa.h> header file. */ -/* #undef HAVE_OPENSSL_RSA_H */ +#define HAVE_OPENSSL_RSA_H 1 /* Define to 1 if you have the <openssl/sha.h> header file. */ -/* #undef HAVE_OPENSSL_SHA_H */ +#define HAVE_OPENSSL_SHA_H 1 /* Define to 1 if you have the `poll' function. */ #define HAVE_POLL 1 @@ -208,7 +208,7 @@ /* #undef HAVE_WS2TCPIP_H */ /* disable HTTPS support */ -#define HTTPS_SUPPORT 0 +#define HTTPS_SUPPORT 1 /* Defined if libcurl supports AsynchDNS */ /* #undef LIBCURL_FEATURE_ASYNCHDNS */ diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h index ca3bb869..b4ee0b70 100644 --- a/src/include/microhttpd.h +++ b/src/include/microhttpd.h @@ -1048,14 +1048,14 @@ union MHD_ConnectionInfo { /** - * Cipher algorithm used, of type "enum gnutls_cipher_algorithm". + * Cipher algorithm used, as a string. */ - int /* enum gnutls_cipher_algorithm */ cipher_algorithm; + const char* cipher_algorithm; /** - * Protocol used, of type "enum gnutls_protocol". + * Protocol used, as a string. */ - int /* enum gnutls_protocol */ protocol; + const char* protocol; /** * Connect socket @@ -1063,14 +1063,14 @@ union MHD_ConnectionInfo MHD_socket connect_fd; /** - * GNUtls session handle, of type "gnutls_session_t". + * TLS session handle, of type "SSL". */ - void * /* gnutls_session_t */ tls_session; + void * /* SSL */ tls_session; /** - * GNUtls client certificate handle, of type "gnutls_x509_crt_t". + * TLS client certificate handle, of type "X509". */ - void * /* gnutls_x509_crt_t */ client_cert; + void * /* X509 */ client_cert; /** * Address information for the client. @@ -1122,18 +1122,18 @@ enum MHD_ConnectionInfoType MHD_CONNECTION_INFO_CLIENT_ADDRESS, /** - * Get the gnuTLS session handle. + * Get the TLS session handle. * @ingroup request */ - MHD_CONNECTION_INFO_GNUTLS_SESSION, + MHD_CONNECTION_INFO_TLS_SESSION, /** * Get the gnuTLS client certificate handle. Dysfunctional (never - * implemented, deprecated). Use #MHD_CONNECTION_INFO_GNUTLS_SESSION - * to get the `gnutls_session_t` and then call - * gnutls_certificate_get_peers(). + * implemented, deprecated). Use #MHD_CONNECTION_INFO_TLS_SESSION + * to get the `SSL` and then call + * SSL_get_peer_certificate() or SSL_get_peer_cert_chain(). */ - MHD_CONNECTION_INFO_GNUTLS_CLIENT_CERT, + MHD_CONNECTION_INFO_TLS_CLIENT_CERT, /** * Get the `struct MHD_Daemon *` responsible for managing this connection. diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c index 785fafdc..ff57ac45 100644 --- a/src/microhttpd/connection.c +++ b/src/microhttpd/connection.c @@ -988,7 +988,7 @@ MHD_connection_update_event_loop_info (struct MHD_Connection *connection) { #if HTTPS_SUPPORT case MHD_TLS_CONNECTION_INIT: - if (0 == gnutls_record_get_direction (connection->tls_session)) + if (SSL_want_read (connection->tls_session)) connection->event_loop_info = MHD_EVENT_LOOP_INFO_READ; else connection->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE; @@ -2781,14 +2781,14 @@ MHD_get_connection_info (struct MHD_Connection *connection, case MHD_CONNECTION_INFO_CIPHER_ALGO: if (connection->tls_session == NULL) return NULL; - connection->cipher = gnutls_cipher_get (connection->tls_session); + connection->cipher = SSL_CIPHER_get_name (SSL_get_current_cipher (connection->tls_session)); return (const union MHD_ConnectionInfo *) &connection->cipher; case MHD_CONNECTION_INFO_PROTOCOL: if (connection->tls_session == NULL) return NULL; - connection->protocol = gnutls_protocol_get_version (connection->tls_session); + connection->protocol = SSL_CIPHER_get_version (SSL_get_current_cipher (connection->tls_session)); return (const union MHD_ConnectionInfo *) &connection->protocol; - case MHD_CONNECTION_INFO_GNUTLS_SESSION: + case MHD_CONNECTION_INFO_TLS_SESSION: if (connection->tls_session == NULL) return NULL; return (const union MHD_ConnectionInfo *) &connection->tls_session; diff --git a/src/microhttpd/connection_https.c b/src/microhttpd/connection_https.c index 834d52e0..83c28143 100644 --- a/src/microhttpd/connection_https.c +++ b/src/microhttpd/connection_https.c @@ -31,7 +31,7 @@ #include "memorypool.h" #include "response.h" #include "reason_phrase.h" -#include <gnutls/gnutls.h> +#include <openssl/ssl.h> /** @@ -46,19 +46,19 @@ static int run_tls_handshake (struct MHD_Connection *connection) { int ret; - connection->last_activity = MHD_monotonic_time(); if (connection->state == MHD_TLS_CONNECTION_INIT) { - ret = gnutls_handshake (connection->tls_session); - if (ret == GNUTLS_E_SUCCESS) + ret = SSL_accept (connection->tls_session); + if (ret == 1) { /* set connection state to enable HTTP processing */ connection->state = MHD_CONNECTION_INIT; return MHD_YES; } - if ( (ret == GNUTLS_E_AGAIN) || - (ret == GNUTLS_E_INTERRUPTED) ) + int error = SSL_get_error (connection->tls_session, ret); + if ( (error == SSL_ERROR_WANT_READ) || + (error == SSL_ERROR_WANT_WRITE) ) { /* handshake not done */ return MHD_YES; @@ -150,10 +150,10 @@ MHD_tls_connection_handle_idle (struct MHD_Connection *connection) break; /* close connection if necessary */ case MHD_CONNECTION_CLOSED: - gnutls_bye (connection->tls_session, GNUTLS_SHUT_RDWR); + SSL_shutdown (connection->tls_session); return MHD_connection_handle_idle (connection); default: - if ( (0 != gnutls_record_check_pending (connection->tls_session)) && + if ( (0 != SSL_pending (connection->tls_session)) && (MHD_YES != MHD_tls_connection_handle_read (connection)) ) return MHD_YES; return MHD_connection_handle_idle (connection); diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c index 1aa7d8d3..40059cfe 100644 --- a/src/microhttpd/daemon.c +++ b/src/microhttpd/daemon.c @@ -47,7 +47,7 @@ #if HTTPS_SUPPORT #include "connection_https.h" -#include <gcrypt.h> +#include <openssl/ssl.h> #endif #if defined(HAVE_POLL_H) && defined(HAVE_POLL) @@ -415,6 +415,92 @@ MHD_ip_limit_del (struct MHD_Daemon *daemon, #if HTTPS_SUPPORT + +static ssize_t +recv_param_adapter (struct MHD_Connection *connection, + void *other, + size_t i); +static ssize_t +send_param_adapter (struct MHD_Connection *connection, + const void *other, + size_t i); + +// Internal functions for implementing OpenSSL BIO. +static int +MHD_bio_write (BIO* bio, const char* buf, int size) +{ + struct MHD_Connection* connection = (struct MHD_Connection*)bio->ptr; + BIO_clear_retry_flags (bio); + ssize_t written = send_param_adapter (connection, buf, size); + if (written < size) + { + BIO_set_retry_write (bio); + } + return written; +} + +static int +MHD_bio_read (BIO* bio, char* buf, int size) +{ + struct MHD_Connection* connection = (struct MHD_Connection*)bio->ptr; + BIO_clear_retry_flags (bio); + ssize_t read = recv_param_adapter (connection, buf, size); + if (read < size) + { + BIO_set_retry_read (bio); + } + return read; +} + +static long +MHD_bio_ctrl (BIO* bio, int cmd, long num, void* ptr) +{ + if (cmd == BIO_CTRL_FLUSH) + { + return 1; + } + return 0; +} + +static int +MHD_bio_new (BIO* bio) +{ + bio->shutdown = 0; + bio->init = 0; + bio->num = -1; // not used. + return 1; +} + +static int +MHD_bio_free (BIO* bio) +{ + if (!bio) + return 0; + + if (bio->init) + { + bio->ptr = NULL; + bio->init = 0; + } + return 1; +} + +// Describes a BIO built on [send|recv]_param_adapter(). +BIO_METHOD MHD_bio_method = +{ + BIO_TYPE_SOURCE_SINK, + "mhd", // name + MHD_bio_write, // write function + MHD_bio_read, // read function + NULL, // puts function, not implemented + NULL, // gets function, not implemented + MHD_bio_ctrl, // control function + MHD_bio_new, // creation + MHD_bio_free, // free + NULL, // callback function, not used +}; + + /** * Callback for receiving data from the socket. * @@ -433,9 +519,8 @@ recv_tls_adapter (struct MHD_Connection *connection, void *other, size_t i) connection->daemon->num_tls_read_ready--; connection->tls_read_ready = MHD_NO; } - res = gnutls_record_recv (connection->tls_session, other, i); - if ( (GNUTLS_E_AGAIN == res) || - (GNUTLS_E_INTERRUPTED == res) ) + res = SSL_read (connection->tls_session, other, i); + if ( res < 0 && SSL_want_read (connection->tls_session) ) { MHD_set_socket_errno_ (EINTR); #if EPOLL_SUPPORT @@ -474,9 +559,8 @@ send_tls_adapter (struct MHD_Connection *connection, { int res; - res = gnutls_record_send (connection->tls_session, other, i); - if ( (GNUTLS_E_AGAIN == res) || - (GNUTLS_E_INTERRUPTED == res) ) + res = SSL_write (connection->tls_session, other, i); + if ( res < 0 && SSL_want_write (connection->tls_session) ) { MHD_set_socket_errno_ (EINTR); #if EPOLL_SUPPORT @@ -498,118 +582,148 @@ send_tls_adapter (struct MHD_Connection *connection, /** - * Read and setup our certificate and key. + * Initialize security aspects of the HTTPS daemon * * @param daemon handle to daemon to initialize * @return 0 on success */ static int -MHD_init_daemon_certificate (struct MHD_Daemon *daemon) +MHD_TLS_init (struct MHD_Daemon *daemon) { - gnutls_datum_t key; - gnutls_datum_t cert; int ret; - -#if GNUTLS_VERSION_MAJOR >= 3 - if (NULL != daemon->cert_callback) - { - gnutls_certificate_set_retrieve_function2 (daemon->x509_cred, - daemon->cert_callback); - } -#endif + daemon->tls_context = SSL_CTX_new (TLSv1_2_server_method()); + if (NULL == daemon->tls_context) + return -1; if (NULL != daemon->https_mem_trust) { - cert.data = (unsigned char *) daemon->https_mem_trust; - cert.size = strlen (daemon->https_mem_trust); - if (gnutls_certificate_set_x509_trust_mem (daemon->x509_cred, &cert, - GNUTLS_X509_FMT_PEM) < 0) - { + ret = 0; + BIO* mem_bio = BIO_new_mem_buf ((void*)daemon->https_mem_trust, -1); + X509* x509 = PEM_read_bio_X509 (mem_bio, NULL, NULL, NULL); + BIO_free(mem_bio); + if (x509 != NULL) + { + ret = SSL_CTX_add_client_CA (daemon->tls_context, x509); + } + if (ret == 0) + { #if HAVE_MESSAGES - MHD_DLOG(daemon, - "Bad trust certificate format\n"); + MHD_DLOG (daemon, + "Bad trust certificate format\n"); #endif - return -1; - } + return -1; + } } - if (MHD_YES == daemon->have_dhparams) + if (NULL != daemon->https_mem_dhparams) { - gnutls_certificate_set_dh_params (daemon->x509_cred, - daemon->https_mem_dhparams); + ret = 0; + BIO* mem_bio = BIO_new_mem_buf ((void*)daemon->https_mem_dhparams, -1); + DH* dh = PEM_read_bio_DHparams (mem_bio, NULL, NULL, NULL); + BIO_free (mem_bio); + if (dh != NULL) + { + ret = SSL_CTX_set_tmp_dh (daemon->tls_context, dh); + } + if (ret == 0) + { +#if HAVE_MESSAGES + MHD_DLOG (daemon, + "Bad DH parameters format\n"); +#endif + return -1; + } } + /* certificate & key loaded from memory */ if ( (NULL != daemon->https_mem_cert) && (NULL != daemon->https_mem_key) ) { - key.data = (unsigned char *) daemon->https_mem_key; - key.size = strlen (daemon->https_mem_key); - cert.data = (unsigned char *) daemon->https_mem_cert; - cert.size = strlen (daemon->https_mem_cert); - - if (NULL != daemon->https_key_password) { -#if GNUTLS_VERSION_NUMBER >= 0x030111 - ret = gnutls_certificate_set_x509_key_mem2 (daemon->x509_cred, - &cert, &key, - GNUTLS_X509_FMT_PEM, - daemon->https_key_password, - 0); -#else + ret = 0; + BIO* mem_bio = BIO_new_mem_buf ((void*)daemon->https_mem_key, -1); + EVP_PKEY* key = PEM_read_bio_PrivateKey (mem_bio, NULL, NULL, + (void*)daemon->https_key_password); + BIO_free (mem_bio); + if (key != NULL) + { + ret = SSL_CTX_use_PrivateKey (daemon->tls_context, key); + } + if (ret == 0) + { #if HAVE_MESSAGES - MHD_DLOG (daemon, - "Failed to setup x509 certificate/key: pre 3.X.X version " \ - "of GnuTLS does not support setting key password"); + MHD_DLOG (daemon, + "Bad private key format\n"); #endif - return -1; + return -1; + } + ret = 0; + mem_bio = BIO_new_mem_buf ((void*)daemon->https_mem_cert, -1); + X509* x509 = PEM_read_bio_X509 (mem_bio, NULL, NULL, NULL); + BIO_free (mem_bio); + if (x509 != NULL) + { + ret = SSL_CTX_use_certificate (daemon->tls_context, x509); + } + if (ret == 0) + { +#if HAVE_MESSAGES + MHD_DLOG (daemon, + "Bad certificate format\n"); #endif - } - else - ret = gnutls_certificate_set_x509_key_mem (daemon->x509_cred, - &cert, &key, - GNUTLS_X509_FMT_PEM); + return -1; + } + if (1 != SSL_CTX_check_private_key (daemon->tls_context)) + { #if HAVE_MESSAGES - if (0 != ret) - MHD_DLOG (daemon, - "GnuTLS failed to setup x509 certificate/key: %s\n", - gnutls_strerror (ret)); + MHD_DLOG (daemon, + "Invalid key / certificate combination\n"); #endif - return ret; + return -1; + } } -#if GNUTLS_VERSION_MAJOR >= 3 - if (NULL != daemon->cert_callback) - return 0; + else + { +#if HAVE_MESSAGES + MHD_DLOG (daemon, + "You need to specify a certificate and key location\n"); #endif + return -1; + } + if (NULL != daemon->https_mem_cipher) + { + ret = SSL_CTX_set_cipher_list (daemon->tls_context, + daemon->https_mem_cipher); + if (ret == 0) + { #if HAVE_MESSAGES - MHD_DLOG (daemon, - "You need to specify a certificate and key location\n"); + MHD_DLOG (daemon, + "Bad cipher string format\n"); #endif - return -1; -} - - -/** - * Initialize security aspects of the HTTPS daemon - * - * @param daemon handle to daemon to initialize - * @return 0 on success - */ -static int -MHD_TLS_init (struct MHD_Daemon *daemon) -{ - switch (daemon->cred_type) + return -1; + } + } + else { - case GNUTLS_CRD_CERTIFICATE: - if (0 != - gnutls_certificate_allocate_credentials (&daemon->x509_cred)) - return GNUTLS_E_MEMORY_ERROR; - return MHD_init_daemon_certificate (daemon); - default: + ret = SSL_CTX_set_cipher_list (daemon->tls_context, + "ECDHE-ECDSA-AES128-GCM-SHA256:" + "ECDHE-ECDSA-AES256-GCM-SHA384:" + "ECDHE-RSA-AES128-GCM-SHA256:" + "ECDHE-RSA-AES256-GCM-SHA384"); + if (ret == 0) + { #if HAVE_MESSAGES - MHD_DLOG (daemon, - "Error: invalid credentials type %d specified.\n", - daemon->cred_type); + MHD_DLOG (daemon, + "Failed to setup default cipher string\n"); #endif - return -1; + return -1; + } } + return 0; +} + +static void +MHD_TLS_deinit (struct MHD_Daemon *daemon) +{ + SSL_CTX_free (daemon->tls_context); } #endif @@ -1450,44 +1564,15 @@ internal_add_connection (struct MHD_Daemon *daemon, connection->send_cls = &send_tls_adapter; connection->state = MHD_TLS_CONNECTION_INIT; MHD_set_https_callbacks (connection); - gnutls_init (&connection->tls_session, GNUTLS_SERVER); - gnutls_priority_set (connection->tls_session, - daemon->priority_cache); - switch (daemon->cred_type) + connection->tls_session = SSL_new (daemon->tls_context); + BIO* bio = BIO_new (&MHD_bio_method); + if (bio) { - /* set needed credentials for certificate authentication. */ - case GNUTLS_CRD_CERTIFICATE: - gnutls_credentials_set (connection->tls_session, - GNUTLS_CRD_CERTIFICATE, - daemon->x509_cred); - break; - default: -#if HAVE_MESSAGES - MHD_DLOG (connection->daemon, - "Failed to setup TLS credentials: unknown credential type %d\n", - daemon->cred_type); -#endif - if (0 != MHD_socket_close_ (client_socket)) - MHD_PANIC ("close failed\n"); - MHD_ip_limit_del (daemon, addr, addrlen); - free (connection->addr); - free (connection); - MHD_PANIC ("Unknown credential type"); -#if EINVAL - errno = EINVAL; -#endif - return MHD_NO; + bio->ptr = connection; + bio->init = 1; } - gnutls_transport_set_ptr (connection->tls_session, - (gnutls_transport_ptr_t) connection); - gnutls_transport_set_pull_function (connection->tls_session, - (gnutls_pull_func) &recv_param_adapter); - gnutls_transport_set_push_function (connection->tls_session, - (gnutls_push_func) &send_param_adapter); - - if (daemon->https_mem_trust) - gnutls_certificate_server_set_request (connection->tls_session, - GNUTLS_CERT_REQUEST); + SSL_set_bio (connection->tls_session, bio, bio); + SSL_set_app_data (connection->tls_session, connection); } #endif @@ -2000,7 +2085,7 @@ MHD_cleanup_connections (struct MHD_Daemon *daemon) MHD_pool_destroy (pos->pool); #if HTTPS_SUPPORT if (NULL != pos->tls_session) - gnutls_deinit (pos->tls_session); + SSL_free (pos->tls_session); #endif if (NULL != daemon->notify_connection) daemon->notify_connection (daemon->notify_connection_cls, @@ -2111,7 +2196,7 @@ MHD_get_timeout (struct MHD_Daemon *daemon, earliest_deadline = pos->last_activity + pos->connection_timeout; #if HTTPS_SUPPORT if ( (0 != (daemon->options & MHD_USE_SSL)) && - (0 != gnutls_record_check_pending (pos->tls_session)) ) + (0 != SSL_pending (pos->tls_session)) ) earliest_deadline = 0; #endif have_timeout = MHD_YES; @@ -2127,7 +2212,7 @@ MHD_get_timeout (struct MHD_Daemon *daemon, earliest_deadline = pos->last_activity + pos->connection_timeout; #if HTTPS_SUPPORT if ( (0 != (daemon->options & MHD_USE_SSL)) && - (0 != gnutls_record_check_pending (pos->tls_session)) ) + (0 != SSL_pending (pos->tls_session)) ) earliest_deadline = 0; #endif have_timeout = MHD_YES; @@ -2189,11 +2274,11 @@ MHD_run_from_select (struct MHD_Daemon *daemon, /* select connection thread handling type */ if ( (MHD_INVALID_SOCKET != (ds = daemon->socket_fd)) && - (FD_ISSET (ds, read_fd_set)) ) + (FD_ISSET (ds, (fd_set*)read_fd_set)) ) (void) MHD_accept_connection (daemon); /* drain signaling pipe to avoid spinning select */ if ( (MHD_INVALID_PIPE_ != daemon->wpipe[0]) && - (FD_ISSET (daemon->wpipe[0], read_fd_set)) ) + (FD_ISSET (daemon->wpipe[0], (fd_set*)read_fd_set)) ) (void) MHD_pipe_read_ (daemon->wpipe[0], &tmp, sizeof (tmp)); if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) @@ -2209,7 +2294,7 @@ MHD_run_from_select (struct MHD_Daemon *daemon, switch (pos->event_loop_info) { case MHD_EVENT_LOOP_INFO_READ: - if ( (FD_ISSET (ds, read_fd_set)) + if ( (FD_ISSET (ds, (fd_set*)read_fd_set)) #if HTTPS_SUPPORT || (MHD_YES == pos->tls_read_ready) #endif @@ -2217,14 +2302,14 @@ MHD_run_from_select (struct MHD_Daemon *daemon, pos->read_handler (pos); break; case MHD_EVENT_LOOP_INFO_WRITE: - if ( (FD_ISSET (ds, read_fd_set)) && + if ( (FD_ISSET (ds, (fd_set*)read_fd_set)) && (pos->read_buffer_size > pos->read_buffer_offset) ) pos->read_handler (pos); - if (FD_ISSET (ds, write_fd_set)) + if (FD_ISSET (ds, (fd_set*)write_fd_set)) pos->write_handler (pos); break; case MHD_EVENT_LOOP_INFO_BLOCK: - if ( (FD_ISSET (ds, read_fd_set)) && + if ( (FD_ISSET (ds, (fd_set*)read_fd_set)) && (pos->read_buffer_size > pos->read_buffer_offset) ) pos->read_handler (pos); break; @@ -3150,118 +3235,93 @@ parse_options_va (struct MHD_Daemon *daemon, #if HTTPS_SUPPORT case MHD_OPTION_HTTPS_MEM_KEY: if (0 != (daemon->options & MHD_USE_SSL)) - daemon->https_mem_key = va_arg (ap, const char *); -#if HAVE_MESSAGES + { + daemon->https_mem_key = va_arg (ap, const char *); + } else + { +#if HAVE_MESSAGES MHD_DLOG (daemon, "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n", opt); #endif + } break; case MHD_OPTION_HTTPS_KEY_PASSWORD: if (0 != (daemon->options & MHD_USE_SSL)) - daemon->https_key_password = va_arg (ap, const char *); -#if HAVE_MESSAGES + { + daemon->https_key_password = va_arg (ap, const char *); + } else + { +#if HAVE_MESSAGES MHD_DLOG (daemon, "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n", opt); #endif + } break; case MHD_OPTION_HTTPS_MEM_CERT: if (0 != (daemon->options & MHD_USE_SSL)) - daemon->https_mem_cert = va_arg (ap, const char *); -#if HAVE_MESSAGES + { + daemon->https_mem_cert = va_arg (ap, const char *); + } else + { +#if HAVE_MESSAGES MHD_DLOG (daemon, "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n", opt); #endif + } break; case MHD_OPTION_HTTPS_MEM_TRUST: if (0 != (daemon->options & MHD_USE_SSL)) - daemon->https_mem_trust = va_arg (ap, const char *); -#if HAVE_MESSAGES + { + daemon->https_mem_trust = va_arg (ap, const char *); + } else + { +#if HAVE_MESSAGES MHD_DLOG (daemon, "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n", opt); #endif + } break; case MHD_OPTION_HTTPS_CRED_TYPE: - daemon->cred_type = (gnutls_credentials_type_t) va_arg (ap, int); break; case MHD_OPTION_HTTPS_MEM_DHPARAMS: - if (0 != (daemon->options & MHD_USE_SSL)) - { - const char *arg = va_arg (ap, const char *); - gnutls_datum_t dhpar; - - if (gnutls_dh_params_init (&daemon->https_mem_dhparams) < 0) - { -#if HAVE_MESSAGES - MHD_DLOG(daemon, - "Error initializing DH parameters\n"); -#endif - return MHD_NO; - } - dhpar.data = (unsigned char *) arg; - dhpar.size = strlen (arg); - if (gnutls_dh_params_import_pkcs3 (daemon->https_mem_dhparams, &dhpar, - GNUTLS_X509_FMT_PEM) < 0) - { -#if HAVE_MESSAGES - MHD_DLOG(daemon, - "Bad Diffie-Hellman parameters format\n"); -#endif - gnutls_dh_params_deinit (daemon->https_mem_dhparams); - return MHD_NO; - } - daemon->have_dhparams = MHD_YES; - } - else - { + if (0 != (daemon->options & MHD_USE_SSL)) + { + daemon->https_mem_dhparams = va_arg (ap, const char *); + } + else + { #if HAVE_MESSAGES - MHD_DLOG (daemon, - "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n", - opt); + MHD_DLOG (daemon, + "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n", + opt); #endif - return MHD_NO; - } + } break; case MHD_OPTION_HTTPS_PRIORITIES: if (0 != (daemon->options & MHD_USE_SSL)) { - gnutls_priority_deinit (daemon->priority_cache); - ret = gnutls_priority_init (&daemon->priority_cache, - pstr = va_arg (ap, const char*), - NULL); - if (GNUTLS_E_SUCCESS != ret) - { + daemon->https_mem_cipher = va_arg (ap, const char *); + } + else + { #if HAVE_MESSAGES - MHD_DLOG (daemon, - "Setting priorities to `%s' failed: %s\n", - pstr, - gnutls_strerror (ret)); -#endif - daemon->priority_cache = NULL; - return MHD_NO; - } + MHD_DLOG (daemon, + "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n", + opt); +#endif } break; case MHD_OPTION_HTTPS_CERT_CALLBACK: -#if GNUTLS_VERSION_MAJOR < 3 -#if HAVE_MESSAGES - MHD_DLOG (daemon, - "MHD_OPTION_HTTPS_CERT_CALLBACK requires building MHD with GnuTLS >= 3.0\n"); -#endif - return MHD_NO; -#else - if (0 != (daemon->options & MHD_USE_SSL)) - daemon->cert_callback = va_arg (ap, gnutls_certificate_retrieve_function2 *); break; #endif -#endif #ifdef DAUTH_SUPPORT case MHD_OPTION_DIGEST_AUTH_RANDOM: daemon->digest_auth_rand_size = va_arg (ap, size_t); @@ -3600,14 +3660,6 @@ MHD_start_daemon_va (unsigned int flags, daemon->epoll_fd = -1; #endif /* try to open listen socket */ -#if HTTPS_SUPPORT - if (0 != (flags & MHD_USE_SSL)) - { - gnutls_priority_init (&daemon->priority_cache, - "NORMAL", - NULL); - } -#endif daemon->socket_fd = MHD_INVALID_SOCKET; daemon->listening_address_reuse = 0; daemon->options = flags; @@ -3672,21 +3724,10 @@ MHD_start_daemon_va (unsigned int flags, daemon->digest_auth_random = NULL; daemon->nonce_nc_size = 4; /* tiny */ #endif -#if HTTPS_SUPPORT - if (0 != (flags & MHD_USE_SSL)) - { - daemon->cred_type = GNUTLS_CRD_CERTIFICATE; - } -#endif if (MHD_YES != parse_options_va (daemon, &servaddr, ap)) { -#if HTTPS_SUPPORT - if ( (0 != (flags & MHD_USE_SSL)) && - (NULL != daemon->priority_cache) ) - gnutls_priority_deinit (daemon->priority_cache); -#endif free (daemon); return NULL; } @@ -3700,10 +3741,6 @@ MHD_start_daemon_va (unsigned int flags, MHD_DLOG (daemon, "Specified value for NC_SIZE too large\n"); #endif -#if HTTPS_SUPPORT - if (0 != (flags & MHD_USE_SSL)) - gnutls_priority_deinit (daemon->priority_cache); -#endif free (daemon); return NULL; } @@ -3715,10 +3752,6 @@ MHD_start_daemon_va (unsigned int flags, "Failed to allocate memory for nonce-nc map: %s\n", MHD_strerror_ (errno)); #endif -#if HTTPS_SUPPORT - if (0 != (flags & MHD_USE_SSL)) - gnutls_priority_deinit (daemon->priority_cache); -#endif free (daemon); return NULL; } @@ -3730,10 +3763,6 @@ MHD_start_daemon_va (unsigned int flags, MHD_DLOG (daemon, "MHD failed to initialize nonce-nc mutex\n"); #endif -#if HTTPS_SUPPORT - if (0 != (flags & MHD_USE_SSL)) - gnutls_priority_deinit (daemon->priority_cache); -#endif free (daemon->nnc); free (daemon); return NULL; @@ -4280,10 +4309,6 @@ thread_failed: free (daemon->nnc); (void) MHD_mutex_destroy_ (&daemon->nnc_lock); #endif -#if HTTPS_SUPPORT - if (0 != (flags & MHD_USE_SSL)) - gnutls_priority_deinit (daemon->priority_cache); -#endif free (daemon); return NULL; } @@ -4513,16 +4538,9 @@ MHD_stop_daemon (struct MHD_Daemon *daemon) /* TLS clean up */ #if HTTPS_SUPPORT - if (MHD_YES == daemon->have_dhparams) - { - gnutls_dh_params_deinit (daemon->https_mem_dhparams); - daemon->have_dhparams = MHD_NO; - } if (0 != (daemon->options & MHD_USE_SSL)) { - gnutls_priority_deinit (daemon->priority_cache); - if (daemon->x509_cred) - gnutls_certificate_free_credentials (daemon->x509_cred); + MHD_TLS_deinit (daemon); } #endif #if EPOLL_SUPPORT @@ -4679,11 +4697,7 @@ MHD_is_feature_supported(enum MHD_FEATURE feature) return MHD_NO; #endif case MHD_FEATURE_HTTPS_CERT_CALLBACK: -#if HTTPS_SUPPORT && GNUTLS_VERSION_MAJOR >= 3 - return MHD_YES; -#else return MHD_NO; -#endif case MHD_FEATURE_IPv6: #ifdef HAVE_INET6 return MHD_YES; @@ -4745,7 +4759,7 @@ MHD_is_feature_supported(enum MHD_FEATURE feature) return MHD_NO; #endif case MHD_FEATURE_HTTPS_KEY_PASSWORD: -#if HTTPS_SUPPORT && GNUTLS_VERSION_NUMBER >= 0x030111 +#if HTTPS_SUPPORT return MHD_YES; #else return MHD_NO; @@ -4755,44 +4769,6 @@ MHD_is_feature_supported(enum MHD_FEATURE feature) } -#if HTTPS_SUPPORT && GCRYPT_VERSION_NUMBER < 0x010600 -#if defined(MHD_USE_POSIX_THREADS) -GCRY_THREAD_OPTION_PTHREAD_IMPL; -#elif defined(MHD_W32_MUTEX_) -static int gcry_w32_mutex_init (void **ppmtx) -{ - *ppmtx = malloc (sizeof (MHD_mutex_)); - - if (NULL == *ppmtx) - return ENOMEM; - - if (MHD_YES != MHD_mutex_create_ ((MHD_mutex_*)*ppmtx)) - { - free (*ppmtx); - *ppmtx = NULL; - return EPERM; - } - - return 0; -} -static int gcry_w32_mutex_destroy (void **ppmtx) - { int res = (MHD_YES == MHD_mutex_destroy_ ((MHD_mutex_*)*ppmtx)) ? 0 : 1; - free (*ppmtx); return res; } -static int gcry_w32_mutex_lock (void **ppmtx) - { return (MHD_YES == MHD_mutex_lock_ ((MHD_mutex_*)*ppmtx)) ? 0 : 1; } -static int gcry_w32_mutex_unlock (void **ppmtx) - { return (MHD_YES == MHD_mutex_unlock_ ((MHD_mutex_*)*ppmtx)) ? 0 : 1; } - -static struct gcry_thread_cbs gcry_threads_w32 = { - (GCRY_THREAD_OPTION_USER | (GCRY_THREAD_OPTION_VERSION << 8)), - NULL, gcry_w32_mutex_init, gcry_w32_mutex_destroy, - gcry_w32_mutex_lock, gcry_w32_mutex_unlock, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; - -#endif // defined(MHD_W32_MUTEX_) -#endif // HTTPS_SUPPORT && GCRYPT_VERSION_NUMBER < 0x010600 - - /** * Initialize do setup work. */ @@ -4810,29 +4786,13 @@ void MHD_init(void) MHD_PANIC ("Winsock version 2.2 is not available\n"); #endif #if HTTPS_SUPPORT -#if GCRYPT_VERSION_NUMBER < 0x010600 -#if defined(MHD_USE_POSIX_THREADS) - if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread)) - MHD_PANIC ("Failed to initialise multithreading in libgcrypt\n"); -#elif defined(MHD_W32_MUTEX_) - if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_w32)) - MHD_PANIC ("Failed to initialise multithreading in libgcrypt\n"); -#endif // defined(MHD_W32_MUTEX_) - gcry_check_version (NULL); -#else - if (NULL == gcry_check_version ("1.6.0")) - MHD_PANIC ("libgcrypt is too old. MHD was compiled for libgcrypt 1.6.0 or newer\n"); -#endif - gnutls_global_init (); + SSL_library_init(); #endif } void MHD_fini(void) { -#if HTTPS_SUPPORT - gnutls_global_deinit (); -#endif #ifdef _WIN32 if (mhd_winsock_inited_) WSACleanup(); diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h index 286aee68..fa751be9 100644 --- a/src/microhttpd/internal.h +++ b/src/microhttpd/internal.h @@ -31,10 +31,7 @@ #include "microhttpd.h" #include "platform_interface.h" #if HTTPS_SUPPORT -#include <gnutls/gnutls.h> -#if GNUTLS_VERSION_MAJOR >= 3 -#include <gnutls/abstract.h> -#endif +#include <openssl/ssl.h> #endif #if EPOLL_SUPPORT #include <sys/epoll.h> @@ -841,17 +838,17 @@ struct MHD_Connection /** * State required for HTTPS/SSL/TLS support. */ - gnutls_session_t tls_session; + SSL* tls_session; /** * Memory location to return for protocol session info. */ - int protocol; + const char* protocol; /** * Memory location to return for protocol session info. */ - int cipher; + const char* cipher; /** * Could it be that we are ready to read due to TLS buffers @@ -1193,42 +1190,14 @@ struct MHD_Daemon uint16_t port; #if HTTPS_SUPPORT + SSL_CTX* tls_context; /** - * Desired cipher algorithms. - */ - gnutls_priority_t priority_cache; - - /** - * What kind of credentials are we offering - * for SSL/TLS? - */ - gnutls_credentials_type_t cred_type; - - /** - * Server x509 credentials - */ - gnutls_certificate_credentials_t x509_cred; - - /** - * Diffie-Hellman parameters - */ - gnutls_dh_params_t dh_params; - -#if GNUTLS_VERSION_MAJOR >= 3 - /** - * Function that can be used to obtain the certificate. Needed - * for SNI support. See #MHD_OPTION_HTTPS_CERT_CALLBACK. - */ - gnutls_certificate_retrieve_function2 *cert_callback; -#endif - - /** - * Pointer to our SSL/TLS key (in ASCII) in memory. + * Pointer to our SSL/TLS key (in PEM) in memory. */ const char *https_mem_key; /** - * Pointer to our SSL/TLS certificate (in ASCII) in memory. + * Pointer to our SSL/TLS certificate (in PEM) in memory. */ const char *https_mem_cert; @@ -1238,19 +1207,19 @@ struct MHD_Daemon const char *https_key_password; /** - * Pointer to our SSL/TLS certificate authority (in ASCII) in memory. + * Pointer to our SSL/TLS certificate authority (in PEM) in memory. */ const char *https_mem_trust; /** - * Our Diffie-Hellman parameters in memory. + * Our Diffie-Hellman parameters (in PEM) in memory. */ - gnutls_dh_params_t https_mem_dhparams; + const char *https_mem_dhparams; /** - * #MHD_YES if we have initialized @e https_mem_dhparams. + * Pointer to SSL/TLS cipher string in memory. */ - int have_dhparams; + const char *https_mem_cipher; /** * For how many connections do we have 'tls_read_ready' set to MHD_YES? |