libmicrohttpd

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

commit 6e95c305e4f0a3b0c33d8d4db7db8058f998e089
parent ce538bc10254dbe52ea8ae66aeb0bc77605d1547
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
Date:   Tue, 11 Oct 2022 09:41:15 +0300

TLS: use application-specific system-wide configuration with fallbacks

Implemented more flexible GnuTLS priorities string initialisation. Now
MHD tries to use "@LIBMICROHTTPD" configuration at first, so all
MHD instances on particular system can be configured by specifying the
string like "LIBMICROHTTPD = ..." in GnuTLS system-wide configuration.
For example "LIBMICROHTTPD = NORMAL:-VERS-TLS1.0:-VERS-TLS1.1" could be
used to disable TLS v1.0 and TLS v1.1 for all MHD instances.
If application-specific configuration is not available, then default
"@SYSTEM" run-time configuration is used.
If "@SYSTEM" is not defined, then GnuTLS build-time default string
is used.
Standard "NORMAL" configuration is used if everything else fails.

Diffstat:
Msrc/include/microhttpd.h | 13++++++++++---
Msrc/microhttpd/daemon.c | 117+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
2 files changed, 119 insertions(+), 11 deletions(-)

diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h @@ -96,7 +96,7 @@ extern "C" * they are parsed as decimal numbers. * Example: 0x01093001 = 1.9.30-1. */ -#define MHD_VERSION 0x00097540 +#define MHD_VERSION 0x00097541 /* If generic headers don't work on your platform, include headers which define 'va_list', 'size_t', 'ssize_t', 'intptr_t', 'off_t', @@ -1732,8 +1732,15 @@ enum MHD_OPTION MHD_OPTION_HTTPS_CRED_TYPE = 10, /** - * Memory pointer to a `const char *` specifying the - * cipher algorithm (default: "NORMAL"). + * Memory pointer to a `const char *` specifying the GnuTLS priorities string. + * If this options is not specified, then MHD will try the following strings: + * * "@LIBMICROHTTPD" (application-specific system-wide configuration) + * * "@SYSTEM" (system-wide configuration) + * * default GnuTLS priorities string + * * "NORMAL" + * The first configuration accepted by GnuTLS will be used. + * For more details see GnuTLS documentation for "Application-specific + * priority strings". */ MHD_OPTION_HTTPS_PRIORITIES = 11, diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c @@ -5892,6 +5892,100 @@ parse_options (struct MHD_Daemon *daemon, } +#ifdef HTTPS_SUPPORT +/** + * Type of GnuTLS priorities base string + */ +enum MHD_TlsPrioritiesBaseType +{ + MHD_TLS_PRIO_BASE_LIBMHD = 0, /**< @c "@LIBMICROHTTPD" */ + MHD_TLS_PRIO_BASE_SYSTEM = 1, /**< @c "@SYSTEM" */ +#if GNUTLS_VERSION_NUMBER >= 0x030300 + MHD_TLS_PRIO_BASE_DEFAULT, /**< Default priorities string */ +#endif /* GNUTLS_VERSION_NUMBER >= 0x030300 */ + MHD_TLS_PRIO_BASE_NORMAL /**< @c "NORMAL */ +}; + +static const struct _MHD_cstr_w_len MHD_TlsBasePriotities[] = { + _MHD_S_STR_W_LEN ("@LIBMICROHTTPD"), + _MHD_S_STR_W_LEN ("@SYSTEM"), +#if GNUTLS_VERSION_NUMBER >= 0x030300 + {NULL, 0}, +#endif /* GNUTLS_VERSION_NUMBER >= 0x030300 */ + _MHD_S_STR_W_LEN ("NORMAL") +}; + +/** + * Initialise TLS priorities with default settings + * @param daemon the daemon to initialise TLS priorities + * @return true on success, false on error + */ +static bool +daemon_tls_priorities_init_default (struct MHD_Daemon *daemon) +{ + unsigned int p; + int res; + + mhd_assert (0 != (((unsigned int) daemon->options) & MHD_USE_TLS)); + mhd_assert (NULL == daemon->priority_cache); + mhd_assert (MHD_TLS_PRIO_BASE_NORMAL + 1 == \ + sizeof(MHD_TlsBasePriotities) / sizeof(MHD_TlsBasePriotities[0])); + + for (p = 0; + p < sizeof(MHD_TlsBasePriotities) / sizeof(MHD_TlsBasePriotities[0]); + ++p) + { + res = gnutls_priority_init (&daemon->priority_cache, + MHD_TlsBasePriotities[p].str, NULL); + if (GNUTLS_E_SUCCESS == res) + { +#ifdef _DEBUG +#ifdef HAVE_MESSAGES + switch ((enum MHD_TlsPrioritiesBaseType) p) + { + case MHD_TLS_PRIO_BASE_LIBMHD: + MHD_DLOG (daemon, + _ ("GnuTLS priorities have been initialised with " \ + "@LIBMICROHTTPD application-specific system-wide " \ + "configuration.\n") ); + break; + case MHD_TLS_PRIO_BASE_SYSTEM: + MHD_DLOG (daemon, + _ ("GnuTLS priorities have been initialised with " \ + "@SYSTEM system-wide configuration.\n") ); + break; +#if GNUTLS_VERSION_NUMBER >= 0x030300 + case MHD_TLS_PRIO_BASE_DEFAULT: + MHD_DLOG (daemon, + _ ("GnuTLS priorities have been initialised with " \ + "GnuTLS default configuration.\n") ); + break; +#endif /* GNUTLS_VERSION_NUMBER >= 0x030300 */ + case MHD_TLS_PRIO_BASE_NORMAL: + MHD_DLOG (daemon, + _ ("GnuTLS priorities have been initialised with " \ + "NORMAL configuration.\n") ); + break; + default: + mhd_assert (0); + } +#endif /* HAVE_MESSAGES */ +#endif /* _DEBUG */ + return true; + } + } +#ifdef HAVE_MESSAGES + MHD_DLOG (daemon, + _ ("Failed to set GnuTLS priorities. Last error: %s\n"), + gnutls_strerror (res)); +#endif /* HAVE_MESSAGES */ + return false; +} + + +#endif /* HTTPS_SUPPORT */ + + /** * Parse a list of options given as varargs. * @@ -6158,7 +6252,8 @@ parse_options_va (struct MHD_Daemon *daemon, if (0 != (daemon->options & MHD_USE_TLS)) { int init_res; - gnutls_priority_deinit (daemon->priority_cache); + if (NULL != daemon->priority_cache) + gnutls_priority_deinit (daemon->priority_cache); init_res = gnutls_priority_init (&daemon->priority_cache, pstr, NULL); @@ -6653,7 +6748,6 @@ setup_epoll_to_listen (struct MHD_Daemon *daemon) #endif - /** * Start a webserver on the given port. * @@ -6775,12 +6869,6 @@ MHD_start_daemon_va (unsigned int flags, /* try to open listen socket */ #ifdef HTTPS_SUPPORT daemon->priority_cache = NULL; - if (0 != (*pflags & MHD_USE_TLS)) - { - gnutls_priority_init (&daemon->priority_cache, - "NORMAL", - NULL); - } #endif /* HTTPS_SUPPORT */ daemon->listen_fd = MHD_INVALID_SOCKET; daemon->listen_is_unix = _MHD_NO; @@ -6857,6 +6945,19 @@ MHD_start_daemon_va (unsigned int flags, free (daemon); return NULL; } +#ifdef HTTPS_SUPPORT + if ((0 != (*pflags & MHD_USE_TLS)) + && (NULL == daemon->priority_cache) + && ! daemon_tls_priorities_init_default (daemon)) + { +#ifdef HAVE_MESSAGES + MHD_DLOG (daemon, + _ ("Failed to initialise GnuTLS priorities.\n")); +#endif /* HAVE_MESSAGES */ + free (daemon); + return NULL; + } +#endif /* HTTPS_SUPPORT */ #ifdef HAVE_MESSAGES if ( (0 != (flags & MHD_USE_THREAD_PER_CONNECTION)) &&