commit 04a3cfce206a341c836223c0161add5a9bf8cc22
parent 16e14b86de3d7f429efe9423f73c8b15bc42ea8f
Author: Evgeny Grin (Karlson2k) <k2k@drgrin.dev>
Date: Wed, 17 Dec 2025 21:33:50 +0100
OpenSSL backend: implemented support for custom profile in the configuration file
Diffstat:
7 files changed, 820 insertions(+), 129 deletions(-)
diff --git a/src/include/d_options.rec b/src/include/d_options.rec
@@ -253,6 +253,76 @@ Comment: Control ALPN for TLS connection.
+ Silently ignored for non-TLS.
+ By default ALPN is automatically used for TLS connections.
+Name: tls_app_name
+Value: 142
+Type: struct MHD_DaemonOptionValueTlsAppName
+Comment: Provide application name to load dedicated section in TLS backend's configuration file.
++ Search for "System-wide configuration of the library" for GnuTLS documentation or
++ for "config, OPENSSL LIBRARY CONFIGURATION" for OpenSSL documentation.
++ If not specified the default backend configuration is used:
++ "@LIBMICROHTTPD" (if available), then "@SYSTEM" (if available) then default priorities, then "NORMAL" for GnuTLS;
++ "libmicrohttpd" (if available), then default name ("openssl_conf") for OpenSSL.
++ Ignored when MbedTLS is used as daemon's TLS backend.
+Argument1: char *app_name
+Description1: the name of the application, used as converted to
++ uppercase (with '@'-prefixed) for GnuTLS and as converted to
++ lowercase for OpenSSL; must not be longer than 127 characters
+Argument2: enum MHD_Bool disable_fallback
+Description2: forbid use fallback/default configuration if specified
++ configuration is not found; also forbid ignoring errors in the
++ configuration on TLS backends, which may ignoring configuration
++ errors
+CustomSetter: /* custom setter */
++ settings->tls_app_name.v_disable_fallback =
++ option->val.tls_app_name.v_disable_fallback;
++ if (NULL == option->val.tls_app_name.v_app_name)
++ return MHD_SC_CONFIGURATION_PARAM_NULL;
++ else
++ {
++ size_t len;
++ len = strlen (option->val.tls_app_name.v_app_name);
++ if (128 <= len)
++ return MHD_SC_CONFIGURATION_PARAM_TOO_LARGE;
++ settings->tls_app_name.v_app_name = (char *) malloc (len + 1u);
++ if (NULL == settings->tls_app_name.v_app_name)
++ return MHD_SC_DAEMON_MEM_ALLOC_FAILURE;
++ memcpy (settings->tls_app_name.v_app_name,
++ option->val.tls_app_name.v_app_name,
++ len + 1u);
++ }
+
+Name: tls_openssl_def_file
+Value: 144
+Type: struct MHD_DaemonOptionValueTlsOsslDefFile
+Comment: Set the configuration pathname for OpenSSL configuration file
++ Ignored OpenSSL is not used as daemon's TLS backend.
+Argument1: char *pathname
+Description1: the path and the name of the OpenSSL configuration file,
++ if only the name is provided then standard path for
++ configuration files is used,
++ could be NULL to use default configuration file pathname
++ or an empty (zero-size) string to disable file loading
+Argument2: enum MHD_Bool disable_fallback
+Description2: forbid use of fallback/default location and name of
++ the OpenSSL configuration file; also forbid initialisation without
++ configuration file
+CustomSetter: /* custom setter */
++ settings->tls_openssl_def_file.v_disable_fallback =
++ option->val.tls_openssl_def_file.v_disable_fallback;
++ if (NULL == option->val.tls_openssl_def_file.v_pathname)
++ settings->tls_openssl_def_file.v_pathname = NULL;
++ else
++ {
++ size_t len;
++ len = strlen (option->val.tls_openssl_def_file.v_pathname);
++ settings->tls_openssl_def_file.v_pathname = (char *) malloc (len + 1u);
++ if (NULL == settings->tls_openssl_def_file.v_pathname)
++ return MHD_SC_DAEMON_MEM_ALLOC_FAILURE;
++ memcpy (settings->tls_openssl_def_file.v_pathname,
++ option->val.tls_openssl_def_file.v_pathname,
++ len + 1u);
++ }
+
# Connection handling
Name: DEFAULT_TIMEOUT
diff --git a/src/include/microhttpd2.h b/src/include/microhttpd2.h
@@ -1577,6 +1577,16 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode
MHD_SC_CONFIGURATION_CONN_LIMIT_TOO_SMALL = 60026
,
/**
+ * The provided configuration parameter is NULL, but it must be non-NULL
+ */
+ MHD_SC_CONFIGURATION_PARAM_NULL = 60027
+ ,
+ /**
+ * The size of the provided configuration parameter is too large
+ */
+ MHD_SC_CONFIGURATION_PARAM_TOO_LARGE = 60028
+ ,
+ /**
* The application requested an unsupported TLS backend to be used.
*/
MHD_SC_TLS_BACKEND_UNSUPPORTED = 60030
@@ -4383,6 +4393,48 @@ MHD_D_OPTION_NO_ALPN (
);
/**
+ * Provide application name to load dedicated section in TLS backend's configuration file.
+ * Search for "System-wide configuration of the library" for GnuTLS documentation or
+ * for "config, OPENSSL LIBRARY CONFIGURATION" for OpenSSL documentation.
+ * If not specified the default backend configuration is used:
+ * "@LIBMICROHTTPD" (if available), then "@SYSTEM" (if available) then default priorities, then "NORMAL" for GnuTLS;
+ * "libmicrohttpd" (if available), then default name ("openssl_conf") for OpenSSL.
+ * Ignored when MbedTLS is used as daemon's TLS backend.
+ * @param app_name the name of the application, used as converted to
+ * uppercase (with '@'-prefixed) for GnuTLS and as converted to
+ * lowercase for OpenSSL; must not be longer than 127 characters
+ * @param disable_fallback forbid use fallback/default configuration if specified
+ * configuration is not found; also forbid ignoring errors in the
+ * configuration on TLS backends, which may ignoring configuration
+ * errors
+ * @return structure with the requested setting
+ */
+struct MHD_DaemonOptionAndValue
+MHD_D_OPTION_TLS_APP_NAME (
+ char *app_name,
+ enum MHD_Bool disable_fallback
+ );
+
+/**
+ * Set the configuration pathname for OpenSSL configuration file
+ * Ignored OpenSSL is not used as daemon's TLS backend.
+ * @param pathname the path and the name of the OpenSSL configuration file,
+ * if only the name is provided then standard path for
+ * configuration files is used,
+ * could be NULL to use default configuration file pathname
+ * or an empty (zero-size) string to disable file loading
+ * @param disable_fallback forbid use of fallback/default location and name of
+ * the OpenSSL configuration file; also forbid initialisation without
+ * configuration file
+ * @return structure with the requested setting
+ */
+struct MHD_DaemonOptionAndValue
+MHD_D_OPTION_TLS_OPENSSL_DEF_FILE (
+ char *pathname,
+ enum MHD_Bool disable_fallback
+ );
+
+/**
* Specify inactivity timeout for connection.
* When no activity for specified time on connection, it is closed
* automatically.
diff --git a/src/include/microhttpd2_generated_daemon_options.h b/src/include/microhttpd2_generated_daemon_options.h
@@ -149,6 +149,25 @@ Works only when #MHD_D_OPTION_BIND_PORT() or #MHD_D_OPTION_BIND_SA() are used.
,
/**
+ * Provide application name to load dedicated section in TLS backend's configuration file.
+ * Search for "System-wide configuration of the library" for GnuTLS documentation or
+ * for "config, OPENSSL LIBRARY CONFIGURATION" for OpenSSL documentation.
+ * If not specified the default backend configuration is used:
+ * "@LIBMICROHTTPD" (if available), then "@SYSTEM" (if available) then default priorities, then "NORMAL" for GnuTLS;
+ * "libmicrohttpd" (if available), then default name ("openssl_conf") for OpenSSL.
+ * Ignored when MbedTLS is used as daemon's TLS backend.
+ */
+ MHD_D_O_TLS_APP_NAME = 142
+ ,
+
+ /**
+ * Set the configuration pathname for OpenSSL configuration file
+ * Ignored OpenSSL is not used as daemon's TLS backend.
+ */
+ MHD_D_O_TLS_OPENSSL_DEF_FILE = 144
+ ,
+
+ /**
* Specify inactivity timeout for connection.
* When no activity for specified time on connection, it is closed
* automatically.
@@ -492,6 +511,51 @@ struct MHD_DaemonOptionValueTlsPskCB
};
/**
+ * Data for #MHD_D_O_TLS_APP_NAME
+ */
+struct MHD_DaemonOptionValueTlsAppName
+{
+ /**
+ * the name of the application, used as converted to
+ * uppercase (with '@'-prefixed) for GnuTLS and as converted to
+ * lowercase for OpenSSL; must not be longer than 127 characters
+ */
+ char *v_app_name;
+
+ /**
+ * forbid use fallback/default configuration if specified
+ * configuration is not found; also forbid ignoring errors in the
+ * configuration on TLS backends, which may ignoring configuration
+ * errors
+ */
+ enum MHD_Bool v_disable_fallback;
+
+};
+
+/**
+ * Data for #MHD_D_O_TLS_OPENSSL_DEF_FILE
+ */
+struct MHD_DaemonOptionValueTlsOsslDefFile
+{
+ /**
+ * the path and the name of the OpenSSL configuration file,
+ * if only the name is provided then standard path for
+ * configuration files is used,
+ * could be NULL to use default configuration file pathname
+ * or an empty (zero-size) string to disable file loading
+ */
+ char *v_pathname;
+
+ /**
+ * forbid use of fallback/default location and name of
+ * the OpenSSL configuration file; also forbid initialisation without
+ * configuration file
+ */
+ enum MHD_Bool v_disable_fallback;
+
+};
+
+/**
* Data for #MHD_D_O_ACCEPT_POLICY
*/
struct MHD_DaemonOptionValueAcceptPol
@@ -715,6 +779,24 @@ union MHD_DaemonOptionValue
enum MHD_Bool no_alpn;
/**
+ * Value for #MHD_D_O_TLS_APP_NAME.
+ * the name of the application, used as converted to
+ * uppercase (with '@'-prefixed) for GnuTLS and as converted to
+ * lowercase for OpenSSL; must not be longer than 127 characters
+ */
+ struct MHD_DaemonOptionValueTlsAppName tls_app_name;
+
+ /**
+ * Value for #MHD_D_O_TLS_OPENSSL_DEF_FILE.
+ * the path and the name of the OpenSSL configuration file,
+ * if only the name is provided then standard path for
+ * configuration files is used,
+ * could be NULL to use default configuration file pathname
+ * or an empty (zero-size) string to disable file loading
+ */
+ struct MHD_DaemonOptionValueTlsOsslDefFile tls_openssl_def_file;
+
+ /**
* Value for #MHD_D_O_DEFAULT_TIMEOUT.
* the in seconds, zero for no timeout
*/
@@ -1149,6 +1231,54 @@ Works only when #MHD_D_OPTION_BIND_PORT() or #MHD_D_OPTION_BIND_SA() are used.
} \
MHD_RESTORE_WARN_COMPOUND_LITERALS_ MHD_RESTORE_WARN_AGGR_DYN_INIT_
/**
+ * Provide application name to load dedicated section in TLS backend's configuration file.
+ * Search for "System-wide configuration of the library" for GnuTLS documentation or
+ * for "config, OPENSSL LIBRARY CONFIGURATION" for OpenSSL documentation.
+ * If not specified the default backend configuration is used:
+ * "@LIBMICROHTTPD" (if available), then "@SYSTEM" (if available) then default priorities, then "NORMAL" for GnuTLS;
+ * "libmicrohttpd" (if available), then default name ("openssl_conf") for OpenSSL.
+ * Ignored when MbedTLS is used as daemon's TLS backend.
+ * @param app_name the name of the application, used as converted to
+ * uppercase (with '@'-prefixed) for GnuTLS and as converted to
+ * lowercase for OpenSSL; must not be longer than 127 characters
+ * @param disable_fallback forbid use fallback/default configuration if specified
+ * configuration is not found; also forbid ignoring errors in the
+ * configuration on TLS backends, which may ignoring configuration
+ * errors
+ * @return structure with the requested setting
+ */
+# define MHD_D_OPTION_TLS_APP_NAME(app_name,disable_fallback) \
+ MHD_NOWARN_COMPOUND_LITERALS_ MHD_NOWARN_AGGR_DYN_INIT_ \
+ (const struct MHD_DaemonOptionAndValue) \
+ { \
+ .opt = MHD_D_O_TLS_APP_NAME, \
+ .val.tls_app_name.v_app_name = (app_name), \
+ .val.tls_app_name.v_disable_fallback = (disable_fallback) \
+ } \
+ MHD_RESTORE_WARN_COMPOUND_LITERALS_ MHD_RESTORE_WARN_AGGR_DYN_INIT_
+/**
+ * Set the configuration pathname for OpenSSL configuration file
+ * Ignored OpenSSL is not used as daemon's TLS backend.
+ * @param pathname the path and the name of the OpenSSL configuration file,
+ * if only the name is provided then standard path for
+ * configuration files is used,
+ * could be NULL to use default configuration file pathname
+ * or an empty (zero-size) string to disable file loading
+ * @param disable_fallback forbid use of fallback/default location and name of
+ * the OpenSSL configuration file; also forbid initialisation without
+ * configuration file
+ * @return structure with the requested setting
+ */
+# define MHD_D_OPTION_TLS_OPENSSL_DEF_FILE(pathname,disable_fallback) \
+ MHD_NOWARN_COMPOUND_LITERALS_ MHD_NOWARN_AGGR_DYN_INIT_ \
+ (const struct MHD_DaemonOptionAndValue) \
+ { \
+ .opt = MHD_D_O_TLS_OPENSSL_DEF_FILE, \
+ .val.tls_openssl_def_file.v_pathname = (pathname), \
+ .val.tls_openssl_def_file.v_disable_fallback = (disable_fallback) \
+ } \
+ MHD_RESTORE_WARN_COMPOUND_LITERALS_ MHD_RESTORE_WARN_AGGR_DYN_INIT_
+/**
* Specify inactivity timeout for connection.
* When no activity for specified time on connection, it is closed
* automatically.
@@ -1939,6 +2069,68 @@ MHD_D_OPTION_NO_ALPN (
/**
+ * Provide application name to load dedicated section in TLS backend's configuration file.
+ * Search for "System-wide configuration of the library" for GnuTLS documentation or
+ * for "config, OPENSSL LIBRARY CONFIGURATION" for OpenSSL documentation.
+ * If not specified the default backend configuration is used:
+ * "@LIBMICROHTTPD" (if available), then "@SYSTEM" (if available) then default priorities, then "NORMAL" for GnuTLS;
+ * "libmicrohttpd" (if available), then default name ("openssl_conf") for OpenSSL.
+ * Ignored when MbedTLS is used as daemon's TLS backend.
+ * @param app_name the name of the application, used as converted to
+ * uppercase (with '@'-prefixed) for GnuTLS and as converted to
+ * lowercase for OpenSSL; must not be longer than 127 characters
+ * @param disable_fallback forbid use fallback/default configuration if specified
+ * configuration is not found; also forbid ignoring errors in the
+ * configuration on TLS backends, which may ignoring configuration
+ * errors
+ * @return structure with the requested setting
+ */
+static MHD_INLINE struct MHD_DaemonOptionAndValue
+MHD_D_OPTION_TLS_APP_NAME (
+ char *app_name,
+ enum MHD_Bool disable_fallback
+ )
+{
+ struct MHD_DaemonOptionAndValue opt_val;
+
+ opt_val.opt = MHD_D_O_TLS_APP_NAME;
+ opt_val.val.tls_app_name.v_app_name = app_name;
+ opt_val.val.tls_app_name.v_disable_fallback = disable_fallback;
+
+ return opt_val;
+}
+
+
+/**
+ * Set the configuration pathname for OpenSSL configuration file
+ * Ignored OpenSSL is not used as daemon's TLS backend.
+ * @param pathname the path and the name of the OpenSSL configuration file,
+ * if only the name is provided then standard path for
+ * configuration files is used,
+ * could be NULL to use default configuration file pathname
+ * or an empty (zero-size) string to disable file loading
+ * @param disable_fallback forbid use of fallback/default location and name of
+ * the OpenSSL configuration file; also forbid initialisation without
+ * configuration file
+ * @return structure with the requested setting
+ */
+static MHD_INLINE struct MHD_DaemonOptionAndValue
+MHD_D_OPTION_TLS_OPENSSL_DEF_FILE (
+ char *pathname,
+ enum MHD_Bool disable_fallback
+ )
+{
+ struct MHD_DaemonOptionAndValue opt_val;
+
+ opt_val.opt = MHD_D_O_TLS_OPENSSL_DEF_FILE;
+ opt_val.val.tls_openssl_def_file.v_pathname = pathname;
+ opt_val.val.tls_openssl_def_file.v_disable_fallback = disable_fallback;
+
+ return opt_val;
+}
+
+
+/**
* Specify inactivity timeout for connection.
* When no activity for specified time on connection, it is closed
* automatically.
diff --git a/src/include/microhttpd2_preamble.h.in b/src/include/microhttpd2_preamble.h.in
@@ -1577,6 +1577,16 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode
MHD_SC_CONFIGURATION_CONN_LIMIT_TOO_SMALL = 60026
,
/**
+ * The provided configuration parameter is NULL, but it must be non-NULL
+ */
+ MHD_SC_CONFIGURATION_PARAM_NULL = 60027
+ ,
+ /**
+ * The size of the provided configuration parameter is too large
+ */
+ MHD_SC_CONFIGURATION_PARAM_TOO_LARGE = 60028
+ ,
+ /**
* The application requested an unsupported TLS backend to be used.
*/
MHD_SC_TLS_BACKEND_UNSUPPORTED = 60030
diff --git a/src/mhd2/daemon_options.h b/src/mhd2/daemon_options.h
@@ -130,6 +130,26 @@ struct DaemonOptions
/**
+ * Value for #MHD_D_O_TLS_APP_NAME.
+ * the name of the application, used as converted to
+ * uppercase (with '@'-prefixed) for GnuTLS and as converted to
+ * lowercase for OpenSSL; must not be longer than 127 characters
+ */
+ struct MHD_DaemonOptionValueTlsAppName tls_app_name;
+
+
+ /**
+ * Value for #MHD_D_O_TLS_OPENSSL_DEF_FILE.
+ * the path and the name of the OpenSSL configuration file,
+ * if only the name is provided then standard path for
+ * configuration files is used,
+ * could be NULL to use default configuration file pathname
+ * or an empty (zero-size) string to disable file loading
+ */
+ struct MHD_DaemonOptionValueTlsOsslDefFile tls_openssl_def_file;
+
+
+ /**
* Value for #MHD_D_O_DEFAULT_TIMEOUT.
* the in seconds, zero for no timeout
*/
diff --git a/src/mhd2/daemon_set_options.c b/src/mhd2/daemon_set_options.c
@@ -150,6 +150,44 @@ MHD_daemon_set_options (
case MHD_D_O_NO_ALPN:
settings->no_alpn = option->val.no_alpn;
continue;
+ case MHD_D_O_TLS_APP_NAME:
+ /* custom setter */
+ settings->tls_app_name.v_disable_fallback =
+ option->val.tls_app_name.v_disable_fallback;
+ if (NULL == option->val.tls_app_name.v_app_name)
+ return MHD_SC_CONFIGURATION_PARAM_NULL;
+ else
+ {
+ size_t len;
+ len = strlen (option->val.tls_app_name.v_app_name);
+ if (128 <= len)
+ return MHD_SC_CONFIGURATION_PARAM_TOO_LARGE;
+ settings->tls_app_name.v_app_name = (char *) malloc (len + 1u);
+ if (NULL == settings->tls_app_name.v_app_name)
+ return MHD_SC_DAEMON_MEM_ALLOC_FAILURE;
+ memcpy (settings->tls_app_name.v_app_name,
+ option->val.tls_app_name.v_app_name,
+ len + 1u);
+ }
+ continue;
+ case MHD_D_O_TLS_OPENSSL_DEF_FILE:
+ /* custom setter */
+ settings->tls_openssl_def_file.v_disable_fallback =
+ option->val.tls_openssl_def_file.v_disable_fallback;
+ if (NULL == option->val.tls_openssl_def_file.v_pathname)
+ settings->tls_openssl_def_file.v_pathname = NULL;
+ else
+ {
+ size_t len;
+ len = strlen (option->val.tls_openssl_def_file.v_pathname);
+ settings->tls_openssl_def_file.v_pathname = (char *) malloc (len + 1u);
+ if (NULL == settings->tls_openssl_def_file.v_pathname)
+ return MHD_SC_DAEMON_MEM_ALLOC_FAILURE;
+ memcpy (settings->tls_openssl_def_file.v_pathname,
+ option->val.tls_openssl_def_file.v_pathname,
+ len + 1u);
+ }
+ continue;
case MHD_D_O_DEFAULT_TIMEOUT:
settings->default_timeout = option->val.default_timeout;
continue;
diff --git a/src/mhd2/tls_open_funcs.c b/src/mhd2/tls_open_funcs.c
@@ -57,7 +57,9 @@
#include "mhd_assert.h"
#include "mhd_unreachable.h"
+#include "mhd_assume.h"
+#include "mhd_str.h"
#include "mhd_conn_socket.h"
#include "mhd_tls_internal.h"
@@ -112,8 +114,17 @@ mhd_tls_open_dbg_print_errs (const char *msg,
# define mhd_DBG_PRINT_TLS_ERRS() \
ERR_print_errors_cb (&mhd_tls_open_dbg_print_errs, NULL)
+
+# define mhd_DBG_PRINT_TLS_INFO_MSG(message) \
+ do { (void) fprintf (stderr, "## OpenSSL info: %s\n", (message)); \
+ (void) fflush (stderr);} while (0)
+# define mhd_DBG_PRINT_TLS_INFO_PARAM1(message,param) \
+ do { (void) fprintf (stderr, "## OpenSSL info: " message "\n", (param)); \
+ (void) fflush (stderr);} while (0)
#else
# define mhd_DBG_PRINT_TLS_ERRS() ERR_clear_error ()
+# define mhd_DBG_PRINT_TLS_INFO_MSG(message) ((void) 0)
+# define mhd_DBG_PRINT_TLS_INFO_PARAM1(message,param) ((void) 0)
#endif
/* ** Global initialisation / de-initialisation ** */
@@ -191,15 +202,398 @@ null_passwd_cb (char *buf,
void *cls)
{
(void) buf; (void) size; (void) rwflag; (void) cls; /* Unused */
-#ifdef mhd_USE_TLS_DEBUG_MESSAGES
- fprintf (stderr, "## OpenSSL: the NULL passphrase callback is called\n");
- fflush (stderr);
-#endif
+ mhd_DBG_PRINT_TLS_INFO_MSG ("The NULL passphrase callback is called\n");
return 0;
}
/**
+ * Get non-default pathname for OpenSSL configuration file
+ * @param s the application-provided settings
+ * @param[out] conf_pathname set to the pathname on success
+ * @return #MHD_SC_OK on success,
+ * error code otherwise
+ */
+static MHD_FN_PAR_NONNULL_ALL_
+MHD_FN_PAR_OUT_ (2) MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode
+daemon_get_conf_file (struct DaemonOptions *restrict s,
+ char **restrict conf_pathname)
+{
+ size_t name_len;
+ bool has_path;
+
+ mhd_assert (NULL != s->tls_openssl_def_file.v_pathname);
+
+#ifndef MHD_SUPPORT_LOG_FUNCTIONALITY
+ (void) d; /* Used only for logging */
+#endif
+
+ /* Handle custom pathname */
+
+ name_len = strlen (s->tls_openssl_def_file.v_pathname);
+ has_path = (NULL != memchr (s->tls_openssl_def_file.v_pathname,
+ '/',
+ name_len));
+#ifdef _WIN32
+ has_path = has_path || (NULL != memchr (s->tls_openssl_def_file,
+ '\\',
+ name_len));
+#endif /* _WIN32 */
+
+ if ((! has_path) && (0u != name_len))
+ {
+ const char *def_path;
+ size_t def_path_len;
+
+ def_path = X509_get_default_cert_area ();
+ if (NULL == def_path)
+ {
+ mhd_DBG_PRINT_TLS_ERRS ();
+ mhd_DBG_PRINT_TLS_INFO_MSG ("X509_get_default_cert_area() returned NULL");
+ return MHD_SC_TLS_DAEMON_INIT_FAILED; /* Unrealistic */
+ }
+
+ def_path_len = strlen (def_path);
+
+ *conf_pathname =
+ (char *) OPENSSL_malloc (def_path_len + 1u + name_len + 1u);
+ if (NULL == *conf_pathname)
+ return MHD_SC_DAEMON_MEM_ALLOC_FAILURE;
+
+ memcpy (*conf_pathname,
+ def_path,
+ def_path_len);
+ (*conf_pathname)[def_path_len] = '/';
+ memcpy ((*conf_pathname) + def_path_len + 1u,
+ s->tls_openssl_def_file.v_pathname,
+ name_len + 1u);
+
+ return MHD_SC_OK;
+ }
+
+ *conf_pathname = (char *) OPENSSL_malloc (name_len + 1u);
+ if (NULL == *conf_pathname)
+ return MHD_SC_DAEMON_MEM_ALLOC_FAILURE;
+
+ memcpy (*conf_pathname,
+ s->tls_openssl_def_file.v_pathname,
+ name_len + 1u);
+
+ return MHD_SC_OK;
+}
+
+
+#ifdef mhd_TLS_OPEN_HAS_CONF_DIAG
+# define mhd_LIBCTX_FORBIDS_FALLBACKS(d_tls) \
+ (0 != OSSL_LIB_CTX_get_conf_diagnostics (d_tls->libctx))
+#else
+# define mhd_LIBCTX_FORBIDS_FALLBACKS(d_tls) ((void) (d_tls), ! ! 0)
+#endif /* ! mhd_TLS_OPEN_HAS_CONF_DIAG */
+
+
+static MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (2)
+MHD_FN_PAR_NONNULL_ (4) bool
+daemon_load_conf_from_cfg (struct MHD_Daemon *restrict d,
+ const char *restrict filename,
+ const char *restrict app_name,
+ CONF *restrict cfg,
+ unsigned long load_flags,
+ bool log_missing_app_name)
+{
+#ifndef MHD_SUPPORT_LOG_FUNCTIONALITY
+ (void) d; /* Used for logging only */
+# ifndef mhd_USE_TLS_DEBUG_MESSAGES
+ (void) filename; /* Used for logs only */
+# endif /* mhd_USE_TLS_DEBUG_MESSAGES */
+#endif /* MHD_SUPPORT_LOG_FUNCTIONALITY */
+
+ if (NULL != app_name)
+ {
+ if (NULL == NCONF_get_string (cfg,
+ NULL,
+ app_name))
+ {
+ if (log_missing_app_name)
+ mhd_LOG_PRINT (d,
+ MHD_SC_TLS_LIB_CONF_WARNING,
+ mhd_LOG_FMT ("TLS library configuration '%s' "
+ "was not found in file '%s'"),
+ app_name,
+ filename);
+ else
+ mhd_DBG_PRINT_TLS_INFO_PARAM1 ("TLS library configuration '%s' "
+ "was not found in the configuration "
+ "file",
+ app_name);
+ return false;
+ }
+ mhd_DBG_PRINT_TLS_INFO_PARAM1 ("Trying to load configuration section "
+ "pointed by '%s'",
+ app_name);
+ }
+ else
+ mhd_DBG_PRINT_TLS_INFO_MSG ("Trying to load configuration section "
+ "pointed by default OpenSSL configuration");
+
+ if (1 != CONF_modules_load (cfg,
+ app_name,
+ load_flags))
+ {
+ mhd_DBG_PRINT_TLS_ERRS ();
+
+ mhd_LOG_PRINT (d,
+ MHD_SC_TLS_LIB_CONF_WARNING,
+ mhd_LOG_FMT ("Error loading TLS library "
+ "configuration '%s' "
+ "from file '%s'"),
+ app_name,
+ filename);
+
+ return false;
+ }
+
+ mhd_DBG_PRINT_TLS_INFO_MSG ("Successfully loaded OpenSSL configuration "
+ "from the configuration file");
+
+ return true;
+}
+
+
+static inline MHD_FN_PAR_NONNULL_ALL_ bool
+is_conf_file_fallback_allowed (
+ const struct mhd_TlsOpenDaemonData *restrict d_tls,
+ const struct DaemonOptions *restrict s)
+{
+ mhd_assert (NULL != d_tls->libctx);
+
+ if (! s->tls_openssl_def_file.v_disable_fallback)
+ return false;
+ if (mhd_LIBCTX_FORBIDS_FALLBACKS (d_tls))
+ return false;
+ return true;
+}
+
+
+static inline MHD_FN_PAR_NONNULL_ALL_ bool
+is_conf_fallback_allowed (const struct mhd_TlsOpenDaemonData *restrict d_tls,
+ const struct DaemonOptions *restrict s)
+{
+ if (! s->tls_app_name.v_disable_fallback)
+ return false;
+
+ return is_conf_file_fallback_allowed (d_tls,
+ s);
+}
+
+
+/**
+ * Load OpenSSL configuration from OpenSSL configuration file
+ * @param d the daemon handle
+ * @param d_tls the daemon TLS settings
+ * @param s the application-provided settings
+ * @param use_custom_conf_pathname choose application-provided pathname or
+ * TLS backend default pathname
+ * @return #MHD_SC_OK on success,
+ * #MHD_SC_TLS_LIB_CONF_WARNING if configuration was not loaded due to
+ * non-fatal error,
+ * error code otherwise
+ */
+static MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_NONNULL_ (3)
+MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode
+daemon_load_lib_conf (struct MHD_Daemon *restrict d,
+ struct mhd_TlsOpenDaemonData *restrict d_tls,
+ struct DaemonOptions *restrict s,
+ bool use_custom_conf_pathname)
+{
+ char *conf_pathname;
+ CONF *conf;
+ enum MHD_StatusCode ret;
+
+ if (! use_custom_conf_pathname)
+ {
+ /* Use default pathname */
+ conf_pathname = CONF_get1_default_config_file ();
+
+ if (NULL == conf_pathname)
+ {
+ mhd_DBG_PRINT_TLS_ERRS ();
+
+ ret = is_conf_fallback_allowed (d_tls,
+ s)
+ ? MHD_SC_TLS_LIB_CONF_WARNING : MHD_SC_TLS_DAEMON_INIT_FAILED;
+
+ mhd_LOG_MSG (d, ret, \
+ "Failed to get default configuration file pathname");
+ }
+ else
+ ret = MHD_SC_OK;
+ }
+ else
+ ret = daemon_get_conf_file (s,
+ &conf_pathname);
+
+ if (MHD_SC_OK != ret)
+ {
+ mhd_DBG_PRINT_TLS_INFO_MSG ("Failed to get configuration file pathname");
+ return ret;
+ }
+
+ mhd_ASSUME (NULL != conf_pathname);
+ mhd_DBG_PRINT_TLS_INFO_PARAM1 ("Trying '%s' as OpenSSL configuration file",
+ conf_pathname);
+
+ if ('\0' == conf_pathname[0])
+ {
+ /* A short-cut */
+ OPENSSL_free (conf_pathname);
+
+ if (NULL == s->tls_app_name.v_app_name)
+ return MHD_SC_OK; /* No special "application name" profile is needed */
+
+ if (! s->tls_app_name.v_disable_fallback)
+ return MHD_SC_OK; /* Initialisation allowed with default values */
+
+ /* Load of special "application name" profile is required */
+ if (! use_custom_conf_pathname)
+ return MHD_SC_TLS_DAEMON_INIT_FAILED; /* No fallback pathname */
+
+ mhd_assert (NULL != s->tls_openssl_def_file.v_pathname);
+
+ if (s->tls_openssl_def_file.v_disable_fallback)
+ return MHD_SC_TLS_DAEMON_INIT_FAILED; /* Fallback pathname is disallowed */
+
+ /* Try to use fallback pathname to load special "application name" profile */
+ return MHD_SC_TLS_LIB_CONF_WARNING;
+ }
+
+ conf = NCONF_new_ex (d_tls->libctx,
+ NULL);
+ if (NULL == conf)
+ {
+ mhd_DBG_PRINT_TLS_ERRS ();
+
+ ret = is_conf_fallback_allowed (d_tls,
+ s)
+ ? MHD_SC_TLS_LIB_CONF_WARNING : MHD_SC_TLS_DAEMON_INIT_FAILED;
+ mhd_LOG_MSG (d, ret, \
+ "Failed to create OpenSSL empty configuration object");
+ }
+
+ if (MHD_SC_OK == ret)
+ {
+ long err_line_num;
+ mhd_DBG_PRINT_TLS_INFO_PARAM1 ("Trying to load configuration file '%s'",
+ conf_pathname);
+
+ if (0 >= NCONF_load (conf,
+ conf_pathname,
+ &err_line_num))
+ {
+ mhd_DBG_PRINT_TLS_ERRS ();
+
+ if (use_custom_conf_pathname)
+ ret = is_conf_file_fallback_allowed (d_tls,
+ s)
+ ? MHD_SC_TLS_LIB_CONF_WARNING : MHD_SC_TLS_DAEMON_INIT_FAILED;
+ else
+ ret = is_conf_fallback_allowed (d_tls,
+ s)
+ ? MHD_SC_TLS_LIB_CONF_WARNING : MHD_SC_TLS_DAEMON_INIT_FAILED;
+
+ mhd_LOG_PRINT (d,
+ ret,
+ mhd_LOG_FMT ("Error loading TLS library configuration "
+ "file '%s' at line %ld"),
+ conf_pathname,
+ err_line_num);
+ }
+
+ if (MHD_SC_OK == ret)
+ {
+ bool conf_loaded;
+ unsigned long flags;
+
+ flags = 0u;
+ if (! s->tls_app_name.v_disable_fallback)
+ flags |= CONF_MFLAGS_IGNORE_ERRORS;
+
+ conf_loaded = false;
+
+ if (NULL != s->tls_app_name.v_app_name)
+ {
+ char app_name_lc[128];
+ const size_t app_name_len = strlen (s->tls_app_name.v_app_name);
+
+ /* Checked at the parameter processing */
+ mhd_ASSUME ((128u) > app_name_len);
+
+ mhd_str_to_lowercase_bin_n (app_name_len + 1u, /* '+1' for zero termination */
+ s->tls_app_name.v_app_name,
+ app_name_lc);
+
+ mhd_ASSUME ('\0' == app_name_lc[app_name_len]);
+
+ conf_loaded =
+ daemon_load_conf_from_cfg (d,
+ conf_pathname,
+ app_name_lc,
+ conf,
+ flags,
+ s->tls_app_name.v_disable_fallback ||
+ mhd_LIBCTX_FORBIDS_FALLBACKS (d_tls));
+
+ if (! conf_loaded &&
+ (s->tls_app_name.v_disable_fallback ||
+ mhd_LIBCTX_FORBIDS_FALLBACKS (d_tls)))
+ ret = MHD_SC_TLS_DAEMON_INIT_FAILED;
+ }
+
+ if (! conf_loaded &&
+ (MHD_SC_OK == ret))
+ {
+
+ mhd_assert ((NULL == s->tls_app_name.v_app_name) ||
+ ! s->tls_app_name.v_disable_fallback);
+
+ conf_loaded =
+ daemon_load_conf_from_cfg (d,
+ conf_pathname,
+ "libmicrohttpd",
+ conf,
+ flags,
+ false);
+ }
+
+ if (! conf_loaded &&
+ (MHD_SC_OK == ret))
+ {
+
+ mhd_assert ((NULL == s->tls_app_name.v_app_name) ||
+ ! s->tls_app_name.v_disable_fallback);
+
+ conf_loaded =
+ daemon_load_conf_from_cfg (d,
+ conf_pathname,
+ NULL,
+ conf,
+ flags,
+ true);
+ }
+
+ if (! conf_loaded)
+ ret = MHD_SC_TLS_LIB_CONF_WARNING;
+ }
+
+ NCONF_free (conf);
+ }
+
+ OPENSSL_free (conf_pathname);
+
+ return ret;
+}
+
+
+/**
* Initialise OpenSSL library context
* @param d the daemon handle
* @param d_tls the daemon TLS settings
@@ -212,12 +606,9 @@ daemon_init_lib_ctx (struct MHD_Daemon *restrict d,
struct mhd_TlsOpenDaemonData *restrict d_tls,
struct DaemonOptions *restrict s)
{
- bool fallback_config;
- bool prevent_fallbacks;
- char *conf_filename;
- d_tls->libctx = OSSL_LIB_CTX_new ();
+ enum MHD_StatusCode ret;
- (void) s; // TODO: support app-defined name for TLS backend profile
+ d_tls->libctx = OSSL_LIB_CTX_new ();
if (NULL == d_tls->libctx)
{
@@ -227,127 +618,50 @@ daemon_init_lib_ctx (struct MHD_Daemon *restrict d,
return MHD_SC_TLS_DAEMON_INIT_FAILED;
}
- prevent_fallbacks = false;
-#ifdef mhd_TLS_OPEN_HAS_CONF_DIAG
- prevent_fallbacks = prevent_fallbacks ||
- (0 != OSSL_LIB_CTX_get_conf_diagnostics (d_tls->libctx));
-#endif
-
- fallback_config = false;
- ERR_clear_error ();
-
- conf_filename = CONF_get1_default_config_file ();
- if (NULL == conf_filename)
- mhd_DBG_PRINT_TLS_ERRS ();
- else
+ if (NULL != s->tls_openssl_def_file.v_pathname)
{
- bool libctx_inited;
- CONF *conf;
+ ret = daemon_load_lib_conf (d,
+ d_tls,
+ s,
+ true);
- libctx_inited = false;
- conf = NCONF_new_ex (d_tls->libctx,
- NULL);
- if (NULL == conf)
- mhd_DBG_PRINT_TLS_ERRS ();
- else
- {
- if (0 >= NCONF_load (conf,
- conf_filename,
- NULL))
- {
- unsigned long err;
+ if (MHD_SC_OK == ret)
+ return MHD_SC_OK;
- err = ERR_peek_last_error ();
- mhd_DBG_PRINT_TLS_ERRS ();
- libctx_inited = true; /* Nothing to initialise */
+ if (MHD_SC_TLS_LIB_CONF_WARNING == ret)
+ ret = s->tls_openssl_def_file.v_disable_fallback
+ ? MHD_SC_TLS_DAEMON_INIT_FAILED : MHD_SC_OK;
+ }
+ else
+ ret = MHD_SC_OK;
- mhd_NOWARN_USED_UNUSED
+ mhd_assert (MHD_SC_TLS_LIB_CONF_WARNING != ret);
- if ((ERR_LIB_CONF != ERR_GET_LIB (err)) ||
- (CONF_R_NO_SUCH_FILE != ERR_GET_REASON (err)))
- {
- fallback_config = true;
- mhd_LOG_PRINT (d, MHD_SC_TLS_LIB_CONF_WARNING, \
- mhd_LOG_FMT ("Error in TLS library configuration "
- "file '%s'"), \
- conf_filename);
- }
+ if (MHD_SC_OK == ret)
+ {
+ mhd_assert ((NULL == s->tls_openssl_def_file.v_pathname) ||
+ ! s->tls_openssl_def_file.v_disable_fallback);
- mhd_RESTORE_WARN_USED_UNUSED
- }
- else /* NCONF_load() succeed */
- {
- (void) s; // TODO: support app-defined name for TLS backend profile
-
- if (! libctx_inited)
- {
- if (NULL != NCONF_get_section (conf,
- "libmicrohttpd"))
- {
- if (0 <
- CONF_modules_load (conf,
- "libmicrohttpd",
- 0))
- libctx_inited = true;
- else
- {
- mhd_DBG_PRINT_TLS_ERRS ();
- fallback_config = true;
- mhd_LOG_PRINT (d, MHD_SC_TLS_LIB_CONF_WARNING, \
- mhd_LOG_FMT ("Failed to load configuration file " \
- "section [%s]"), \
- "libmicrohttpd");
-
- libctx_inited =
- (0 < CONF_modules_load (conf,
- "libmicrohttpd",
- CONF_MFLAGS_IGNORE_ERRORS));
- if (! libctx_inited)
- mhd_DBG_PRINT_TLS_ERRS ();
- }
- }
- }
- if (! libctx_inited)
- {
- if (0 <
- CONF_modules_load (conf,
- NULL,
- 0))
- libctx_inited = true;
- else
- {
- mhd_DBG_PRINT_TLS_ERRS ();
- fallback_config = true;
- mhd_LOG_MSG (d, MHD_SC_TLS_LIB_CONF_WARNING, \
- "Failed to load configuration file default section");
-
- libctx_inited =
- (0 < CONF_modules_load (conf,
- NULL,
- CONF_MFLAGS_IGNORE_ERRORS));
- if (! libctx_inited)
- mhd_DBG_PRINT_TLS_ERRS ();
- }
- }
-#ifdef mhd_TLS_OPEN_HAS_CONF_DIAG
- if (fallback_config && libctx_inited && ! prevent_fallbacks)
- prevent_fallbacks =
- (0 != OSSL_LIB_CTX_get_conf_diagnostics (d_tls->libctx));
-#endif /* mhd_TLS_OPEN_HAS_CONF_DIAG */
- }
- NCONF_free (conf);
- }
- OPENSSL_free (conf_filename);
+ ret = daemon_load_lib_conf (d,
+ d_tls,
+ s,
+ false);
- if (fallback_config && prevent_fallbacks)
- libctx_inited = true;
+ if (MHD_SC_OK == ret)
+ return MHD_SC_OK;
- if (libctx_inited)
+ if (MHD_SC_TLS_LIB_CONF_WARNING == ret)
{
- return MHD_SC_OK; /* Success exit point */
+ if ((! s->tls_app_name.v_disable_fallback) &&
+ (! s->tls_openssl_def_file.v_disable_fallback))
+ return MHD_SC_OK; /* Load without configuration file */
+
+ ret = MHD_SC_TLS_DAEMON_INIT_FAILED;
}
}
+ mhd_assert (MHD_SC_TLS_LIB_CONF_WARNING != ret);
+
OSSL_LIB_CTX_free (d_tls->libctx);
mhd_LOG_MSG (d, MHD_SC_TLS_DAEMON_INIT_FAILED, \
"Failed to initialise TLS library context");
@@ -380,28 +694,23 @@ daemon_deinit_lib_ctx (struct mhd_TlsOpenDaemonData *restrict d_tls)
'h', '3' /* Registered value for HTTP/3 */
#endif /* Disabled code */
-#ifdef MHD_SUPPORT_HTTP2
-static const char alpn_code_http2[] = { mhd_ALPN_CODE_HTTP2 };
-#endif /* MHD_SUPPORT_HTTP2 */
-static const char alpn_code_http1_1[] = { mhd_ALPN_CODE_HTTP1_1 };
-static const char alpn_code_http1_0[] = { mhd_ALPN_CODE_HTTP1_0 };
#ifdef MHD_SUPPORT_HTTP2
static const unsigned char alpn_list_http2_1x[] = {
- sizeof(alpn_code_http2), mhd_ALPN_CODE_HTTP2
+ mhd_ALPN_H2_LEN, mhd_ALPN_CODE_HTTP2
,
- sizeof(alpn_code_http1_1), mhd_ALPN_CODE_HTTP1_1
+ mhd_ALPN_H1_1_LEN, mhd_ALPN_CODE_HTTP1_1
,
- sizeof(alpn_code_http1_0), mhd_ALPN_CODE_HTTP1_0
+ mhd_ALPN_H1_0_LEN, mhd_ALPN_CODE_HTTP1_0
};
static const unsigned char alpn_list_http2_only[] = {
- sizeof(alpn_code_http2), mhd_ALPN_CODE_HTTP2
+ mhd_ALPN_H2_LEN, mhd_ALPN_CODE_HTTP2
};
#endif /* MHD_SUPPORT_HTTP2 */
static const unsigned char alpn_list_http1x_only[] = {
- sizeof(alpn_code_http1_1), mhd_ALPN_CODE_HTTP1_1
+ mhd_ALPN_H1_1_LEN, mhd_ALPN_CODE_HTTP1_1
,
- sizeof(alpn_code_http1_0), mhd_ALPN_CODE_HTTP1_0
+ mhd_ALPN_H1_0_LEN, mhd_ALPN_CODE_HTTP1_0
};
#ifndef OPENSSL_NO_NEXTPROTONEG