libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

commit ca3a7d621cf9582089642e159d9feb75823d0449
parent 8172eecea0e181426c4d5949e268103b22ade4f2
Author: Christian Grothoff <christian@grothoff.org>
Date:   Mon,  7 Apr 2014 11:27:18 +0000

add MHD_OPTION_HTTPS_MEM_DHPARAMS to support PFS

Diffstat:
MAUTHORS | 3++-
MChangeLog | 4++++
Mdoc/libmicrohttpd.texi | 12+++++++++++-
Msrc/include/microhttpd.h | 13++++++++++---
Msrc/microhttpd/daemon.c | 72+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Msrc/microhttpd/internal.h | 10++++++++++
6 files changed, 96 insertions(+), 18 deletions(-)

diff --git a/AUTHORS b/AUTHORS @@ -46,8 +46,9 @@ Matthew Mundell <matthew.mundell@greenbone.net> Scott Goldman <scottjg@github.com> Jared Cantwell Luke-Jr <luke@dashjr.org> -Evgeny Grin (Karlson2k) <k2k@narod.ru> Sree Harsha Totakura <sreeharsha@totakura.in> +Evgeny Grin (Karlson2k) <k2k@narod.ru> +Hani Benhabiles <kroosec@gmail.com> Documentation contributions also came from: Marco Maggi <marco.maggi-ipsu@poste.it> diff --git a/ChangeLog b/ChangeLog @@ -1,3 +1,7 @@ +Mon Apr 7 13:25:30 CEST 2014 + Add MHD_OPTION_HTTPS_MEM_DHPARAMS to allow applications + to enable PFS. -HB/CG + Tue Apr 01 07:10:23 CET 2014 Added usage of native mutex on W32. -EG diff --git a/doc/libmicrohttpd.texi b/doc/libmicrohttpd.texi @@ -360,7 +360,7 @@ for the specific platform. @section Portability to W32 libmicrohttpd in general ported well to W32. Most libmicrohttpd features -are supported. W32 do not support some functions, like epoll and +are supported. W32 do not support some functions, like epoll and corresponding MHD features are not available on W32. @@ -847,6 +847,16 @@ associate state until handshake is completed. If this option is not given the queue size is set to a default value of 10. This option must be followed by a @code{unsigned int}. +@item MHD_OPTION_HTTPS_MEM_DHPARAMS +@cindex TLS +@cindex SSL +@cindex DH +Memory pointer for the Diffie-Hellman parameters (dh.pem) to be used +by the HTTPS daemon for key exchange. This option must be followed by +a @code{const char *} argument. The argument would be a GNUtls +property string, such as ``NORMAL:+DHE-RSA''. This option is needed +to activate ciphersuites with so-called ``Perfect Forward Secrecy'' +property. @end table @end deftp diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h @@ -130,7 +130,7 @@ typedef intptr_t ssize_t; * Current version of the library. * 0x01093001 = 1.9.30-1. */ -#define MHD_VERSION 0x00093400 +#define MHD_VERSION 0x00093401 /** * MHD-internal return code for "YES". @@ -837,7 +837,14 @@ enum MHD_OPTION * resources for the SYN packet along with its DATA. This option should be * followed by an `unsigned int` argument. */ - MHD_OPTION_TCP_FASTOPEN_QUEUE_SIZE = 23 + MHD_OPTION_TCP_FASTOPEN_QUEUE_SIZE = 23, + + /** + * Memory pointer for the Diffie-Hellman parameters (dh.pem) to be used by the + * HTTPS daemon for key exchange. + * This option must be followed by a `const char *` argument. + */ + MHD_OPTION_HTTPS_MEM_DHPARAMS = 24 }; @@ -2448,7 +2455,7 @@ enum MHD_FEATURE * #MHD_destroy_post_processor, #MHD_destroy_post_processor can * be used. */ - MHD_FEATURE_POSTPROCESSOR = 13, + MHD_FEATURE_POSTPROCESSOR = 13 }; diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c @@ -520,6 +520,11 @@ MHD_init_daemon_certificate (struct MHD_Daemon *daemon) } } + if (MHD_YES == daemon->have_dhparams) + { + gnutls_certificate_set_dh_params (daemon->x509_cred, + daemon->https_mem_dhparams); + } /* certificate & key loaded from memory */ if ( (NULL != daemon->https_mem_cert) && (NULL != daemon->https_mem_key) ) @@ -2968,6 +2973,42 @@ parse_options_va (struct MHD_Daemon *daemon, 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 unsigned 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 HAVE_MESSAGES + 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)) { @@ -3706,7 +3747,7 @@ MHD_start_daemon_va (unsigned int flags, MHD_DLOG (daemon, "MHD failed to initialize IP connection limit mutex\n"); #endif - MHD_mutex_destroy_ (&daemon->cleanup_connection_mutex); + (void) MHD_mutex_destroy_ (&daemon->cleanup_connection_mutex); if ( (MHD_INVALID_SOCKET != socket_fd) && (0 != MHD_socket_close_ (socket_fd)) ) MHD_PANIC ("close failed\n"); @@ -3724,8 +3765,8 @@ MHD_start_daemon_va (unsigned int flags, if ( (MHD_INVALID_SOCKET != socket_fd) && (0 != MHD_socket_close_ (socket_fd)) ) MHD_PANIC ("close failed\n"); - MHD_mutex_destroy_ (&daemon->cleanup_connection_mutex); - MHD_mutex_destroy_ (&daemon->per_ip_connection_mutex); + (void) MHD_mutex_destroy_ (&daemon->cleanup_connection_mutex); + (void) MHD_mutex_destroy_ (&daemon->per_ip_connection_mutex); goto free_and_fail; } #endif @@ -3741,8 +3782,8 @@ MHD_start_daemon_va (unsigned int flags, "Failed to create listen thread: %s\n", MHD_strerror_ (res_thread_create)); #endif - MHD_mutex_destroy_ (&daemon->cleanup_connection_mutex); - MHD_mutex_destroy_ (&daemon->per_ip_connection_mutex); + (void) MHD_mutex_destroy_ (&daemon->cleanup_connection_mutex); + (void) MHD_mutex_destroy_ (&daemon->per_ip_connection_mutex); if ( (MHD_INVALID_SOCKET != socket_fd) && (0 != MHD_socket_close_ (socket_fd)) ) MHD_PANIC ("close failed\n"); @@ -3861,7 +3902,7 @@ MHD_start_daemon_va (unsigned int flags, #endif /* Free memory for this worker; cleanup below handles * all previously-created workers. */ - MHD_mutex_destroy_ (&d->cleanup_connection_mutex); + (void) MHD_mutex_destroy_ (&d->cleanup_connection_mutex); goto thread_failed; } } @@ -3878,8 +3919,8 @@ thread_failed: if ( (MHD_INVALID_SOCKET != socket_fd) && (0 != MHD_socket_close_ (socket_fd)) ) MHD_PANIC ("close failed\n"); - MHD_mutex_destroy_ (&daemon->cleanup_connection_mutex); - MHD_mutex_destroy_ (&daemon->per_ip_connection_mutex); + (void) MHD_mutex_destroy_ (&daemon->cleanup_connection_mutex); + (void) MHD_mutex_destroy_ (&daemon->per_ip_connection_mutex); if (NULL != daemon->worker_pool) free (daemon->worker_pool); goto free_and_fail; @@ -3902,7 +3943,7 @@ thread_failed: #endif #ifdef DAUTH_SUPPORT free (daemon->nnc); - MHD_mutex_destroy_ (&daemon->nnc_lock); + (void) MHD_mutex_destroy_ (&daemon->nnc_lock); #endif #if HTTPS_SUPPORT if (0 != (flags & MHD_USE_SSL)) @@ -4091,7 +4132,7 @@ MHD_stop_daemon (struct MHD_Daemon *daemon) if (0 != (rc = pthread_join (daemon->worker_pool[i].pid, &unused))) MHD_PANIC ("Failed to join a thread\n"); close_all_connections (&daemon->worker_pool[i]); - MHD_mutex_destroy_ (&daemon->worker_pool[i].cleanup_connection_mutex); + (void) MHD_mutex_destroy_ (&daemon->worker_pool[i].cleanup_connection_mutex); #if EPOLL_SUPPORT if ( (-1 != daemon->worker_pool[i].epoll_fd) && (0 != MHD_socket_close_ (daemon->worker_pool[i].epoll_fd)) ) @@ -4130,6 +4171,11 @@ 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); @@ -4146,10 +4192,10 @@ MHD_stop_daemon (struct MHD_Daemon *daemon) #ifdef DAUTH_SUPPORT free (daemon->nnc); - MHD_mutex_destroy_ (&daemon->nnc_lock); + (void) MHD_mutex_destroy_ (&daemon->nnc_lock); #endif - MHD_mutex_destroy_ (&daemon->per_ip_connection_mutex); - MHD_mutex_destroy_ (&daemon->cleanup_connection_mutex); + (void) MHD_mutex_destroy_ (&daemon->per_ip_connection_mutex); + (void) MHD_mutex_destroy_ (&daemon->cleanup_connection_mutex); if (MHD_INVALID_PIPE_ != daemon->wpipe[1]) { diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h @@ -1194,6 +1194,16 @@ struct MHD_Daemon const char *https_mem_trust; /** + * Our Diffie-Hellman parameters in memory. + */ + gnutls_dh_params_t https_mem_dhparams; + + /** + * #MHD_YES if we have initialized @e https_mem_dhparams. + */ + int have_dhparams; + + /** * For how many connections do we have 'tls_read_ready' set to MHD_YES? * Used to avoid O(n) traversal over all connections when determining * event-loop timeout (as it needs to be zero if there is any connection