libmicrohttpd2

HTTP server C library (MHD 2.x, alpha)
Log | Files | Refs | README | LICENSE

tls_open_funcs.c (89064B)


      1 /* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */
      2 /*
      3   This file is part of GNU libmicrohttpd.
      4   Copyright (C) 2024-2025 Evgeny Grin (Karlson2k)
      5 
      6   GNU libmicrohttpd is free software; you can redistribute it and/or
      7   modify it under the terms of the GNU Lesser General Public
      8   License as published by the Free Software Foundation; either
      9   version 2.1 of the License, or (at your option) any later version.
     10 
     11   GNU libmicrohttpd is distributed in the hope that it will be useful,
     12   but WITHOUT ANY WARRANTY; without even the implied warranty of
     13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14   Lesser General Public License for more details.
     15 
     16   Alternatively, you can redistribute GNU libmicrohttpd and/or
     17   modify it under the terms of the GNU General Public License as
     18   published by the Free Software Foundation; either version 2 of
     19   the License, or (at your option) any later version, together
     20   with the eCos exception, as follows:
     21 
     22     As a special exception, if other files instantiate templates or
     23     use macros or inline functions from this file, or you compile this
     24     file and link it with other works to produce a work based on this
     25     file, this file does not by itself cause the resulting work to be
     26     covered by the GNU General Public License. However the source code
     27     for this file must still be made available in accordance with
     28     section (3) of the GNU General Public License v2.
     29 
     30     This exception does not invalidate any other reasons why a work
     31     based on this file might be covered by the GNU General Public
     32     License.
     33 
     34   You should have received copies of the GNU Lesser General Public
     35   License and the GNU General Public License along with this library;
     36   if not, see <https://www.gnu.org/licenses/>.
     37 */
     38 
     39 /**
     40  * @file src/mhd2/tls_open_funcs.c
     41  * @brief  The implementation of OpenSSL wrapper functions
     42  * @author Karlson2k (Evgeny Grin)
     43  */
     44 
     45 #include "mhd_sys_options.h"
     46 
     47 #include "sys_bool_type.h"
     48 #include "sys_base_types.h"
     49 
     50 #include "compat_calloc.h"
     51 #include "sys_malloc.h"
     52 #include <string.h>
     53 
     54 #ifdef mhd_USE_TLS_DEBUG_MESSAGES
     55 #  include <stdio.h> /* For TLS debug printing */
     56 #endif
     57 
     58 #include "mhd_assert.h"
     59 #include "mhd_unreachable.h"
     60 #include "mhd_assume.h"
     61 #include "mhd_predict.h"
     62 
     63 #include "mhd_str.h"
     64 #include "mhd_str_types.h"
     65 #include "mhd_conn_socket.h"
     66 
     67 #include "mhd_tls_internal.h"
     68 
     69 #include "tls_open_tls_lib.h"
     70 
     71 #include "mhd_tls_ver_stct.h"
     72 
     73 #include "tls_open_daemon_data.h"
     74 #include "tls_open_conn_data.h"
     75 #include "tls_open_funcs.h"
     76 
     77 #include "daemon_options.h"
     78 
     79 #include "daemon_logger.h"
     80 
     81 #ifdef mhd_HAVE_OPENSSL_ACME
     82 #  include "mhd_tls_acme_func.h"
     83 #endif /* mhd_HAVE_OPENSSL_ACME */
     84 
     85 #include "microhttpd2_portability.h"
     86 #include "mhd_public_api.h"
     87 
     88 #if defined(HAVE_WUSED_BUT_MARKED_UNUSED) && defined(MHD_WARN_IGNORE_STYLE_GCC)
     89 #  define mhd_NOWARN_USED_UNUSED   \
     90           MHD_WARN_PUSH_ MHD_WARN_IGNORE_ ("-Wused-but-marked-unused")
     91 #  define mhd_RESTORE_WARN_USED_UNUSED MHD_WARN_POP_
     92 #else
     93 #  define mhd_NOWARN_USED_UNUSED   /* empty */
     94 #  define mhd_RESTORE_WARN_USED_UNUSED   /* empty */
     95 #endif
     96 
     97 #ifdef mhd_USE_TLS_DEBUG_MESSAGES
     98 
     99 static MHD_FN_PAR_NONNULL_ (1) int
    100 mhd_tls_open_dbg_print_errs (const char *msg,
    101                              size_t msg_len,
    102                              void *cls)
    103 {
    104   int ret;
    105   int print_size = (int)msg_len;
    106 
    107   (void)cls;  /* Not used */
    108 
    109   if ((print_size < 0)
    110       || (msg_len != (unsigned int)print_size))
    111     print_size = (int)((~((unsigned int)0u)) >> 1);
    112 
    113   ret = fprintf (stderr,
    114                  "## OpenSSL error: %.*s\n",
    115                  print_size, msg);
    116   (void)fflush (stderr);
    117   return ret;
    118 }
    119 
    120 
    121 #  define mhd_DBG_PRINT_TLS_ERRS() \
    122           ERR_print_errors_cb (&mhd_tls_open_dbg_print_errs, NULL)
    123 
    124 #  define mhd_DBG_PRINT_TLS_INFO_MSG(message) \
    125           do { (void) fprintf (stderr, "## OpenSSL info: %s\n", (message)); \
    126                (void) fflush (stderr);} while (0)
    127 #  define mhd_DBG_PRINT_TLS_INFO_PARAM1(message, param) \
    128      do { (void) fprintf (stderr, "## OpenSSL info: " message "\n", (param)); \
    129           (void) fflush (stderr);} while (0)
    130 #else
    131 #  define mhd_DBG_PRINT_TLS_ERRS()      ERR_clear_error ()
    132 #  define mhd_DBG_PRINT_TLS_INFO_MSG(message)       ((void) 0)
    133 #  define mhd_DBG_PRINT_TLS_INFO_PARAM1(message, param)  ((void) 0)
    134 #endif
    135 
    136 /* ** Global initialisation / de-initialisation ** */
    137 
    138 static bool openssl_lib_inited = false;
    139 
    140 #ifdef mhd_HAVE_OPENSSL_ACME
    141 /**
    142  * The index of the pointer to MHD connection TLS data in the "ex_data" storage
    143  * of the TLS session.
    144  * This leaves the "app_data" (index zero of the "ex_data" storage) for other
    145  * possible uses.
    146  */
    147 static int conn_mhd_ctls_idx = -1;
    148 #endif /* mhd_HAVE_OPENSSL_ACME */
    149 
    150 MHD_INTERNAL void
    151 mhd_tls_open_global_init_once (void)
    152 {
    153   const unsigned long ver_num = OpenSSL_version_num ();
    154   /* Make sure that used shared OpenSSL library has least the same version as
    155      MHD was configured for. Fail if the version is earlier. */
    156   openssl_lib_inited = ((0x900000UL < ver_num) /* Versions before 3.0 */
    157                         && (OPENSSL_VERSION_NUMBER <= ver_num));
    158 
    159   /* The call of OPENSSL_init_ssl() typically not needed, but it won't hurt
    160      if library was initialised automatically.
    161      In some exotic situations automatic initialisation could fail, and
    162      this call would make sure that the library is initialised before used. */
    163   openssl_lib_inited = openssl_lib_inited
    164                        && (0 < OPENSSL_init_ssl (0, NULL));
    165 
    166 #ifdef mhd_HAVE_OPENSSL_ACME
    167   if (openssl_lib_inited)
    168   {
    169     conn_mhd_ctls_idx = SSL_get_ex_new_index (0,
    170                                               NULL,
    171                                               NULL,
    172                                               NULL,
    173                                               NULL);
    174     openssl_lib_inited = (0 <= conn_mhd_ctls_idx);
    175   }
    176 #endif /* mhd_HAVE_OPENSSL_ACME */
    177 }
    178 
    179 
    180 MHD_INTERNAL MHD_FN_PURE_ bool
    181 mhd_tls_open_is_inited_fine (void)
    182 {
    183   return openssl_lib_inited;
    184 }
    185 
    186 
    187 /* ** Daemon initialisation / de-initialisation ** */
    188 
    189 /**
    190  * Check application-provided daemon TLS settings
    191  * @param d the daemon handle
    192  * @param sk_edge_trigg the sockets polling uses edge-triggering
    193  * @param s the application-provided settings
    194  * @return #MHD_SC_OK on success,
    195  *         error code otherwise
    196  */
    197 static MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode
    198 check_app_tls_settings (struct MHD_Daemon *restrict d,
    199                         bool sk_edge_trigg,
    200                         struct DaemonOptions *restrict s)
    201 {
    202   mhd_assert (MHD_TLS_BACKEND_NONE != s->tls);
    203   mhd_assert ((MHD_TLS_BACKEND_OPENSSL == s->tls) \
    204               || (MHD_TLS_BACKEND_ANY == s->tls));
    205   if (NULL == s->tls_cert_key.v_mem_cert)
    206   {
    207     mhd_LOG_MSG (d, MHD_SC_TLS_CONF_BAD_CERT, \
    208                  "No valid TLS certificate is provided");
    209     return MHD_SC_TLS_CONF_BAD_CERT;
    210   }
    211   mhd_assert (NULL != s->tls_cert_key.v_mem_key);
    212 
    213   if (sk_edge_trigg)
    214   {
    215     mhd_LOG_MSG (d, MHD_SC_TLS_BACKEND_DAEMON_INCOMPATIBLE_SETTINGS, \
    216                  "Edge-triggered sockets polling cannot be used "
    217                  "with OpenSSL backend");
    218     return MHD_SC_TLS_BACKEND_DAEMON_INCOMPATIBLE_SETTINGS;
    219   }
    220 
    221 #ifdef mhd_HAVE_TLS_ACME
    222   if (!mhd_tls_open_is_acme_alpn_supported (s)
    223       && s->acme_alpn_required)
    224   {
    225     mhd_LOG_MSG (d, MHD_SC_TLS_BACKEND_DAEMON_INCOMPATIBLE_SETTINGS,
    226                  "This build of OpenSSL backend does not support "
    227                  "ACME ALPN challenge protocol, but daemon settings "
    228                  "require it");
    229     return MHD_SC_TLS_BACKEND_DAEMON_INCOMPATIBLE_SETTINGS;
    230   }
    231 #endif
    232 
    233   return MHD_SC_OK;
    234 }
    235 
    236 
    237 /* Helper to prevent password prompts in terminal */
    238 static int
    239 null_passwd_cb (char *buf,
    240                 int size,
    241                 int rwflag,
    242                 void *cls)
    243 {
    244   (void)buf;
    245   (void)size;
    246   (void)rwflag;
    247   (void)cls;                                          /* Unused */
    248   mhd_DBG_PRINT_TLS_INFO_MSG ("The NULL passphrase callback is called\n");
    249   return 0;
    250 }
    251 
    252 
    253 /**
    254  * Create new empty OpenSSL library context
    255  * @param d the daemon handle
    256  * @param d_tls the daemon TLS settings
    257  * @return 'true' on success,
    258  *         'false' otherwise
    259  */
    260 static MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_ bool
    261 create_lib_ctx (struct MHD_Daemon *restrict d,
    262                 struct mhd_TlsOpenDaemonData *restrict d_tls)
    263 {
    264 #ifndef MHD_SUPPORT_LOG_FUNCTIONALITY
    265   (void)d;  /* Used for logging only */
    266 #endif /* MHD_SUPPORT_LOG_FUNCTIONALITY */
    267   mhd_assert (NULL == d_tls->libctx);
    268 
    269   d_tls->libctx = OSSL_LIB_CTX_new ();
    270 
    271   if (NULL == d_tls->libctx)
    272   {
    273     mhd_DBG_PRINT_TLS_ERRS ();
    274     mhd_LOG_MSG (d, MHD_SC_TLS_DAEMON_INIT_FAILED, \
    275                  "Failed to create TLS library context");
    276     return false;
    277   }
    278   return true;
    279 }
    280 
    281 
    282 /**
    283  * Reset OpenSSL library context.
    284  *
    285  * This function must not be called if library context is being used.
    286  * @param d the daemon handle
    287  * @param d_tls the daemon TLS settings
    288  * @return 'true' on success,
    289  *         'false' otherwise
    290  */
    291 static MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_ bool
    292 reset_lib_ctx (struct MHD_Daemon *restrict d,
    293                struct mhd_TlsOpenDaemonData *restrict d_tls)
    294 {
    295   mhd_assert (NULL != d_tls->libctx);
    296 
    297   OSSL_LIB_CTX_free (d_tls->libctx);
    298   d_tls->libctx = NULL;
    299 
    300   return create_lib_ctx (d,
    301                          d_tls);
    302 }
    303 
    304 
    305 /**
    306  * Get non-default pathname for OpenSSL configuration file
    307  * @param s the application-provided settings
    308  * @param[out] conf_pathname set to the pathname on success
    309  * @return #MHD_SC_OK on success,
    310  *         error code otherwise
    311  */
    312 static MHD_FN_PAR_NONNULL_ALL_
    313 MHD_FN_PAR_OUT_ (2) MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode
    314 daemon_get_conf_file (struct DaemonOptions *restrict s,
    315                       char **restrict conf_pathname)
    316 {
    317   size_t name_len;
    318   bool has_path;
    319 
    320   mhd_assert (NULL != s->tls_openssl_def_file.v_pathname);
    321 
    322 #ifndef MHD_SUPPORT_LOG_FUNCTIONALITY
    323   (void)d;  /* Used only for logging */
    324 #endif
    325 
    326   /* Handle custom pathname */
    327 
    328   name_len = strlen (s->tls_openssl_def_file.v_pathname);
    329   has_path = (NULL != memchr (s->tls_openssl_def_file.v_pathname,
    330                               '/',
    331                               name_len));
    332 #ifdef _WIN32
    333   has_path = has_path || (NULL != memchr (s->tls_openssl_def_file,
    334                                           '\\',
    335                                           name_len));
    336 #endif /* _WIN32 */
    337 
    338   if ((!has_path) && (0u != name_len))
    339   {
    340     const char *def_path;
    341     size_t def_path_len;
    342 
    343     def_path = X509_get_default_cert_area ();
    344     if (NULL == def_path)
    345     {
    346       mhd_DBG_PRINT_TLS_ERRS ();
    347       mhd_DBG_PRINT_TLS_INFO_MSG ("X509_get_default_cert_area() returned NULL");
    348       return MHD_SC_TLS_DAEMON_INIT_FAILED; /* Unrealistic */
    349     }
    350 
    351     def_path_len = strlen (def_path);
    352 
    353     *conf_pathname =
    354       (char *)OPENSSL_malloc (def_path_len + 1u + name_len + 1u);
    355     if (NULL == *conf_pathname)
    356       return MHD_SC_DAEMON_MEM_ALLOC_FAILURE;
    357 
    358     memcpy (*conf_pathname,
    359             def_path,
    360             def_path_len);
    361     (*conf_pathname)[def_path_len] = '/';
    362     memcpy ((*conf_pathname) + def_path_len + 1u,
    363             s->tls_openssl_def_file.v_pathname,
    364             name_len + 1u);
    365 
    366     return MHD_SC_OK;
    367   }
    368 
    369   *conf_pathname = (char *)OPENSSL_malloc (name_len + 1u);
    370   if (NULL == *conf_pathname)
    371     return MHD_SC_DAEMON_MEM_ALLOC_FAILURE;
    372 
    373   memcpy (*conf_pathname,
    374           s->tls_openssl_def_file.v_pathname,
    375           name_len + 1u);
    376 
    377   return MHD_SC_OK;
    378 }
    379 
    380 
    381 #ifdef mhd_TLS_OPEN_HAS_CONF_DIAG
    382 #  define mhd_LIBCTX_FORBIDS_FALLBACKS(d_tls) \
    383           (0 != OSSL_LIB_CTX_get_conf_diagnostics (d_tls->libctx))
    384 #else
    385 #  define mhd_LIBCTX_FORBIDS_FALLBACKS(d_tls)   ((void) (d_tls), ! ! 0)
    386 #endif /* ! mhd_TLS_OPEN_HAS_CONF_DIAG */
    387 
    388 
    389 static MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (2)
    390 MHD_FN_PAR_NONNULL_ (4) bool
    391 daemon_load_conf_from_cfg (struct MHD_Daemon *restrict d,
    392                            const char *restrict filename,
    393                            const char *restrict app_name,
    394                            CONF *restrict cfg,
    395                            unsigned long load_flags,
    396                            bool log_missing_app_name)
    397 {
    398 #ifndef MHD_SUPPORT_LOG_FUNCTIONALITY
    399   (void)d;  /* Used for logging only */
    400 #  ifndef mhd_USE_TLS_DEBUG_MESSAGES
    401   (void)filename;  /* Used for logs only */
    402 #  endif /* mhd_USE_TLS_DEBUG_MESSAGES */
    403 #endif /* MHD_SUPPORT_LOG_FUNCTIONALITY */
    404 
    405   if (NULL != app_name)
    406   {
    407     if (NULL == NCONF_get_string (cfg,
    408                                   NULL,
    409                                   app_name))
    410     {
    411       if (log_missing_app_name)
    412         mhd_LOG_PRINT (d,
    413                        MHD_SC_TLS_LIB_CONF_WARNING,
    414                        mhd_LOG_FMT ("TLS library configuration '%s' "
    415                                     "was not found in file '%s'"),
    416                        app_name,
    417                        filename);
    418       else
    419         mhd_DBG_PRINT_TLS_INFO_PARAM1 ("TLS library configuration '%s' "
    420                                        "was not found in the configuration "
    421                                        "file",
    422                                        app_name);
    423       return false;
    424     }
    425     mhd_DBG_PRINT_TLS_INFO_PARAM1 ("Trying to load configuration section "
    426                                    "pointed by '%s'",
    427                                    app_name);
    428   }
    429   else
    430     mhd_DBG_PRINT_TLS_INFO_MSG ("Trying to load configuration section "
    431                                 "pointed by default OpenSSL configuration");
    432 
    433   if (1 != CONF_modules_load (cfg,
    434                               app_name,
    435                               load_flags))
    436   {
    437     mhd_DBG_PRINT_TLS_ERRS ();
    438 
    439     mhd_LOG_PRINT (d,
    440                    MHD_SC_TLS_LIB_CONF_WARNING,
    441                    mhd_LOG_FMT ("Error loading TLS library "
    442                                 "configuration '%s' "
    443                                 "from file '%s'"),
    444                    app_name,
    445                    filename);
    446 
    447     return false;
    448   }
    449 
    450   mhd_DBG_PRINT_TLS_INFO_MSG ("Successfully loaded OpenSSL configuration "
    451                               "from the configuration file");
    452 
    453   return true;
    454 }
    455 
    456 
    457 static MHD_FN_PAR_NONNULL_ALL_
    458 MHD_FN_PAR_INOUT_ (2) MHD_FN_PAR_INOUT_ (4) bool
    459 cfg_reset_and_reload (struct MHD_Daemon *restrict d,
    460                       struct mhd_TlsOpenDaemonData *restrict d_tls,
    461                       const char *restrict filename,
    462                       CONF **restrict cfg_ptr)
    463 {
    464 #ifndef MHD_SUPPORT_LOG_FUNCTIONALITY
    465   (void)d;  /* Used for logging only */
    466 #endif /* MHD_SUPPORT_LOG_FUNCTIONALITY */
    467   mhd_assert (NULL != *cfg_ptr);
    468 
    469   mhd_DBG_PRINT_TLS_INFO_MSG ("Resetting library CTX, CONF and reloading "
    470                               "configuration file");
    471 
    472   /* Destroy old cfg, which is connected to the library CTX */
    473   NCONF_free (*cfg_ptr);
    474   *cfg_ptr = NULL;
    475 
    476   /* Reset OpenSSL library CTX, which may have partially applied configuration */
    477   if (!reset_lib_ctx (d,
    478                       d_tls))
    479     return false;
    480 
    481   /* Create a new cfg connected to the new CTX */
    482   *cfg_ptr = NCONF_new_ex (d_tls->libctx,
    483                            NULL);
    484   if (NULL == *cfg_ptr)
    485   {
    486     mhd_DBG_PRINT_TLS_ERRS ();
    487 
    488     mhd_DBG_PRINT_TLS_INFO_MSG ("Failed to create a new OpenSSL CONF");
    489     return false;
    490   }
    491 
    492   if (0 >= NCONF_load (*cfg_ptr,
    493                        filename,
    494                        NULL))
    495   {
    496     mhd_DBG_PRINT_TLS_ERRS ();
    497 
    498     mhd_DBG_PRINT_TLS_INFO_PARAM1 ("Failed to reload configuration file '%s'",
    499                                    filename);
    500     return false;
    501   }
    502 
    503   return true;
    504 }
    505 
    506 
    507 static inline MHD_FN_PAR_NONNULL_ALL_ bool
    508 is_conf_file_fallback_allowed (
    509   const struct mhd_TlsOpenDaemonData *restrict d_tls,
    510   const struct DaemonOptions *restrict s)
    511 {
    512   mhd_assert (NULL != d_tls->libctx);
    513 
    514   if (!s->tls_openssl_def_file.v_disable_fallback)
    515     return false;
    516   if (mhd_LIBCTX_FORBIDS_FALLBACKS (d_tls))
    517     return false;
    518   return true;
    519 }
    520 
    521 
    522 static inline MHD_FN_PAR_NONNULL_ALL_ bool
    523 is_conf_fallback_allowed (const struct mhd_TlsOpenDaemonData *restrict d_tls,
    524                           const struct DaemonOptions *restrict s)
    525 {
    526   if (!s->tls_app_name.v_disable_fallback)
    527     return false;
    528 
    529   return is_conf_file_fallback_allowed (d_tls,
    530                                         s);
    531 }
    532 
    533 
    534 /**
    535  * Load OpenSSL configuration from OpenSSL configuration file
    536  * @param d the daemon handle
    537  * @param d_tls the daemon TLS settings
    538  * @param s the application-provided settings
    539  * @param use_custom_conf_pathname choose application-provided pathname or
    540  *                                 TLS backend default pathname
    541  * @return #MHD_SC_OK on success,
    542  *         #MHD_SC_TLS_LIB_CONF_WARNING if configuration was not loaded due to
    543  *                                      non-fatal error,
    544  *         error code otherwise
    545  */
    546 static MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_NONNULL_ (3)
    547 MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode
    548 daemon_load_lib_conf (struct MHD_Daemon *restrict d,
    549                       struct mhd_TlsOpenDaemonData *restrict d_tls,
    550                       struct DaemonOptions *restrict s,
    551                       bool use_custom_conf_pathname)
    552 {
    553   char *conf_pathname;
    554   CONF *conf;
    555   enum MHD_StatusCode ret;
    556 
    557   if (!use_custom_conf_pathname)
    558   {
    559     /* Use default pathname */
    560     conf_pathname = CONF_get1_default_config_file ();
    561 
    562     if (NULL == conf_pathname)
    563     {
    564       mhd_DBG_PRINT_TLS_ERRS ();
    565 
    566       ret = is_conf_fallback_allowed (d_tls,
    567                                       s)
    568              ? MHD_SC_TLS_LIB_CONF_WARNING : MHD_SC_TLS_DAEMON_INIT_FAILED;
    569 
    570       mhd_LOG_MSG (d, ret, \
    571                    "Failed to get default configuration file pathname");
    572     }
    573     else
    574       ret = MHD_SC_OK;
    575   }
    576   else
    577     ret = daemon_get_conf_file (s,
    578                                 &conf_pathname);
    579 
    580   if (MHD_SC_OK != ret)
    581   {
    582     mhd_DBG_PRINT_TLS_INFO_MSG ("Failed to get configuration file pathname");
    583     return ret;
    584   }
    585 
    586   mhd_ASSUME (NULL != conf_pathname);
    587   mhd_DBG_PRINT_TLS_INFO_PARAM1 ("Trying '%s' as OpenSSL configuration file",
    588                                  conf_pathname);
    589 
    590   if ('\0' == conf_pathname[0])
    591   {
    592     OPENSSL_free (conf_pathname); /* A short-cut */
    593 
    594     if (NULL == s->tls_app_name.v_app_name)
    595       return MHD_SC_OK; /* No special "application name" profile is needed */
    596 
    597     if (!s->tls_app_name.v_disable_fallback)
    598       return MHD_SC_OK; /* Initialisation allowed with default values */
    599 
    600     /* Load of special "application name" profile is required */
    601 
    602     if (!use_custom_conf_pathname)
    603       return MHD_SC_TLS_DAEMON_INIT_FAILED; /* No fallback pathname */
    604 
    605     mhd_assert (NULL != s->tls_openssl_def_file.v_pathname);
    606 
    607     if (s->tls_openssl_def_file.v_disable_fallback)
    608       return MHD_SC_TLS_DAEMON_INIT_FAILED; /* Fallback pathname is disallowed */
    609 
    610     /* Try to use fallback pathname to load special "application name" profile */
    611     return MHD_SC_TLS_LIB_CONF_WARNING;
    612   }
    613 
    614   conf = NCONF_new_ex (d_tls->libctx,
    615                        NULL);
    616   if (NULL == conf)
    617   {
    618     mhd_DBG_PRINT_TLS_ERRS ();
    619 
    620     ret = is_conf_fallback_allowed (d_tls,
    621                                     s)
    622           ? MHD_SC_TLS_LIB_CONF_WARNING : MHD_SC_TLS_DAEMON_INIT_FAILED;
    623     mhd_LOG_MSG (d, ret, \
    624                  "Failed to create OpenSSL empty configuration object");
    625   }
    626 
    627   if (MHD_SC_OK == ret)
    628   {
    629     long err_line_num;
    630     mhd_DBG_PRINT_TLS_INFO_PARAM1 ("Trying to load configuration file '%s'",
    631                                    conf_pathname);
    632 
    633     if (0 >= NCONF_load (conf,
    634                          conf_pathname,
    635                          &err_line_num))
    636     {
    637       mhd_DBG_PRINT_TLS_ERRS ();
    638 
    639       if (use_custom_conf_pathname)
    640         ret = is_conf_file_fallback_allowed (d_tls,
    641                                              s)
    642               ? MHD_SC_TLS_LIB_CONF_WARNING : MHD_SC_TLS_DAEMON_INIT_FAILED;
    643       else
    644         ret = is_conf_fallback_allowed (d_tls,
    645                                         s)
    646               ? MHD_SC_TLS_LIB_CONF_WARNING : MHD_SC_TLS_DAEMON_INIT_FAILED;
    647 
    648       mhd_LOG_PRINT (d,
    649                      ret,
    650                      mhd_LOG_FMT ("Error loading TLS library configuration "
    651                                   "file '%s' at line %ld"),
    652                      conf_pathname,
    653                      err_line_num);
    654     }
    655 
    656     if (MHD_SC_OK == ret)
    657     {
    658       bool conf_loaded;
    659       unsigned long flags;
    660 
    661       flags = 0u;
    662       if (!s->tls_app_name.v_disable_fallback)
    663         flags |= CONF_MFLAGS_IGNORE_ERRORS;
    664 
    665       conf_loaded = false;
    666 
    667       if (NULL != s->tls_app_name.v_app_name)
    668       {
    669         char app_name_lc[128];
    670         const size_t app_name_len = strlen (s->tls_app_name.v_app_name);
    671 
    672         /* Checked at the parameter processing */
    673         mhd_ASSUME ((128u) > app_name_len);
    674 
    675         mhd_str_to_lowercase_bin_n (app_name_len + 1u, /* '+1' for zero termination */
    676                                     s->tls_app_name.v_app_name,
    677                                     app_name_lc);
    678 
    679         mhd_ASSUME ('\0' ==  app_name_lc[app_name_len]);
    680 
    681         conf_loaded =
    682           daemon_load_conf_from_cfg (d,
    683                                      conf_pathname,
    684                                      app_name_lc,
    685                                      conf,
    686                                      flags,
    687                                      s->tls_app_name.v_disable_fallback
    688                                      || mhd_LIBCTX_FORBIDS_FALLBACKS (d_tls));
    689 
    690         if (!conf_loaded)
    691         {
    692           if (s->tls_app_name.v_disable_fallback
    693               || mhd_LIBCTX_FORBIDS_FALLBACKS (d_tls))
    694             ret = MHD_SC_TLS_DAEMON_INIT_FAILED;
    695           else if (!cfg_reset_and_reload (d,
    696                                           d_tls,
    697                                           conf_pathname,
    698                                           &conf))
    699             ret = MHD_SC_TLS_DAEMON_INIT_FAILED;
    700         }
    701       }
    702 
    703       if (!conf_loaded
    704           && (MHD_SC_OK == ret))
    705       {
    706 
    707         mhd_assert ((NULL == s->tls_app_name.v_app_name)
    708                     || !s->tls_app_name.v_disable_fallback);
    709 
    710         conf_loaded =
    711           daemon_load_conf_from_cfg (d,
    712                                      conf_pathname,
    713                                      "libmicrohttpd",
    714                                      conf,
    715                                      flags,
    716                                      false);
    717         if ((!conf_loaded)
    718             && (!cfg_reset_and_reload (d,
    719                                        d_tls,
    720                                        conf_pathname,
    721                                        &conf)))
    722           ret = MHD_SC_TLS_DAEMON_INIT_FAILED;
    723       }
    724 
    725       if (!conf_loaded
    726           && (MHD_SC_OK == ret))
    727       {
    728 
    729         mhd_assert ((NULL == s->tls_app_name.v_app_name)
    730                     || !s->tls_app_name.v_disable_fallback);
    731 
    732         conf_loaded =
    733           daemon_load_conf_from_cfg (d,
    734                                      conf_pathname,
    735                                      NULL,
    736                                      conf,
    737                                      flags,
    738                                      true);
    739       }
    740 
    741       if (!conf_loaded)
    742         ret = MHD_SC_TLS_LIB_CONF_WARNING;
    743     }
    744 
    745     NCONF_free (conf); /* Explicitly safe with NULL */
    746   }
    747 
    748   OPENSSL_free (conf_pathname);
    749 
    750   return ret;
    751 }
    752 
    753 
    754 /**
    755  * Initialise OpenSSL library context
    756  * @param d the daemon handle
    757  * @param d_tls the daemon TLS settings
    758  * @param s the application-provided settings
    759  * @return #MHD_SC_OK on success,
    760  *         error code otherwise
    761  */
    762 static MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode
    763 daemon_init_lib_ctx (struct MHD_Daemon *restrict d,
    764                      struct mhd_TlsOpenDaemonData *restrict d_tls,
    765                      struct DaemonOptions *restrict s)
    766 {
    767   enum MHD_StatusCode ret;
    768 
    769   if (!create_lib_ctx (d, d_tls))
    770     return MHD_SC_TLS_DAEMON_INIT_FAILED;
    771 
    772   if (NULL != s->tls_openssl_def_file.v_pathname)
    773   {
    774     ret = daemon_load_lib_conf (d,
    775                                 d_tls,
    776                                 s,
    777                                 true);
    778 
    779     if (MHD_SC_OK == ret)
    780       return MHD_SC_OK;
    781 
    782     if (MHD_SC_TLS_LIB_CONF_WARNING == ret)
    783       ret = s->tls_openssl_def_file.v_disable_fallback
    784             ? MHD_SC_TLS_DAEMON_INIT_FAILED : MHD_SC_OK;
    785   }
    786   else
    787     ret = MHD_SC_OK;
    788 
    789   mhd_assert (MHD_SC_TLS_LIB_CONF_WARNING != ret);
    790 
    791   if (MHD_SC_OK == ret)
    792   {
    793     mhd_assert ((NULL == s->tls_openssl_def_file.v_pathname)
    794                 || !s->tls_openssl_def_file.v_disable_fallback);
    795 
    796     ret = daemon_load_lib_conf (d,
    797                                 d_tls,
    798                                 s,
    799                                 false);
    800 
    801     if (MHD_SC_OK == ret)
    802       return MHD_SC_OK;
    803 
    804     if (MHD_SC_TLS_LIB_CONF_WARNING == ret)
    805     {
    806       if ((!s->tls_app_name.v_disable_fallback)
    807           && (!s->tls_openssl_def_file.v_disable_fallback))
    808         return MHD_SC_OK; /* Load without configuration file */
    809 
    810       ret = MHD_SC_TLS_DAEMON_INIT_FAILED;
    811     }
    812   }
    813 
    814   mhd_assert (MHD_SC_TLS_LIB_CONF_WARNING != ret);
    815 
    816   OSSL_LIB_CTX_free (d_tls->libctx); /* Explicitly safe with NULL */
    817   mhd_LOG_MSG (d, MHD_SC_TLS_DAEMON_INIT_FAILED, \
    818                "Failed to initialise TLS library context");
    819   return MHD_SC_TLS_DAEMON_INIT_FAILED;
    820 }
    821 
    822 
    823 /**
    824  * De-initialise OpenSSL library context
    825  * @param d_tls the daemon TLS settings
    826  */
    827 static MHD_FN_PAR_NONNULL_ALL_ void
    828 daemon_deinit_lib_ctx (struct mhd_TlsOpenDaemonData *restrict d_tls)
    829 {
    830   mhd_assert (NULL != d_tls->libctx);
    831   OSSL_LIB_CTX_free (d_tls->libctx);
    832 }
    833 
    834 
    835 #define mhd_ALPN_CODE_HTTP1_0 \
    836    'h', 't', 't', 'p', '/', '1', '.', '0' /* Registered value for HTTP/1.0 */
    837 #define mhd_ALPN_CODE_HTTP1_1 \
    838    'h', 't', 't', 'p', '/', '1', '.', '1' /* Registered value for HTTP/1.1 */
    839 #ifdef MHD_SUPPORT_HTTP2
    840 #  define mhd_ALPN_CODE_HTTP2 \
    841           'h', '2' /* Registered value for HTTP/2 over TLS */
    842 #endif /* MHD_SUPPORT_HTTP2 */
    843 #if 0  /* Disabled code */
    844 #  define mhd_ALPN_CODE_HTTP3 \
    845           'h', '3' /* Registered value for HTTP/3 */
    846 #endif /* Disabled code */
    847 #ifdef mhd_HAVE_OPENSSL_ACME
    848 /* Registered value for ACME TLS-ALPN-01 challenge */
    849 #  define mhd_ALPN_CODE_ACME \
    850           'a', 'c', 'm', 'e', '-', 't', 'l', 's', '/', '1'
    851 #endif /* mhd_HAVE_OPENSSL_ACME */
    852 
    853 
    854 #ifdef MHD_SUPPORT_HTTP2
    855 static const unsigned char alpn_list_http2_1x[] = {
    856   mhd_ALPN_H2_LEN, mhd_ALPN_CODE_HTTP2
    857   ,
    858   mhd_ALPN_H1_1_LEN, mhd_ALPN_CODE_HTTP1_1
    859   ,
    860   mhd_ALPN_H1_0_LEN, mhd_ALPN_CODE_HTTP1_0
    861 };
    862 static const unsigned char alpn_list_http2_only[] = {
    863   mhd_ALPN_H2_LEN, mhd_ALPN_CODE_HTTP2
    864 };
    865 #endif /* MHD_SUPPORT_HTTP2 */
    866 static const unsigned char alpn_list_http1x_only[] = {
    867   mhd_ALPN_H1_1_LEN, mhd_ALPN_CODE_HTTP1_1
    868   ,
    869   mhd_ALPN_H1_0_LEN, mhd_ALPN_CODE_HTTP1_0
    870 };
    871 #ifdef mhd_HAVE_OPENSSL_ACME
    872 /* RFC 8737, section 3: the ACME TLS-ALPN-01 challenge is answered with
    873    the "acme-tls/1" protocol and no other protocol */
    874 static const unsigned char alpn_list_acme_only[] = {
    875   mhd_ALPN_ACME_LEN, mhd_ALPN_CODE_ACME
    876 };
    877 #endif /* mhd_HAVE_OPENSSL_ACME */
    878 
    879 #ifndef OPENSSL_NO_NEXTPROTONEG
    880 /**
    881  * Provide the list of supported protocols for NPN extension
    882  * @param sess the TLS session (ignored)
    883  * @param[out] out the pointer to get the location of the data
    884  * @param[out] outlen the size of the data provided
    885  * @param cls the closure (ignored)
    886  * @return always SSL_TLSEXT_ERR_OK
    887  */
    888 static int
    889 get_npn_list (SSL *sess,
    890               const unsigned char **out,
    891               unsigned int *outlen,
    892               void *cls)
    893 {
    894   struct mhd_TlsOpenDaemonData *const d_tls =
    895     (struct mhd_TlsOpenDaemonData *)cls;
    896   (void)sess;  /* Unused */
    897   *out = d_tls->alpn_prots;
    898   *outlen = d_tls->alpn_prots_size;
    899   return SSL_TLSEXT_ERR_OK;
    900 }
    901 
    902 
    903 #endif /* ! OPENSSL_NO_NEXTPROTONEG */
    904 
    905 /**
    906  * Select protocol from the provided list for ALPN extension
    907  * @param sess the TLS session
    908  * @param[out] out the pointer to get the location of selected protocol value
    909  * @param[out] outlen the size of the selected protocol value
    910  * @param in the list of protocols values provided by the client
    911  * @param inlen the size of the list of protocols values provided by the client
    912  * @param cls the closure (ignored)
    913  * @return SSL_TLSEXT_ERR_OK if matching protocol found and selected,
    914  *         SSL_TLSEXT_ERR_ALERT_FATAL otherwise
    915  */
    916 static int
    917 select_alpn_prot (SSL *sess,
    918                   const unsigned char **out,
    919                   unsigned char *outlen,
    920                   const unsigned char *in,
    921                   unsigned int inlen,
    922                   void *cls)
    923 {
    924   struct mhd_TlsOpenDaemonData *const restrict d_tls =
    925     (struct mhd_TlsOpenDaemonData *)cls;
    926 
    927 #ifdef mhd_HAVE_OPENSSL_ACME
    928   if (!0)
    929   {
    930     const struct mhd_TlsOpenConnData *const restrict c_tls =
    931       (const struct mhd_TlsOpenConnData *)SSL_get_ex_data (sess,
    932                                                            conn_mhd_ctls_idx);
    933     mhd_assert (NULL != c_tls);
    934 
    935     if (c_tls->is_acme)
    936     {
    937       /* ALPN has been checked: ACME TLS-ALPN-01 only */
    938       mhd_assert (inlen == (unsigned int)sizeof(alpn_list_acme_only));
    939       mhd_assert (0 == memcmp (in, alpn_list_acme_only, inlen));
    940 
    941       *out = alpn_list_acme_only + 1; /* Skip the length byte */
    942       *outlen = (unsigned char)mhd_ALPN_ACME_LEN;
    943       return SSL_TLSEXT_ERR_OK; /* Success */
    944     }
    945   }
    946 #else  /* ! mhd_HAVE_OPENSSL_ACME */
    947   (void)sess;   /* Unused */
    948 #endif /* ! mhd_HAVE_OPENSSL_ACME */
    949 
    950   if (OPENSSL_NPN_NEGOTIATED ==
    951       SSL_select_next_proto ((unsigned char **)mhd_DROP_CONST (out),
    952                              outlen,
    953                              in,
    954                              inlen,
    955                              d_tls->alpn_prots,
    956                              d_tls->alpn_prots_size))
    957     return SSL_TLSEXT_ERR_OK; /* Success */
    958 
    959   return SSL_TLSEXT_ERR_ALERT_FATAL; /* Failure */
    960 }
    961 
    962 
    963 #ifdef mhd_USE_OPENSSL_CLIENT_HELLO_GET0_EXT
    964 #  ifndef mhd_HAVE_OPENSSL_ACME
    965 #    error mhd_USE_OPENSSL_CLIENT_HELLO_GET0_EXT requires mhd_HAVE_OPENSSL_ACME
    966 #  endif /* ! mhd_HAVE_OPENSSL_ACME */
    967 #endif /* mhd_USE_OPENSSL_CLIENT_HELLO_GET0_EXT */
    968 
    969 #ifdef mhd_HAVE_OPENSSL_ACME
    970 
    971 /**
    972  * The TLS session ID context for the ACME ALPN challenge connections.
    973  * The value is not interpreted by the TLS library, it only has to differ from
    974  * the context used for the normal connections, which is the empty default one.
    975  */
    976 static const unsigned char acme_sid_ctx[] = { 'A', 'C', 'M', 'E' };
    977 
    978 
    979 /**
    980  * Callback to prevent storing of the ACME ALPN challenge session
    981  * @param sess the TLS session (unused)
    982  * @param is_forward_secure set to non-zero if the session is forward secure
    983  *                          (unused)
    984  * @return always non-zero, the session must not be stored
    985  */
    986 static int
    987 acme_sess_not_resumable (SSL *sess,
    988                          int is_forward_secure)
    989 {
    990   (void)sess;                 /* Unused */
    991   (void)is_forward_secure;    /* Unused */
    992   return !0;
    993 }
    994 
    995 
    996 /**
    997  * Exclude the connection from the TLS sessions resumption.
    998  *
    999  * The ACME certificate is set for the single connection, while a resumed
   1000  * handshake sends no certificate at all and the client keeps the certificate
   1001  * of the original session. Therefore both directions must be blocked:
   1002  * the session of this connection must not be stored, so that no normal
   1003  * connection could resume it and get the ACME certificate, and this connection
   1004  * must not resume any session stored for the normal connections, as it would
   1005  * get the daemon certificate instead of the ACME certificate.
   1006  *
   1007  * The session ID context must be set before the TLS library looks up
   1008  * the session requested by the client, the callback preventing the storing is
   1009  * used later.
   1010  *
   1011  * @param sess the TLS session to exclude from the sessions resumption
   1012  * @return 'true' on success,
   1013  *         'false' otherwise
   1014  */
   1015 static MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_ bool
   1016 mark_acme_no_resume (SSL *sess)
   1017 {
   1018   /* Any stored session has another session ID context, which is treated by
   1019      the TLS library as a cache miss */
   1020   if (0 == SSL_set_session_id_context (sess,
   1021                                        acme_sid_ctx,
   1022                                        (unsigned int)sizeof(acme_sid_ctx)))
   1023     return false;
   1024 
   1025   SSL_set_not_resumable_session_callback (sess,
   1026                                           &acme_sess_not_resumable);
   1027   return true;
   1028 }
   1029 
   1030 
   1031 /**
   1032  * Result of the application of the ACME ALPN challenge check to a connection
   1033  */
   1034 enum mhd_TlsOpenConnAcmeCheckFinishResult
   1035 {
   1036   /**
   1037    * The connection is prepared and the handshake can be continued, either as
   1038    * a normal HTTPS connection or as an ACME ALPN challenge connection
   1039    */
   1040   mhd_TLS_OPEN_ACME_CHECK_FINISH_OK = 0,
   1041   /**
   1042    * The TLS library failed to use the ACME credentials for the connection.
   1043    * The handshake must be aborted, the "internal error" alert matches
   1044    * the failure.
   1045    */
   1046   mhd_TLS_OPEN_ACME_CHECK_FINISH_ERROR,
   1047   /**
   1048    * The second ClientHello message, received after TLS 1.3 HelloRetryRequest,
   1049    * has been recognised differently than the first one.
   1050    * The handshake must be aborted, the "illegal parameter" alert matches
   1051    * the failure.
   1052    */
   1053   mhd_TLS_OPEN_ACME_CHECK_FINISH_MISMATCH_HRR
   1054 };
   1055 
   1056 
   1057 /**
   1058  * Apply the result of the ACME ALPN challenge check to the connection.
   1059  *
   1060  * If the ClientHello message has been recognised as the challenge, the ACME
   1061  * certificate, the private key and the certificates chain are set for
   1062  * the connection and the connection is excluded from the TLS sessions
   1063  * resumption. Otherwise only the state of the connection is updated, as
   1064  * the ALPN protocols for a normal HTTPS connection are set for the TLS
   1065  * context.
   1066  *
   1067  * The function must be called for every checked ClientHello message,
   1068  * including the second one received after TLS 1.3 HelloRetryRequest.
   1069  *
   1070  * @param[in,out] c_tls the connection TLS handle
   1071  * @param acme_certs the list of the ACME certificates used for the check
   1072  * @param acme_cred the credentials selected by the check,
   1073  *                  or NULL if the ClientHello message is not
   1074  *                  an ACME ALPN challenge
   1075  * @return #mhd_TLS_OPEN_ACME_CHECK_FINISH_OK if the handshake can be
   1076  *         continued,
   1077  *         other values if the handshake must be aborted
   1078  * @warning If @p acme_cred is not NULL, the list of the ACME certificates is
   1079  *          read-locked by the check and is unlocked by this function
   1080  */
   1081 static MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ (1)
   1082 MHD_FN_PAR_NONNULL_ (2) enum mhd_TlsOpenConnAcmeCheckFinishResult
   1083 mhd_tls_open_conn_acme_check_finish (
   1084   struct mhd_TlsOpenConnData *restrict c_tls,
   1085   struct mhd_TlsCertsList *restrict acme_certs,
   1086   const union mhd_TlsCredDataPtr *restrict acme_cred)
   1087 {
   1088   enum mhd_TlsOpenConnAcmeCheckFinishResult res;
   1089 
   1090   mhd_assert (NULL != c_tls);
   1091 
   1092   if (NULL == acme_cred)
   1093   {
   1094     /* Normal (not ACME ALPN challenge) connection */
   1095     if (c_tls->is_acme) /* Second ClientHello after TLS 1.3 HRR with another result */
   1096     {
   1097       mhd_assert (c_tls->clienthello_processed);
   1098       c_tls->is_acme = false; /* Reset to non-ACME connection */
   1099       return mhd_TLS_OPEN_ACME_CHECK_FINISH_MISMATCH_HRR; /* Unmatched ClientHello, abort handshake */
   1100     }
   1101 
   1102     /* Process the connection as a normal HTTPS connection. */
   1103     c_tls->clienthello_processed = true;
   1104     return mhd_TLS_OPEN_ACME_CHECK_FINISH_OK; /* Non-ACME connection exit point */
   1105   }
   1106 
   1107   /* Assume OK unless the checks below fail */
   1108   res = mhd_TLS_OPEN_ACME_CHECK_FINISH_OK;
   1109 
   1110   if (c_tls->clienthello_processed && !c_tls->is_acme)
   1111     res = mhd_TLS_OPEN_ACME_CHECK_FINISH_MISMATCH_HRR;
   1112 
   1113   if (mhd_TLS_OPEN_ACME_CHECK_FINISH_OK == res)
   1114   {
   1115     struct mhd_TlsOpenCredData *const restrict acme_open_cred =
   1116       acme_cred->open;
   1117 
   1118     mhd_assert (NULL != acme_open_cred);
   1119 
   1120     ERR_clear_error ();
   1121     /* Remove the daemon certificate: the certificate of another key type
   1122        would not be replaced by the ACME certificate and could be selected
   1123        by the TLS library instead of it. */
   1124     SSL_certs_clear (c_tls->sess);
   1125     /* The TLS library takes its own references for the objects, therefore
   1126        the ACME credentials could be removed by the application at any moment
   1127        after this point */
   1128     if (!mark_acme_no_resume (c_tls->sess)
   1129         || (0 >= SSL_use_certificate (c_tls->sess,
   1130                                       acme_open_cred->cert))
   1131         || (0 >= SSL_set1_chain (c_tls->sess,
   1132                                  acme_open_cred->chain))
   1133         || (0 >= SSL_use_PrivateKey (c_tls->sess,
   1134                                      acme_open_cred->key)))
   1135     {
   1136       mhd_DBG_PRINT_TLS_ERRS ();
   1137       res = mhd_TLS_OPEN_ACME_CHECK_FINISH_ERROR;
   1138     }
   1139   }
   1140   mhd_daemon_acme_cert_r_unlock (acme_certs);
   1141 
   1142   c_tls->clienthello_processed = true;
   1143   c_tls->is_acme = (mhd_TLS_OPEN_ACME_CHECK_FINISH_OK == res);
   1144   return res;
   1145 }
   1146 
   1147 
   1148 #  ifdef mhd_USE_OPENSSL_CLIENT_HELLO_GET0_EXT
   1149 
   1150 
   1151 /**
   1152  * Check whether the ClientHello message is the ACME TLS-ALPN-01 challenge and
   1153  * select the ACME credentials for the indicated domain.
   1154  *
   1155  * The extensions are taken from the ClientHello message parsed by the TLS
   1156  * library. The TLS library rejects any duplicated extension before this
   1157  * function is called.
   1158  *
   1159  * @param sess the TLS session processing the ClientHello message
   1160  * @param acme_certs the list of the ACME certificates to check against
   1161  * @return non-NULL if the ClientHello message is recognised as a TLS-ALPN-01
   1162  *         challenge and the ACME credentials are selected,
   1163  *         NULL otherwise
   1164  * @warning If a non-NULL pointer is returned, the daemon's ACME certificate
   1165  *          list remains read-locked and must be unlocked with
   1166  *          #mhd_daemon_acme_cert_r_unlock().
   1167  */
   1168 static MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_
   1169 const union mhd_TlsCredDataPtr *
   1170 clnthello_check_acme (SSL *sess,
   1171                       struct mhd_TlsCertsList *restrict acme_certs)
   1172 {
   1173   struct mhd_TlsClientHelloAcmeCheckData check;
   1174   bool all_checks_ok;
   1175 
   1176   mhd_tls_acme_check_ext_init (&check,
   1177                                acme_certs);
   1178 
   1179   all_checks_ok = true;
   1180 
   1181   /* The ALPN extension is checked first as it is checked without locking
   1182      the list of the ACME certificates. Any typical HTTPS ClientHello is
   1183      rejected by this check alone. */
   1184   if (all_checks_ok)
   1185   {
   1186     static const unsigned int ext_alpn_id =
   1187       TLSEXT_TYPE_application_layer_protocol_negotiation;
   1188     const unsigned char *ext_alpn_data;
   1189     size_t ext_alpn_size;
   1190 
   1191     all_checks_ok = (0 != SSL_client_hello_get0_ext (sess,
   1192                                                      ext_alpn_id,
   1193                                                      &ext_alpn_data,
   1194                                                      &ext_alpn_size));
   1195     if (all_checks_ok)
   1196       all_checks_ok = mhd_tls_acme_check_ext (ext_alpn_id,
   1197                                               ext_alpn_size,
   1198                                               ext_alpn_data,
   1199                                               &check);
   1200   }
   1201 
   1202   if (all_checks_ok)
   1203   {
   1204     static const unsigned int ext_sni_id = TLSEXT_TYPE_server_name;
   1205     const unsigned char *ext_sni_data;
   1206     size_t ext_sni_size;
   1207 
   1208     all_checks_ok = (0 != SSL_client_hello_get0_ext (sess,
   1209                                                      ext_sni_id,
   1210                                                      &ext_sni_data,
   1211                                                      &ext_sni_size));
   1212     if (all_checks_ok)
   1213       all_checks_ok = mhd_tls_acme_check_ext (ext_sni_id,
   1214                                               ext_sni_size,
   1215                                               ext_sni_data,
   1216                                               &check);
   1217   }
   1218 
   1219   /* The TLS library parsed the complete ClientHello message before calling
   1220      this function, no need to make additional check for parse completeness */
   1221   return mhd_tls_acme_check_ext_finish (&check,
   1222                                         all_checks_ok);
   1223 }
   1224 
   1225 
   1226 /**
   1227  * The TLS library callback for checking the ClientHello message for
   1228  * the ACME ALPN challenge.
   1229  *
   1230  * The callback is registered for the TLS context as the TLS library has no
   1231  * session-specific version of this callback.
   1232  *
   1233  * @param sess the TLS session processing the ClientHello message
   1234  * @param[out] alert the TLS alert to send if the handshake is aborted
   1235  * @param cls the closure, the pointer to the daemon TLS settings
   1236  * @return #SSL_CLIENT_HELLO_SUCCESS for a normal HTTPS ClientHello or after
   1237  *         successful ACME setup,
   1238  *         #SSL_CLIENT_HELLO_ERROR to abort the handshake otherwise
   1239  */
   1240 static int
   1241 check_clnt_hello_cb (SSL *sess,
   1242                      int *alert,
   1243                      void *cls)
   1244 {
   1245   struct mhd_TlsOpenDaemonData *const restrict d_tls =
   1246     (struct mhd_TlsOpenDaemonData *)cls;
   1247   struct mhd_TlsOpenConnData *const restrict c_tls =
   1248     (struct mhd_TlsOpenConnData *)SSL_get_ex_data (sess,
   1249                                                    conn_mhd_ctls_idx);
   1250   const union mhd_TlsCredDataPtr *acme_cred; /* Set to non-NULL if request is recognised ACME challenge */
   1251   enum mhd_TlsOpenConnAcmeCheckFinishResult res;
   1252 
   1253   mhd_assert (NULL != c_tls);
   1254   mhd_assert (c_tls->sess == sess);
   1255 
   1256   acme_cred = NULL;
   1257   if (mhd_daemon_has_acme_certs (d_tls->acme_certs))
   1258     acme_cred = clnthello_check_acme (sess,
   1259                                       d_tls->acme_certs);
   1260 
   1261   res = mhd_tls_open_conn_acme_check_finish (c_tls,
   1262                                              d_tls->acme_certs,
   1263                                              acme_cred);
   1264 
   1265   switch (res)
   1266   {
   1267   case mhd_TLS_OPEN_ACME_CHECK_FINISH_OK:
   1268     return SSL_CLIENT_HELLO_SUCCESS;   /* Success exit point */
   1269 
   1270   case mhd_TLS_OPEN_ACME_CHECK_FINISH_ERROR:
   1271     *alert = SSL_AD_INTERNAL_ERROR;
   1272     break;
   1273 
   1274   case mhd_TLS_OPEN_ACME_CHECK_FINISH_MISMATCH_HRR:
   1275     *alert = SSL_AD_ILLEGAL_PARAMETER;
   1276     break;
   1277 
   1278   default:
   1279     mhd_UNREACHABLE ();
   1280     *alert = SSL_AD_INTERNAL_ERROR;
   1281     break;
   1282   }
   1283 
   1284   return SSL_CLIENT_HELLO_ERROR; /* Failure exit point */
   1285 }
   1286 
   1287 
   1288 #  else  /* ! mhd_USE_OPENSSL_CLIENT_HELLO_GET0_EXT */
   1289 
   1290 /**
   1291  * Callback to abort the TLS handshake.
   1292  *
   1293  * The messages callback cannot report any failure, therefore this callback is
   1294  * set by the messages callback when the handshake must be aborted. The TLS
   1295  * library calls it after the ClientHello message has been processed and
   1296  * before the response is constructed.
   1297  *
   1298  * @param sess the TLS session (unused)
   1299  * @param cls the closure (unused)
   1300  * @return always zero, the handshake is aborted with the "internal error"
   1301  *         alert
   1302  */
   1303 static int
   1304 cert_cb_always_fail (SSL *sess,
   1305                      void *cls)
   1306 {
   1307   (void)sess;   /* Unused */
   1308   (void)cls;    /* Unused */
   1309   return 0;
   1310 }
   1311 
   1312 
   1313 /**
   1314  * The TLS library callback for checking the ClientHello message for
   1315  * the ACME ALPN challenge.
   1316  *
   1317  * The callback is set for the session, but only when the daemon has any ACME
   1318  * certificate. The body of the ClientHello message is parsed by MHD.
   1319  *
   1320  * The callback removes itself as soon as no ClientHello message can be
   1321  * received on the connection any more.
   1322  *
   1323  * @param write_p zero if the message is received, non-zero if it is sent
   1324  * @param version the TLS protocol version (unused)
   1325  * @param content_type the type of the record carrying the message
   1326  * @param buf the message data, including the handshake header
   1327  * @param len the size of the data pointed by @a buf
   1328  * @param sess the TLS session processing the message
   1329  * @param cls the closure, the list of the ACME certificates
   1330  */
   1331 static void
   1332 check_hello_msg_acme (int write_p,
   1333                       int version,
   1334                       int content_type,
   1335                       const void *buf,
   1336                       size_t len,
   1337                       SSL *sess,
   1338                       void *cls)
   1339 {
   1340   struct mhd_TlsCertsList *const restrict acme_certs =
   1341     (struct mhd_TlsCertsList *)cls;
   1342   struct mhd_TlsOpenConnData *const restrict c_tls =
   1343     (struct mhd_TlsOpenConnData *)SSL_get_ex_data (sess,
   1344                                                    conn_mhd_ctls_idx);
   1345   const unsigned char *const restrict msg = (const unsigned char *)buf;
   1346   const union mhd_TlsCredDataPtr *acme_cred; /* Set to non-NULL if request is recognised ACME challenge */
   1347 
   1348   (void)version;   /* Unused */
   1349   mhd_assert (NULL != c_tls);
   1350   mhd_assert (c_tls->sess == sess);
   1351 
   1352   if ((0 != write_p) || (SSL3_RT_HANDSHAKE != content_type))
   1353     return; /* Not an incoming handshake message */
   1354 
   1355   /* The first byte of the handshake header is the type of the message,
   1356      the body of the message follows the header */
   1357   if ((((size_t)SSL3_HM_HEADER_LENGTH) >= len)
   1358       || (SSL3_MT_CLIENT_HELLO != msg[0]))
   1359   {
   1360     /* The client has sent another handshake message, no ClientHello can be
   1361        received on this connection any more: TLS1.3 has no renegotiation and
   1362        TLS1.2 renegotiation is rejected by #SSL_OP_NO_RENEGOTIATION */
   1363     SSL_set_msg_callback (sess,
   1364                           NULL);
   1365     return;
   1366   }
   1367 
   1368   /* If this is the second ClientHello then stop the callback,
   1369      the TLS library accepts no more ClientHello */
   1370   if (c_tls->clienthello_processed)
   1371     SSL_set_msg_callback (sess,
   1372                           NULL);
   1373 
   1374   acme_cred =
   1375     mhd_tls_acme_check_clienthello_body (len - SSL3_HM_HEADER_LENGTH,
   1376                                          msg + SSL3_HM_HEADER_LENGTH,
   1377                                          acme_certs);
   1378 
   1379   if (mhd_TLS_OPEN_ACME_CHECK_FINISH_OK !=
   1380       mhd_tls_open_conn_acme_check_finish (c_tls,
   1381                                            acme_certs,
   1382                                            acme_cred))
   1383   {
   1384     /* This callback cannot abort the handshake, the abort is performed by
   1385        the certificates callback after the ClientHello message is processed.
   1386        The alert cannot be selected this way: the client always receives
   1387        the "internal error" alert. The "illegal parameter" alert, used for
   1388        the unmatched ClientHello when the ClientHello callback is available,
   1389        is not delivered to the client. */
   1390     SSL_set_cert_cb (sess,
   1391                      &cert_cb_always_fail,
   1392                      NULL);
   1393   }
   1394 }
   1395 
   1396 
   1397 #  endif /* ! mhd_USE_OPENSSL_CLIENT_HELLO_GET0_EXT */
   1398 
   1399 #endif /* mhd_HAVE_OPENSSL_ACME */
   1400 
   1401 /**
   1402  * Initialise TLS server context
   1403  * @param d the daemon handle
   1404  * @param d_tls the daemon TLS settings
   1405  * @param s the application-provided settings
   1406  * @return #MHD_SC_OK on success,
   1407  *         error code otherwise
   1408  */
   1409 static MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode
   1410 daemon_init_ctx (struct MHD_Daemon *restrict d,
   1411                  struct mhd_TlsOpenDaemonData *restrict d_tls,
   1412                  struct DaemonOptions *restrict s)
   1413 {
   1414   uint64_t ctx_opts;
   1415 
   1416 #ifndef MHD_SUPPORT_LOG_FUNCTIONALITY
   1417   (void)d;  /* Mute compiler warning */
   1418 #endif
   1419   (void)s;  // TODO: support configuration options
   1420 
   1421   mhd_assert (NULL != d_tls->libctx);
   1422 
   1423   ERR_clear_error ();
   1424 
   1425   d_tls->ctx = SSL_CTX_new_ex (d_tls->libctx,
   1426                                NULL,
   1427                                TLS_server_method ());
   1428   if (NULL == d_tls->ctx)
   1429   {
   1430     mhd_DBG_PRINT_TLS_ERRS ();
   1431     mhd_LOG_MSG (d, MHD_SC_TLS_DAEMON_INIT_FAILED, \
   1432                  "Failed to initialise TLS server context");
   1433     return MHD_SC_TLS_DAEMON_INIT_FAILED;
   1434   }
   1435 
   1436   /* Enable some safe and useful workarounds */
   1437   ctx_opts = SSL_OP_SAFARI_ECDHE_ECDSA_BUG | SSL_OP_TLSEXT_PADDING;
   1438 
   1439   // TODO: add configuration option
   1440   // ctx_opts |= SSL_OP_CIPHER_SERVER_PREFERENCE;
   1441 
   1442 #ifndef OPENSSL_NO_KTLS
   1443   /* Enable kernel TLS */ // TODO: add configuration option
   1444   ctx_opts |= SSL_OP_ENABLE_KTLS;
   1445 #  ifdef SSL_OP_ENABLE_KTLS_TX_ZEROCOPY_SENDFILE
   1446   ctx_opts |= SSL_OP_ENABLE_KTLS_TX_ZEROCOPY_SENDFILE;
   1447 #  endif
   1448 #endif
   1449 
   1450   /* HTTP defines strict framing for the client-side data,
   1451      no risk of attack on server on unexpected connection interruption */
   1452   /* ctx_opts |= SSL_OP_IGNORE_UNEXPECTED_EOF; */ // TODO: recheck
   1453 
   1454   /* There is no reason to use re-negotiation with HTTP */
   1455   ctx_opts |= SSL_OP_NO_RENEGOTIATION;
   1456 
   1457   /* Do not use TLS 1.3 resumption for now */
   1458   ctx_opts |= SSL_OP_NO_TICKET;
   1459 
   1460   (void)SSL_CTX_set_options (d_tls->ctx,
   1461                              ctx_opts);
   1462 
   1463   /* Prevent interactive password prompts */
   1464   SSL_CTX_set_default_passwd_cb (d_tls->ctx,
   1465                                  &null_passwd_cb);
   1466 
   1467   // TODO: make the setting configurable
   1468   /* SSL_CTX_set_security_level (d_tls->ctx, 0); */
   1469 
   1470   /* recv()- and send()-related options */
   1471   (void)SSL_CTX_set_mode (d_tls->ctx,
   1472                           SSL_MODE_ENABLE_PARTIAL_WRITE
   1473                           | SSL_MODE_AUTO_RETRY);
   1474   (void)SSL_CTX_clear_mode (d_tls->ctx,
   1475                             SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER
   1476                             | SSL_MODE_ASYNC);
   1477 
   1478   SSL_CTX_set_read_ahead (d_tls->ctx,
   1479                           !0);
   1480 
   1481   /* ALPN and NPN */
   1482   // TODO: use daemon option to disable ALPN
   1483   // TODO: use daemon option to select protocols for ALPN
   1484 #ifdef MHD_SUPPORT_HTTP2
   1485   if (1 /* enabled both HTTP/2 and HTTP/1.x */)
   1486   {
   1487     d_tls->alpn_prots = alpn_list_http2_1x;
   1488     d_tls->alpn_prots_size = sizeof(alpn_list_http2_1x);
   1489   }
   1490   else if (0 /* HTTP/2 only */)
   1491   {
   1492     d_tls->alpn_prots = alpn_list_http2_only;
   1493     d_tls->alpn_prots_size = sizeof(alpn_list_http2_only);
   1494   }
   1495   else
   1496 #endif /* MHD_SUPPORT_HTTP2 */
   1497   if (1 /* HTTP/1.x only */)
   1498   {
   1499     d_tls->alpn_prots = alpn_list_http1x_only;
   1500     d_tls->alpn_prots_size = sizeof(alpn_list_http1x_only);
   1501   }
   1502   else
   1503   {
   1504     mhd_UNREACHABLE ();
   1505   }
   1506   SSL_CTX_set_alpn_select_cb (d_tls->ctx,
   1507                               &select_alpn_prot,
   1508                               d_tls);
   1509 #ifdef mhd_USE_OPENSSL_CLIENT_HELLO_GET0_EXT
   1510   /* The ACME ALPN challenge is detected by the ClientHello message.
   1511      The callback is set unconditionally as OpenSSL does not allow to set
   1512      it on connection (session) basis. */
   1513   SSL_CTX_set_client_hello_cb (d_tls->ctx,
   1514                                &check_clnt_hello_cb,
   1515                                d_tls);
   1516 #endif /* mhd_USE_OPENSSL_CLIENT_HELLO_GET0_EXT */
   1517 #ifndef OPENSSL_NO_NEXTPROTONEG
   1518   SSL_CTX_set_next_protos_advertised_cb (d_tls->ctx,
   1519                                          &get_npn_list,
   1520                                          d_tls);
   1521 #endif /* ! OPENSSL_NO_NEXTPROTONEG */
   1522 
   1523   return MHD_SC_OK;
   1524 }
   1525 
   1526 
   1527 /**
   1528  * De-initialise TLS server context
   1529  * @param d_tls the daemon TLS settings
   1530  */
   1531 static MHD_FN_PAR_NONNULL_ALL_ void
   1532 daemon_deinit_ctx (struct mhd_TlsOpenDaemonData *restrict d_tls)
   1533 {
   1534   mhd_assert (NULL != d_tls->ctx);
   1535   SSL_CTX_free (d_tls->ctx);
   1536 }
   1537 
   1538 
   1539 /**
   1540  * Load the certificates chain from the OpenSSL BIO
   1541  * @param d the daemon handle
   1542  * @param d_tls the daemon TLS settings
   1543  * @param bio the certificates chain data opened in OpenSSL BIO
   1544  * @return #MHD_SC_OK on success,
   1545  *         error code otherwise
   1546  */
   1547 static MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode
   1548 daemon_load_certs_chain_obio (struct MHD_Daemon *restrict d,
   1549                               struct mhd_TlsOpenDaemonData *restrict d_tls,
   1550                               BIO *restrict bio)
   1551 {
   1552   enum MHD_StatusCode ret;
   1553   X509 *cert;
   1554 
   1555   ret = MHD_SC_OK;
   1556 
   1557   /* The certificate object must be pre-allocated to associate it with
   1558    * the lib context */
   1559   cert = X509_new_ex (d_tls->libctx,
   1560                       NULL);
   1561   if (NULL == cert)
   1562   {
   1563     mhd_DBG_PRINT_TLS_ERRS ();
   1564     mhd_LOG_MSG (d, MHD_SC_TLS_DAEMON_INIT_FAILED, \
   1565                  "Failed to create new certificate object");
   1566     return MHD_SC_TLS_DAEMON_INIT_FAILED;
   1567   }
   1568 
   1569   if (NULL == PEM_read_bio_X509_AUX (bio,
   1570                                      &cert,
   1571                                      &null_passwd_cb,
   1572                                      NULL))
   1573   {
   1574     mhd_DBG_PRINT_TLS_ERRS ();
   1575     mhd_LOG_MSG (d, MHD_SC_TLS_DAEMON_INIT_FAILED, \
   1576                  "Failed to process the certificate");
   1577     ret = MHD_SC_TLS_DAEMON_INIT_FAILED;
   1578   }
   1579   else
   1580   {
   1581     if (0 >= SSL_CTX_use_certificate (d_tls->ctx,
   1582                                       cert))
   1583     {
   1584       mhd_DBG_PRINT_TLS_ERRS ();
   1585       mhd_LOG_MSG (d, MHD_SC_TLS_DAEMON_INIT_FAILED, \
   1586                    "Failed to set the certificate");
   1587       ret = MHD_SC_TLS_DAEMON_INIT_FAILED;
   1588     }
   1589     else
   1590     {
   1591       if (0 != ERR_peek_error ())
   1592         mhd_DBG_PRINT_TLS_ERRS ();
   1593     }
   1594   }
   1595   /* Free certificate: if it was successfully read, it has been "copied" to CTX */
   1596   X509_free (cert);
   1597   if (MHD_SC_OK != ret)
   1598     return ret;
   1599 
   1600   do
   1601   {
   1602     X509 *inter_ca; /* Certifying certificate */
   1603     inter_ca = X509_new_ex (d_tls->libctx,
   1604                             NULL);
   1605     if (NULL == inter_ca)
   1606     {
   1607       mhd_DBG_PRINT_TLS_ERRS ();
   1608       mhd_LOG_MSG (d, MHD_SC_TLS_DAEMON_INIT_FAILED, \
   1609                    "Failed to create new chain certificate object");
   1610       return MHD_SC_TLS_DAEMON_INIT_FAILED;
   1611     }
   1612     if (NULL == PEM_read_bio_X509 (bio,
   1613                                    &inter_ca,
   1614                                    &null_passwd_cb,
   1615                                    NULL))
   1616     {
   1617       unsigned long err;
   1618       err = ERR_peek_last_error ();
   1619 
   1620       mhd_NOWARN_USED_UNUSED
   1621 
   1622       if ((ERR_LIB_PEM == ERR_GET_LIB (err))
   1623           && (PEM_R_NO_START_LINE == ERR_GET_REASON (err)))
   1624       {
   1625         /* End of data */
   1626         ERR_clear_error ();
   1627         X509_free (inter_ca); /* Empty, not needed */
   1628 
   1629         mhd_assert (MHD_SC_OK == ret);
   1630         return MHD_SC_OK; /* Success exit point */
   1631       }
   1632 
   1633       mhd_RESTORE_WARN_USED_UNUSED
   1634       mhd_DBG_PRINT_TLS_ERRS ();
   1635 
   1636       mhd_LOG_MSG (d, MHD_SC_TLS_DAEMON_INIT_FAILED, \
   1637                    "Failed to load next object in the certificates " \
   1638                    "chain");
   1639       ret = MHD_SC_TLS_DAEMON_INIT_FAILED;
   1640     }
   1641     else
   1642     {
   1643       if (SSL_CTX_add0_chain_cert (d_tls->ctx,
   1644                                    inter_ca))
   1645       {
   1646         /* Success, do not free the certificate as
   1647          * function '_add0_' was used to add it. */
   1648         /* Read the next certificate in the chain. */
   1649         continue;
   1650       }
   1651 
   1652       mhd_DBG_PRINT_TLS_ERRS ();
   1653       mhd_LOG_MSG (d, MHD_SC_TLS_DAEMON_INIT_FAILED, \
   1654                    "Failed to add the new certificate object "
   1655                    "to the chain");
   1656       ret = MHD_SC_TLS_DAEMON_INIT_FAILED;
   1657     }
   1658 
   1659     X509_free (inter_ca); /* Failed, the object is not needed */
   1660     mhd_assert (MHD_SC_OK != ret);
   1661   } while (MHD_SC_OK == ret);
   1662   mhd_assert (MHD_SC_OK != ret);
   1663   return ret;
   1664 }
   1665 
   1666 
   1667 /**
   1668  * Load the certificates chain based on application-provided settings
   1669  * @param d the daemon handle
   1670  * @param d_tls the daemon TLS settings
   1671  * @param s the application-provided settings
   1672  * @return #MHD_SC_OK on success,
   1673  *         error code otherwise
   1674  */
   1675 static MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode
   1676 daemon_load_certs_chain (struct MHD_Daemon *restrict d,
   1677                          struct mhd_TlsOpenDaemonData *restrict d_tls,
   1678                          struct DaemonOptions *restrict s)
   1679 {
   1680   enum MHD_StatusCode ret;
   1681   BIO *m_bio;
   1682 
   1683   mhd_assert (NULL != d_tls->libctx);
   1684   mhd_assert (NULL != d_tls->ctx);
   1685 
   1686   ERR_clear_error ();
   1687 
   1688   m_bio = BIO_new_mem_buf (s->tls_cert_key.v_mem_cert,
   1689                            -1);
   1690   if (NULL == m_bio)
   1691   {
   1692     mhd_DBG_PRINT_TLS_ERRS ();
   1693     return MHD_SC_DAEMON_MEM_ALLOC_FAILURE;
   1694   }
   1695   ret = daemon_load_certs_chain_obio (d,
   1696                                       d_tls,
   1697                                       m_bio);
   1698   BIO_free (m_bio);
   1699   return ret;
   1700 }
   1701 
   1702 
   1703 /**
   1704  * Initialise TLS certificate
   1705  * The function loads the certificate chain and the private key.
   1706  * @param d the daemon handle
   1707  * @param d_tls the daemon TLS settings
   1708  * @param s the application-provided settings
   1709  * @return #MHD_SC_OK on success,
   1710  *         error code otherwise
   1711  */
   1712 static MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode
   1713 daemon_init_cert (struct MHD_Daemon *restrict d,
   1714                   struct mhd_TlsOpenDaemonData *restrict d_tls,
   1715                   struct DaemonOptions *restrict s)
   1716 {
   1717   enum MHD_StatusCode ret;
   1718   BIO *m_bio;
   1719   EVP_PKEY *pr_key;
   1720   int res_i;
   1721   long res_l;
   1722 
   1723   mhd_assert (NULL != d_tls->libctx);
   1724   mhd_assert (NULL != d_tls->ctx);
   1725 
   1726   ERR_clear_error ();
   1727 
   1728   ret = daemon_load_certs_chain (d,
   1729                                  d_tls,
   1730                                  s);
   1731   if (MHD_SC_OK != ret)
   1732     return ret;
   1733 
   1734   /* Check and cache the certificates chain.
   1735      This also prevents automatic chain re-building for each session. */
   1736   res_l =
   1737     SSL_CTX_build_cert_chain (
   1738       d_tls->ctx,
   1739       SSL_BUILD_CHAIN_FLAG_CHECK /* Use only certificates in the chain */
   1740       | SSL_BUILD_CHAIN_FLAG_UNTRUSTED /* Intermediate CA certs does not need to be trusted */
   1741       | SSL_BUILD_CHAIN_FLAG_NO_ROOT /* The root CA should not be added to the chain */
   1742       | SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR /* Allow the root CA to be not trusted */
   1743       );
   1744   if (0 >= res_l)
   1745   {
   1746     mhd_DBG_PRINT_TLS_ERRS ();
   1747     mhd_LOG_MSG (d, MHD_SC_TLS_DAEMON_INIT_FAILED, \
   1748                  "Failed rebuild certificate chain");
   1749     return MHD_SC_TLS_DAEMON_INIT_FAILED;
   1750   }
   1751   if (2 == res_l)
   1752     mhd_DBG_PRINT_TLS_ERRS ();
   1753 
   1754   m_bio = BIO_new_mem_buf (s->tls_cert_key.v_mem_key,
   1755                            -1);
   1756   if (NULL == m_bio)
   1757   {
   1758     mhd_DBG_PRINT_TLS_ERRS ();
   1759     return MHD_SC_DAEMON_MEM_ALLOC_FAILURE;
   1760   }
   1761   pr_key =
   1762     PEM_read_bio_PrivateKey_ex (m_bio,
   1763                                 NULL,
   1764                                 NULL == s->tls_cert_key.v_mem_pass ?
   1765                                 &null_passwd_cb : NULL,
   1766                                 mhd_DROP_CONST (s->tls_cert_key.v_mem_pass),
   1767                                 d_tls->libctx,
   1768                                 NULL);
   1769   BIO_free (m_bio);
   1770   if (NULL == pr_key)
   1771   {
   1772     mhd_DBG_PRINT_TLS_ERRS ();
   1773     mhd_LOG_MSG (d, MHD_SC_TLS_DAEMON_INIT_FAILED, \
   1774                  "Failed to read the private key");
   1775     return MHD_SC_TLS_DAEMON_INIT_FAILED;
   1776   }
   1777 
   1778   res_i = SSL_CTX_use_PrivateKey (d_tls->ctx,
   1779                                   pr_key);
   1780   EVP_PKEY_free (pr_key); /* The key has been "copied" or failed */
   1781   if (1 != res_i)
   1782   {
   1783     mhd_DBG_PRINT_TLS_ERRS ();
   1784     mhd_LOG_MSG (d, MHD_SC_TLS_DAEMON_INIT_FAILED, \
   1785                  "Failed to set the private key");
   1786     return MHD_SC_TLS_DAEMON_INIT_FAILED;
   1787   }
   1788   /* This actually RE-checks the key.
   1789      The key should be already checked automatically when it was set after
   1790      setting the certificate. */
   1791   if (1 != SSL_CTX_check_private_key (d_tls->ctx))
   1792   {
   1793     mhd_DBG_PRINT_TLS_ERRS ();
   1794     mhd_LOG_MSG (d, MHD_SC_TLS_DAEMON_INIT_FAILED, \
   1795                  "The private key does not match the certificate");
   1796     return MHD_SC_TLS_DAEMON_INIT_FAILED;
   1797   }
   1798 
   1799   return MHD_SC_OK;
   1800 }
   1801 
   1802 
   1803 MHD_INTERNAL MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_
   1804 MHD_FN_PAR_OUT_ (4) mhd_StatusCodeInt
   1805 mhd_tls_open_daemon_init (struct MHD_Daemon *restrict d,
   1806                           bool sk_edge_trigg,
   1807                           struct DaemonOptions *restrict s,
   1808                           struct mhd_TlsOpenDaemonData **restrict p_d_tls)
   1809 {
   1810   mhd_StatusCodeInt res;
   1811   struct mhd_TlsOpenDaemonData *restrict d_tls;
   1812 
   1813   /* Successful initialisation must be checked earlier */
   1814   mhd_assert (openssl_lib_inited);
   1815 
   1816   res = check_app_tls_settings (d, sk_edge_trigg, s);
   1817   if (MHD_SC_OK != res)
   1818     return res;
   1819 
   1820   d_tls = (struct mhd_TlsOpenDaemonData *)
   1821           mhd_calloc (1, sizeof (struct mhd_TlsOpenDaemonData));
   1822   *p_d_tls = d_tls;
   1823   if (NULL == d_tls)
   1824     return MHD_SC_DAEMON_MEM_ALLOC_FAILURE;
   1825 
   1826 #ifndef HAVE_NULL_PTR_ALL_ZEROS
   1827   d_tls->libctx = NULL;
   1828   d_tls->ctx = NULL;
   1829   d_tls->alpn_prots = NULL;
   1830 #  ifdef mhd_HAVE_OPENSSL_ACME
   1831   d_tls->acme_certs = NULL;
   1832 #  endif /* mhd_HAVE_OPENSSL_ACME */
   1833 #endif /* ! HAVE_NULL_PTR_ALL_ZEROS */
   1834 
   1835 #ifdef mhd_HAVE_OPENSSL_ACME
   1836   d_tls->acme_certs = mhd_daemon_get_acme_certs (d);
   1837 #endif /* mhd_HAVE_OPENSSL_ACME */
   1838 
   1839   res = daemon_init_lib_ctx (d,
   1840                              d_tls,
   1841                              s);
   1842   if (MHD_SC_OK == res)
   1843   {
   1844     res = daemon_init_ctx (d,
   1845                            d_tls,
   1846                            s);
   1847     if (MHD_SC_OK == res)
   1848     {
   1849       res = daemon_init_cert (d,
   1850                               d_tls,
   1851                               s);
   1852       if (MHD_SC_OK == res)
   1853         return MHD_SC_OK; /* Success exit point */
   1854 
   1855       /* Below is a clean-up code path */
   1856       daemon_deinit_ctx (d_tls);
   1857     }
   1858     daemon_deinit_lib_ctx (d_tls);
   1859   }
   1860   free (d_tls);
   1861   *p_d_tls = NULL;
   1862   mhd_assert (MHD_SC_OK != res);
   1863   return res; /* Failure exit point */
   1864 }
   1865 
   1866 
   1867 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_
   1868 MHD_FN_PAR_INOUT_ (1) void
   1869 mhd_tls_open_daemon_deinit (struct mhd_TlsOpenDaemonData *restrict d_tls)
   1870 {
   1871   mhd_assert (NULL != d_tls);
   1872   daemon_deinit_ctx (d_tls);
   1873   daemon_deinit_lib_ctx (d_tls);
   1874   free (d_tls);
   1875 }
   1876 
   1877 
   1878 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_
   1879 MHD_FN_PAR_INOUT_ (1) void
   1880 mhd_tls_open_thread_cleanup (struct mhd_TlsOpenDaemonData *restrict d_tls)
   1881 {
   1882   OPENSSL_thread_stop_ex (d_tls->libctx);
   1883 }
   1884 
   1885 
   1886 /* ** Credentials creation / destruction ** */
   1887 
   1888 #ifdef mhd_HAVE_OPENSSL_ACME
   1889 
   1890 /**
   1891  * Read the end-entity certificate and the chain of the signing certificates
   1892  * from the provided PEM data.
   1893  * @param d_tls the pointer to the daemon's TLS settings
   1894  * @param[in,out] cred the credentials data with the initialised (empty)
   1895  *                     @a chain member, the @a cert member is set on success
   1896  * @param cert_len the length of the @p cert buffer
   1897  * @param cert the certificates data in PEM format
   1898  * @return #mhd_TLS_CRED_CREATE_OK on success,
   1899  *         other enum mhd_TlsCredCreateResult values on failure
   1900  */
   1901 static MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_
   1902 MHD_FN_PAR_IN_SIZE_ (4, 3) enum mhd_TlsCredCreateResult
   1903 cred_read_certs (struct mhd_TlsOpenDaemonData *restrict d_tls,
   1904                  struct mhd_TlsOpenCredData *restrict cred,
   1905                  int cert_len,
   1906                  const char *restrict cert)
   1907 {
   1908   BIO *bio;
   1909   enum mhd_TlsCredCreateResult res;
   1910 
   1911   mhd_assert (NULL == cred->cert);
   1912   mhd_assert (NULL != cred->chain);
   1913 
   1914   res = mhd_TLS_CRED_CREATE_OK;
   1915   bio = BIO_new_mem_buf (cert,
   1916                          cert_len);
   1917   if (NULL == bio)
   1918   {
   1919     mhd_DBG_PRINT_TLS_ERRS ();
   1920     res = mhd_TLS_CRED_CREATE_ALLOC_FAILED;
   1921   }
   1922   else
   1923   {
   1924     cred->cert = X509_new_ex (d_tls->libctx,
   1925                               NULL);
   1926     if (NULL == cred->cert)
   1927     {
   1928       mhd_DBG_PRINT_TLS_ERRS ();
   1929       res = mhd_TLS_CRED_CREATE_ALLOC_FAILED;
   1930     }
   1931     else
   1932     {
   1933       if (NULL == PEM_read_bio_X509_AUX (bio,
   1934                                          &(cred->cert),
   1935                                          &null_passwd_cb,
   1936                                          NULL))
   1937       {
   1938         mhd_DBG_PRINT_TLS_ERRS ();
   1939         res = mhd_TLS_CRED_CREATE_BAD_CRED_DATA;
   1940       }
   1941       else
   1942       {
   1943         do
   1944         {
   1945           X509 *inter_ca; /* Certifying certificate */
   1946 
   1947           inter_ca = X509_new_ex (d_tls->libctx,
   1948                                   NULL);
   1949           if (NULL == inter_ca)
   1950           {
   1951             mhd_DBG_PRINT_TLS_ERRS ();
   1952             res = mhd_TLS_CRED_CREATE_ALLOC_FAILED;
   1953             break;
   1954           }
   1955 
   1956           if (NULL != PEM_read_bio_X509 (bio,
   1957                                          &inter_ca,
   1958                                          &null_passwd_cb,
   1959                                          NULL))
   1960           {
   1961             mhd_NOWARN_USED_UNUSED
   1962 
   1963             if (0 < sk_X509_push (cred->chain,
   1964                                   inter_ca))
   1965             {
   1966               /* The certificate 'inter_ca' is owned by the chain now.
   1967                  Read the next certificate in the chain. */
   1968               continue;
   1969             }
   1970 
   1971             mhd_RESTORE_WARN_USED_UNUSED
   1972 
   1973             /* The cleanup path */
   1974             res = mhd_TLS_CRED_CREATE_ALLOC_FAILED;
   1975           }
   1976           else
   1977           {
   1978             unsigned long err;
   1979             err = ERR_peek_last_error ();
   1980 
   1981             mhd_NOWARN_USED_UNUSED
   1982 
   1983             if ((ERR_LIB_PEM == ERR_GET_LIB (err))
   1984                 && (PEM_R_NO_START_LINE == ERR_GET_REASON (err)))
   1985             {
   1986               X509_free (inter_ca); /* Allocated but not used, not needed */
   1987               ERR_clear_error (); /* End of data, all certificates are read */
   1988               BIO_free (bio);
   1989               return mhd_TLS_CRED_CREATE_OK; /* Success exit point */
   1990             }
   1991 
   1992             /* The cleanup path */
   1993             res = mhd_TLS_CRED_CREATE_BAD_CRED_DATA;
   1994 
   1995             mhd_RESTORE_WARN_USED_UNUSED
   1996           }
   1997           mhd_DBG_PRINT_TLS_ERRS ();
   1998           mhd_assert (mhd_TLS_CRED_CREATE_OK != res);
   1999           X509_free (inter_ca); /* Empty or unusable, not needed */
   2000           break;
   2001         } while (!0);
   2002         mhd_assert (mhd_TLS_CRED_CREATE_OK != res);
   2003       }
   2004       X509_free (cred->cert);
   2005     }
   2006     BIO_free (bio);
   2007   }
   2008 
   2009   mhd_assert (mhd_TLS_CRED_CREATE_OK != res);
   2010   return res;
   2011 }
   2012 
   2013 
   2014 /**
   2015  * Provide the application-supplied password for the private key.
   2016  *
   2017  * Unlike the OpenSSL built-in callback, this one uses the length known by MHD
   2018  * instead of deriving it from the zero-termination and refuses to truncate
   2019  * the password silently.
   2020  * @param[out] buf the buffer to put the password to
   2021  * @param size the size of the @a buf
   2022  * @param rwflag not used, the password is used for decryption only
   2023  * @param cls the pointer to the password string
   2024  * @return the number of characters put to the @a buf,
   2025  *         -1 if the password does not fit the @a buf
   2026  */
   2027 static int
   2028 mem_passwd_cb (char *buf,
   2029                int size,
   2030                int rwflag,
   2031                void *cls)
   2032 {
   2033   const struct MHD_String *const pass = (const struct MHD_String *)cls;
   2034 
   2035   (void)rwflag;  /* Unused */
   2036 
   2037   if ((0 > size) || (pass->len > (size_t)size))
   2038     return -1; /* The password does not fit, do not truncate it silently */
   2039 
   2040   memcpy (buf,
   2041           pass->cstr,
   2042           pass->len);
   2043   return (int)pass->len;
   2044 }
   2045 
   2046 
   2047 /**
   2048  * Read the private key from the provided PEM data and check that it matches
   2049  * the certificate.
   2050  * @param d_tls the pointer to the daemon's TLS settings
   2051  * @param[in,out] cred the credentials data with the set @a cert member,
   2052  *                     the @a key member is set on success
   2053  * @param key_len the length of the @p key buffer
   2054  * @param key the private key data in PEM format
   2055  * @param pass_len the length of the @p pass buffer, must be zero if the @p pass
   2056  *                 is NULL
   2057  * @param pass the password for the private key, zero-terminated,
   2058  *             may be NULL
   2059  * @return #mhd_TLS_CRED_CREATE_OK on success,
   2060  *         other enum mhd_TlsCredCreateResult values on failure
   2061  */
   2062 static MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (2)
   2063 MHD_FN_PAR_NONNULL_ (4) MHD_FN_MUST_CHECK_RESULT_
   2064 MHD_FN_PAR_IN_SIZE_ (4, 3) MHD_FN_PAR_IN_SIZE_ (6, 5) MHD_FN_PAR_CSTR_ (6)
   2065 enum mhd_TlsCredCreateResult
   2066 cred_read_key (struct mhd_TlsOpenDaemonData *restrict d_tls,
   2067                struct mhd_TlsOpenCredData *restrict cred,
   2068                int key_len,
   2069                const char *restrict key,
   2070                size_t pass_len,
   2071                const char *restrict pass)
   2072 {
   2073   enum mhd_TlsCredCreateResult res;
   2074   BIO *bio;
   2075   EVP_PKEY *key_obj;
   2076   struct MHD_String pass_str;
   2077 
   2078   mhd_assert (NULL != cred->cert);
   2079   mhd_assert (NULL == cred->key);
   2080   mhd_assert ((NULL != pass) || (0 == pass_len));
   2081 
   2082   res = mhd_TLS_CRED_CREATE_OK;
   2083   pass_str.len = pass_len;
   2084   pass_str.cstr = pass;
   2085 
   2086   bio = BIO_new_mem_buf (key,
   2087                          key_len);
   2088   if (NULL == bio)
   2089   {
   2090     mhd_DBG_PRINT_TLS_ERRS ();
   2091     res = mhd_TLS_CRED_CREATE_ALLOC_FAILED;
   2092   }
   2093   else
   2094   {
   2095     key_obj =
   2096       PEM_read_bio_PrivateKey_ex (bio,
   2097                                   NULL,
   2098                                   (NULL == pass) ? &null_passwd_cb :
   2099                                   &mem_passwd_cb,
   2100                                   (NULL == pass) ? NULL : &pass_str,
   2101                                   d_tls->libctx,
   2102                                   NULL);
   2103     BIO_free (bio);
   2104 
   2105     if (NULL == key_obj)
   2106     {
   2107       mhd_DBG_PRINT_TLS_ERRS ();
   2108       res = mhd_TLS_CRED_CREATE_BAD_CRED_DATA;
   2109     }
   2110     else
   2111     {
   2112       ERR_clear_error ();
   2113       if (1 != X509_check_private_key (cred->cert,
   2114                                        key_obj))
   2115       {
   2116         mhd_DBG_PRINT_TLS_ERRS ();
   2117         res = mhd_TLS_CRED_CREATE_BAD_CRED_DATA;
   2118       }
   2119       else
   2120       {
   2121         ERR_clear_error ();
   2122         cred->key = key_obj;
   2123         return mhd_TLS_CRED_CREATE_OK; /* Success exit point */
   2124       }
   2125       EVP_PKEY_free (key_obj);
   2126     }
   2127   }
   2128 
   2129   return res; /* Failure exit point */
   2130 }
   2131 
   2132 
   2133 MHD_INTERNAL MHD_FN_MUST_CHECK_RESULT_
   2134 MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (2)
   2135 MHD_FN_PAR_NONNULL_ (4) MHD_FN_PAR_NONNULL_ (6)
   2136 MHD_FN_PAR_OUT_ (2)
   2137 MHD_FN_PAR_IN_SIZE_ (4, 3) MHD_FN_PAR_IN_SIZE_ (6, 5)
   2138 MHD_FN_PAR_IN_SIZE_ (8, 7)
   2139 MHD_FN_PAR_CSTR_ (4) MHD_FN_PAR_CSTR_ (6) MHD_FN_PAR_CSTR_ (8)
   2140 enum mhd_TlsCredCreateResult
   2141 mhd_tls_open_cred_create (struct mhd_TlsOpenDaemonData *restrict d_tls,
   2142                           union mhd_TlsCredDataPtr *restrict pp_cred,
   2143                           size_t cert_len,
   2144                           const char *restrict cert,
   2145                           size_t key_len,
   2146                           const char *restrict key,
   2147                           size_t pass_len,
   2148                           const char *restrict pass)
   2149 {
   2150   struct mhd_TlsOpenCredData *cred;
   2151   enum mhd_TlsCredCreateResult res;
   2152   int cert_len_i;
   2153   int key_len_i;
   2154 
   2155   mhd_assert (0 != cert_len);
   2156   mhd_assert (0 != key_len);
   2157   mhd_assert ((NULL != pass) || (0 == pass_len));
   2158 
   2159   pp_cred->open = NULL;
   2160 
   2161   cert_len_i = (int)cert_len;
   2162   key_len_i = (int)key_len;
   2163   if (mhd_COND_HARDLY_EVER (cert_len != (size_t)cert_len_i)
   2164       || mhd_COND_HARDLY_EVER (0 > cert_len_i)
   2165       || mhd_COND_HARDLY_EVER (key_len != (size_t)key_len_i)
   2166       || mhd_COND_HARDLY_EVER (0 > key_len_i))
   2167     return mhd_TLS_CRED_CREATE_BAD_CRED_DATA; /* The data is too large */
   2168 
   2169   cred = (struct mhd_TlsOpenCredData *)
   2170          mhd_calloc (1,
   2171                      sizeof(struct mhd_TlsOpenCredData));
   2172   if (NULL == cred)
   2173     return mhd_TLS_CRED_CREATE_ALLOC_FAILED;
   2174 
   2175 #  ifndef NDEBUG
   2176 #    ifndef HAVE_NULL_PTR_ALL_ZEROS
   2177   cred->cert = NULL;
   2178   cred->key = NULL;
   2179   cred->chain = NULL;
   2180 #    endif /* HAVE_NULL_PTR_ALL_ZEROS */
   2181 #  endif /* NDEBUG */
   2182 
   2183   ERR_clear_error ();
   2184   /* The chain is always allocated (and stays empty if no chain is provided) as
   2185      the empty chain must replace the chain inherited from the daemon's context
   2186      when the credentials are used for the connection. */
   2187   cred->chain = sk_X509_new_null ();
   2188   if (NULL == cred->chain)
   2189   {
   2190     mhd_DBG_PRINT_TLS_ERRS ();
   2191     res = mhd_TLS_CRED_CREATE_ALLOC_FAILED;
   2192   }
   2193   else
   2194   {
   2195     ERR_clear_error ();
   2196 
   2197     res = cred_read_certs (d_tls,
   2198                            cred,
   2199                            cert_len_i,
   2200                            cert);
   2201     if (mhd_TLS_CRED_CREATE_OK == res)
   2202     {
   2203       res = cred_read_key (d_tls,
   2204                            cred,
   2205                            key_len_i,
   2206                            key,
   2207                            pass_len,
   2208                            pass);
   2209       if (mhd_TLS_CRED_CREATE_OK == res)
   2210       {
   2211         pp_cred->open = cred;
   2212         return mhd_TLS_CRED_CREATE_OK; /* Success exit point */
   2213       }
   2214 
   2215       /* Below is a clean-up code path */
   2216       X509_free (cred->cert);
   2217     }
   2218     mhd_NOWARN_USED_UNUSED
   2219     sk_X509_pop_free (cred->chain,
   2220                       X509_free);
   2221 
   2222     mhd_RESTORE_WARN_USED_UNUSED
   2223   }
   2224 
   2225   free (cred);
   2226   mhd_assert (mhd_TLS_CRED_CREATE_OK != res);
   2227   return res; /* Failure exit point */
   2228 }
   2229 
   2230 
   2231 MHD_INTERNAL void
   2232 mhd_tls_open_cred_destroy_nodmn (union mhd_TlsCredDataPtr cred)
   2233 {
   2234   mhd_ASSUME (NULL != cred.open);
   2235   mhd_assert (NULL != cred.open->key);
   2236   mhd_assert (NULL != cred.open->cert);
   2237   mhd_assert (NULL != cred.open->chain);
   2238 
   2239   /* Release in the reverse order of the creation.
   2240      The objects still used by any TLS session or context are not destroyed
   2241      here as OpenSSL holds its own references for them. */
   2242   EVP_PKEY_free (cred.open->key);
   2243   X509_free (cred.open->cert);
   2244   mhd_NOWARN_USED_UNUSED
   2245   sk_X509_pop_free (cred.open->chain,
   2246                     &X509_free);
   2247 
   2248   mhd_RESTORE_WARN_USED_UNUSED
   2249   free (cred.open);
   2250 
   2251 }
   2252 
   2253 
   2254 #endif /* mhd_HAVE_OPENSSL_ACME */
   2255 
   2256 
   2257 /* ** Connection initialisation / de-initialisation ** */
   2258 
   2259 MHD_INTERNAL size_t
   2260 mhd_tls_open_conn_get_tls_size_v (void)
   2261 {
   2262   return sizeof (struct mhd_TlsOpenConnData);
   2263 }
   2264 
   2265 
   2266 #ifdef mhd_HAVE_OPENSSL_ACME
   2267 /**
   2268  * Prepare the connection data for the detection of the ACME ALPN challenge
   2269  * @param d_tls the daemon TLS settings
   2270  * @param[in,out] c_tls the connection TLS handle with the initialised session
   2271  * @return 'true' on success,
   2272  *         'false' otherwise
   2273  */
   2274 static MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_ bool
   2275 conn_init_acme_data (const struct mhd_TlsOpenDaemonData *restrict d_tls,
   2276                      struct mhd_TlsOpenConnData *restrict c_tls)
   2277 {
   2278   bool res;
   2279 
   2280   /* c_tls is created by calloc(), all bool member must be 'false' */
   2281   mhd_assert (!c_tls->clienthello_processed);
   2282   mhd_assert (!c_tls->is_acme);
   2283 
   2284   /* The additional context for ClientHello and ALPN callbacks */
   2285   res = (0 != SSL_set_ex_data (c_tls->sess,
   2286                                conn_mhd_ctls_idx,
   2287                                c_tls));
   2288 
   2289 #  ifdef mhd_USE_OPENSSL_CLIENT_HELLO_GET0_EXT
   2290   (void)d_tls;   /* Unused, the ClientHello callback is set for the context */
   2291 #  else  /* ! mhd_USE_OPENSSL_CLIENT_HELLO_GET0_EXT */
   2292   /* Conditionally process ClientHello message - only if any ACME certificates
   2293     are present */
   2294   if (res
   2295       && (mhd_daemon_has_acme_certs (d_tls->acme_certs)))
   2296   {
   2297     /* The unparsed ClientHello message is provided only by the messages
   2298        callback */
   2299     (void)SSL_set_msg_callback_arg (c_tls->sess,  /* does not actually return a value */
   2300                                     d_tls->acme_certs);
   2301     SSL_set_msg_callback (c_tls->sess,
   2302                           &check_hello_msg_acme);
   2303   }
   2304 #  endif /* ! mhd_USE_OPENSSL_CLIENT_HELLO_GET0_EXT */
   2305   return res;
   2306 }
   2307 
   2308 
   2309 #else  /* ! mhd_HAVE_OPENSSL_ACME */
   2310 #  define conn_init_acme_data(d_tls, c_tls) \
   2311         (((void) (d_tls)), ((void) (c_tls)), (! 0))
   2312 #endif /* ! mhd_HAVE_OPENSSL_ACME */
   2313 
   2314 MHD_INTERNAL MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_
   2315 MHD_FN_PAR_OUT_ (3) bool
   2316 mhd_tls_open_conn_init (const struct mhd_TlsOpenDaemonData *restrict d_tls,
   2317                         const struct mhd_ConnSocket *sk,
   2318                         struct mhd_TlsOpenConnData *restrict c_tls)
   2319 {
   2320   int fd;
   2321 
   2322   ERR_clear_error ();
   2323 
   2324   fd = (int)sk->fd;
   2325   if (sk->fd != (MHD_Socket)fd)
   2326     return false; /* OpenSSL docs clam that it should not be possible */
   2327 
   2328   c_tls->sess = SSL_new (d_tls->ctx);
   2329 
   2330   if (NULL == c_tls->sess)
   2331   {
   2332     mhd_DBG_PRINT_TLS_ERRS ();
   2333     return false;
   2334   }
   2335 
   2336   if ((0 < SSL_set_fd (c_tls->sess, fd))
   2337       && conn_init_acme_data (d_tls,
   2338                               c_tls))
   2339   {
   2340     SSL_set_accept_state (c_tls->sess); /* Force server mode */
   2341 
   2342 #ifndef NDEBUG
   2343     c_tls->dbg.is_inited = true;
   2344 #endif
   2345     return true; /* Success exit point */
   2346   }
   2347 
   2348   SSL_free (c_tls->sess);
   2349   c_tls->sess = NULL;
   2350   return false;
   2351 }
   2352 
   2353 
   2354 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ void
   2355 mhd_tls_open_conn_deinit (struct mhd_TlsOpenConnData *restrict c_tls)
   2356 {
   2357   mhd_assert (NULL != c_tls->sess);
   2358   mhd_assert (c_tls->dbg.is_inited);
   2359   SSL_free (c_tls->sess);
   2360 }
   2361 
   2362 
   2363 /* ** TLS connection establishing ** */
   2364 
   2365 MHD_INTERNAL MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_
   2366 enum mhd_TlsProcedureResult
   2367 mhd_tls_open_conn_handshake (struct mhd_TlsOpenConnData *restrict c_tls)
   2368 {
   2369   int res;
   2370 
   2371   mhd_assert (c_tls->dbg.is_inited);
   2372   mhd_assert (!c_tls->dbg.is_tls_handshake_completed);
   2373   mhd_assert (!c_tls->shut_tls_wr_sent);
   2374   mhd_assert (!c_tls->shut_tls_wr_received);
   2375   mhd_assert (!c_tls->dbg.is_failed);
   2376 
   2377   ERR_clear_error ();
   2378 
   2379   res = SSL_do_handshake (c_tls->sess);
   2380 
   2381   if (1 == res)
   2382   {
   2383 #ifndef NDEBUG
   2384     c_tls->dbg.is_tls_handshake_completed = true;
   2385 #endif /* ! NDEBUG */
   2386     return mhd_TLS_PROCED_SUCCESS; /* Success exit point */
   2387   }
   2388 
   2389   switch (SSL_get_error (c_tls->sess, res))
   2390   {
   2391   case SSL_ERROR_WANT_READ:
   2392     /* OpenSSL does not distinguish between "interrupted" and "try again" codes.
   2393        Based on OpenSSL result it is unclear whether the "recv-ready" flag
   2394        should be reset or not.
   2395        If edge-triggered sockets polling is used and the flag is cleared, but
   2396        it should not (because the process has been "interrupted") then already
   2397        pending data could be never processed.
   2398        If the flag is not cleared, but it should be cleared (because all
   2399        received data has been processed) then it would create busy-waiting loop
   2400        with edge-triggered sockets polling.
   2401        Temporal solution: disallow edge-triggered sockets polling with OpenSSL
   2402        backend and use clear of "ready" flag. */
   2403     // TODO: replace "BIO" with custom version and track returned errors.
   2404     return mhd_TLS_PROCED_SEND_MORE_NEEDED;
   2405   case SSL_ERROR_WANT_WRITE:
   2406     /* OpenSSL does not distinguish between "interrupted" and "try again" codes.
   2407        Based on OpenSSL result it is unclear whether the "send-ready" flag
   2408        should be reset or not.
   2409        If edge-triggered sockets polling is used and the flag is cleared, but
   2410        it should not (because the process has been "interrupted") then already
   2411        pending data could be never sent.
   2412        If the flag is not cleared, but it should be cleared (because all
   2413        received data has been processed) then it would create busy-waiting loop
   2414        with edge-triggered sockets polling.
   2415        Temporal solution: disallow edge-triggered sockets polling with OpenSSL
   2416        backend and use clear of "ready" flag. */
   2417     // TODO: replace "BIO" with custom version and track returned errors.
   2418     return mhd_TLS_PROCED_RECV_MORE_NEEDED;
   2419   case SSL_ERROR_NONE:
   2420     mhd_assert (0 && "This should not be possible");
   2421     mhd_UNREACHABLE ();
   2422     break;
   2423   default: /* Handled with all other errors below */
   2424     break;
   2425   }
   2426   mhd_DBG_PRINT_TLS_ERRS ();
   2427 #ifndef NDEBUG
   2428   c_tls->dbg.is_failed = true;
   2429 #endif /* ! NDEBUG */
   2430   return mhd_TLS_PROCED_FAILED;
   2431 }
   2432 
   2433 
   2434 MHD_INTERNAL MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_
   2435 enum mhd_TlsProcedureResult
   2436 mhd_tls_open_conn_shutdown (struct mhd_TlsOpenConnData *restrict c_tls)
   2437 {
   2438   int res;
   2439 
   2440   mhd_assert (c_tls->dbg.is_inited);
   2441   mhd_assert (c_tls->dbg.is_tls_handshake_completed);
   2442   mhd_assert (!c_tls->dbg.is_failed);
   2443 
   2444   ERR_clear_error ();
   2445 
   2446   res = SSL_shutdown (c_tls->sess);
   2447 
   2448   if (1 == res)
   2449   {
   2450     c_tls->shut_tls_wr_sent = true;
   2451     c_tls->shut_tls_wr_received = true;
   2452     return mhd_TLS_PROCED_SUCCESS; /* Success exit point */
   2453   }
   2454 
   2455   /* The OpenSSL documentation contradicts itself: there are two mutually
   2456      exclusive statements on a single page.
   2457    * https://docs.openssl.org/master/man3/SSL_shutdown/#shutdown-lifecycle
   2458      indicates that for nonblocking socket ZERO could be returned when
   2459      "close_notify" is GOING to be sent, but NOT sent yet.
   2460      It also suggests to CALL SSL_get_error(3) when ZERO is returned.
   2461    * https://docs.openssl.org/master/man3/SSL_shutdown/#return-values
   2462      indicates ZERO is returned ONLY when "close_notify" HAS BEEN sent.
   2463      It also suggests to NOT CALL SSL_get_error(3) when ZERO is returned.
   2464    */
   2465   switch (SSL_get_error (c_tls->sess, res))
   2466   {
   2467   case SSL_ERROR_WANT_READ:
   2468     /* OpenSSL does not distinguish between "interrupted" and "try again" codes.
   2469        Based on OpenSSL result it is unclear whether the "recv-ready" flag
   2470        should be reset or not.
   2471        If edge-triggered sockets polling is used and the flag is cleared, but
   2472        it should not (because the process has been "interrupted") then already
   2473        pending data could be never processed.
   2474        If the flag is not cleared, but it should be cleared (because all
   2475        received data has been processed) then it would create busy-waiting loop
   2476        with edge-triggered sockets polling.
   2477        Temporal solution: disallow edge-triggered sockets polling with OpenSSL
   2478        backend and use clear of "ready" flag. */
   2479     // TODO: replace "BIO" with custom version and track returned errors.
   2480     return mhd_TLS_PROCED_SEND_MORE_NEEDED;
   2481   case SSL_ERROR_WANT_WRITE:
   2482     c_tls->shut_tls_wr_sent = true;
   2483     /* OpenSSL does not distinguish between "interrupted" and "try again" codes.
   2484        Based on OpenSSL result it is unclear whether the "send-ready" flag
   2485        should be reset or not.
   2486        If edge-triggered sockets polling is used and the flag is cleared, but
   2487        it should not (because the process has been "interrupted") then already
   2488        pending data could be never sent.
   2489        If the flag is not cleared, but it should be cleared (because all
   2490        received data has been processed) then it would create busy-waiting loop
   2491        with edge-triggered sockets polling.
   2492        Temporal solution: disallow edge-triggered sockets polling with OpenSSL
   2493        backend and use clear of "ready" flag. */
   2494     // TODO: replace "BIO" with custom version and track returned errors.
   2495     return mhd_TLS_PROCED_RECV_MORE_NEEDED;
   2496   case SSL_ERROR_NONE:
   2497     mhd_assert (res != 0 && "Should not be possible");
   2498     c_tls->shut_tls_wr_sent = true;
   2499     return mhd_TLS_PROCED_RECV_INTERRUPTED;
   2500   default: /* Handled with all other errors below */
   2501     break;
   2502   }
   2503   mhd_DBG_PRINT_TLS_ERRS ();
   2504 #ifndef NDEBUG
   2505   c_tls->dbg.is_failed = true;
   2506 #endif /* ! NDEBUG */
   2507   return mhd_TLS_PROCED_FAILED;
   2508 }
   2509 
   2510 
   2511 /* ** Data receiving and sending ** */
   2512 
   2513 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_
   2514 MHD_FN_PAR_OUT_SIZE_ (3, 2)
   2515 MHD_FN_PAR_OUT_ (4) enum mhd_SocketError
   2516 mhd_tls_open_conn_recv (struct mhd_TlsOpenConnData *restrict c_tls,
   2517                         size_t buf_size,
   2518                         char buf[MHD_FN_PAR_DYN_ARR_SIZE_ (buf_size)],
   2519                         size_t *restrict received)
   2520 {
   2521   int res;
   2522 
   2523   mhd_assert (c_tls->dbg.is_inited);
   2524   mhd_assert (c_tls->dbg.is_tls_handshake_completed);
   2525   mhd_assert (!c_tls->shut_tls_wr_sent);
   2526   mhd_assert (!c_tls->dbg.is_failed);
   2527 #ifdef mhd_HAVE_OPENSSL_ACME
   2528   mhd_assert (!c_tls->is_acme); /* ACME ALPN challenge connection is not used
   2529                                    for the data exchange */
   2530 #endif /* mhd_HAVE_OPENSSL_ACME */
   2531 
   2532   ERR_clear_error ();
   2533 
   2534   res = SSL_read_ex (c_tls->sess,
   2535                      buf,
   2536                      buf_size,
   2537                      received);
   2538   if (1 == res)
   2539   {
   2540     mhd_assert (0 != *received);
   2541     return mhd_SOCKET_ERR_NO_ERROR; /* Success exit point */
   2542   }
   2543 
   2544   mhd_assert (0 == res);
   2545   *received = 0;
   2546   switch (SSL_get_error (c_tls->sess, res))
   2547   {
   2548   case SSL_ERROR_ZERO_RETURN: /* Not an error */
   2549     c_tls->shut_tls_wr_received = true;
   2550     return mhd_SOCKET_ERR_NO_ERROR;   /* Success exit point */
   2551   case SSL_ERROR_WANT_READ:
   2552     /* OpenSSL does not distinguish between "interrupted" and "try again" codes.
   2553        Based on OpenSSL result it is unclear whether the "recv-ready" flag
   2554        should be reset or not.
   2555        If edge-triggered sockets polling is used and the flag is cleared, but
   2556        it should not (because the process has been "interrupted") then already
   2557        pending data could be never processed.
   2558        If the flag is not cleared, but it should be cleared (because all
   2559        received data has been processed) then it would create busy-waiting loop
   2560        with edge-triggered sockets polling.
   2561        Temporal solution: disallow edge-triggered sockets polling with OpenSSL
   2562        backend and use clear of "ready" flag. */
   2563     // TODO: replace "BIO" with custom version and track returned errors.
   2564     return mhd_SOCKET_ERR_AGAIN;
   2565   case SSL_ERROR_NONE:
   2566     mhd_assert (0 && "Should not be possible");
   2567     break;
   2568   case SSL_ERROR_WANT_WRITE:
   2569     mhd_assert (0 && "Should not be possible as re-handshakes are disallowed");
   2570     break;
   2571   case SSL_ERROR_SYSCALL:
   2572     mhd_DBG_PRINT_TLS_ERRS ();
   2573 #ifndef NDEBUG
   2574     c_tls->dbg.is_failed = true;
   2575 #endif /* ! NDEBUG */
   2576     return mhd_SOCKET_ERR_CONN_BROKEN;
   2577   case SSL_ERROR_SSL:
   2578   default:
   2579     break;
   2580   }
   2581   /* Treat all other kinds of errors as hard errors */
   2582   mhd_DBG_PRINT_TLS_ERRS ();
   2583 #ifndef NDEBUG
   2584   c_tls->dbg.is_failed = true;
   2585 #endif /* ! NDEBUG */
   2586   return mhd_SOCKET_ERR_TLS;
   2587 }
   2588 
   2589 
   2590 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ bool
   2591 mhd_tls_open_conn_has_data_in (struct mhd_TlsOpenConnData *restrict c_tls)
   2592 {
   2593   return 0 != SSL_pending (c_tls->sess);
   2594 }
   2595 
   2596 
   2597 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_
   2598 MHD_FN_PAR_IN_SIZE_ (3, 2)
   2599 MHD_FN_PAR_OUT_ (4) enum mhd_SocketError
   2600 mhd_tls_open_conn_send4 (struct mhd_TlsOpenConnData *restrict c_tls,
   2601                          size_t buf_size,
   2602                          const char buf[MHD_FN_PAR_DYN_ARR_SIZE_ (buf_size)],
   2603                          size_t *restrict sent)
   2604 {
   2605   int res;
   2606 
   2607   mhd_assert (c_tls->dbg.is_inited);
   2608   mhd_assert (c_tls->dbg.is_tls_handshake_completed);
   2609   mhd_assert (!c_tls->shut_tls_wr_sent);
   2610   mhd_assert (!c_tls->dbg.is_failed);
   2611 #ifdef mhd_HAVE_OPENSSL_ACME
   2612   mhd_assert (!c_tls->is_acme); /* ACME ALPN challenge connection is not used
   2613                                    for the data exchange */
   2614 #endif /* mhd_HAVE_OPENSSL_ACME */
   2615 
   2616   ERR_clear_error ();
   2617 
   2618   res = SSL_write_ex (c_tls->sess,
   2619                       buf,
   2620                       buf_size,
   2621                       sent);
   2622   if (1 == res)
   2623   {
   2624     mhd_assert (0 != *sent);
   2625     return mhd_SOCKET_ERR_NO_ERROR; /* Success exit point */
   2626   }
   2627 
   2628   mhd_assert (0 == res);
   2629   *sent = 0;
   2630   switch (SSL_get_error (c_tls->sess, res))
   2631   {
   2632   case SSL_ERROR_WANT_WRITE:
   2633     /* OpenSSL does not distinguish between "interrupted" and "try again" codes.
   2634        Based on OpenSSL result it is unclear whether the "send-ready" flag
   2635        should be reset or not.
   2636        If edge-triggered sockets polling is used and the flag is cleared, but
   2637        it should not (because the process has been "interrupted") then already
   2638        pending data could be never sent.
   2639        If the flag is not cleared, but it should be cleared (because all
   2640        received data has been processed) then it would create busy-waiting loop
   2641        with edge-triggered sockets polling.
   2642        Temporal solution: disallow edge-triggered sockets polling with OpenSSL
   2643        backend and use clear of "ready" flag. */
   2644     // TODO: replace "BIO" with custom version and track returned errors.
   2645     return mhd_SOCKET_ERR_AGAIN;
   2646   case SSL_ERROR_NONE:
   2647     mhd_assert (0 && "Should not be possible");
   2648     break;
   2649   case SSL_ERROR_WANT_READ:
   2650     mhd_assert (0 && "Should not be possible as re-handshakes are disallowed");
   2651     break;
   2652   case SSL_ERROR_ZERO_RETURN:
   2653     c_tls->shut_tls_wr_received = true;
   2654     return mhd_SOCKET_ERR_AGAIN;
   2655   case SSL_ERROR_SYSCALL:
   2656     mhd_DBG_PRINT_TLS_ERRS ();
   2657 #ifndef NDEBUG
   2658     c_tls->dbg.is_failed = true;
   2659 #endif /* ! NDEBUG */
   2660     return mhd_SOCKET_ERR_CONN_BROKEN;
   2661   case SSL_ERROR_SSL:
   2662   default:
   2663     break;
   2664   }
   2665   /* Treat all other kinds of errors as hard errors */
   2666   mhd_DBG_PRINT_TLS_ERRS ();
   2667 #ifndef NDEBUG
   2668   c_tls->dbg.is_failed = true;
   2669 #endif /* ! NDEBUG */
   2670   return mhd_SOCKET_ERR_TLS;
   2671 }
   2672 
   2673 
   2674 /* ** TLS connection information ** */
   2675 
   2676 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_
   2677 MHD_FN_PAR_OUT_ (2) void
   2678 mhd_tls_open_conn_get_tls_sess (
   2679   struct mhd_TlsOpenConnData *restrict c_tls,
   2680   union MHD_ConnInfoDynamicTlsSess *restrict tls_sess_out)
   2681 {
   2682   tls_sess_out->v_openssl_session = c_tls->sess;
   2683 }
   2684 
   2685 
   2686 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_
   2687 MHD_FN_PAR_OUT_ (2) bool
   2688 mhd_tls_open_conn_get_tls_ver (struct mhd_TlsOpenConnData *restrict c_tls,
   2689                                struct mhd_StctTlsVersion *restrict tls_ver_out)
   2690 {
   2691   int openssl_tls_ver;
   2692 
   2693   mhd_assert (c_tls->dbg.is_tls_handshake_completed);
   2694 
   2695   openssl_tls_ver = SSL_version (c_tls->sess);
   2696   switch (openssl_tls_ver)
   2697   {
   2698   case TLS1_VERSION:
   2699     tls_ver_out->tls_ver = MHD_TLS_VERSION_1_0;
   2700     break;
   2701   case TLS1_1_VERSION:
   2702     tls_ver_out->tls_ver = MHD_TLS_VERSION_1_1;
   2703     break;
   2704   case TLS1_2_VERSION:
   2705     tls_ver_out->tls_ver = MHD_TLS_VERSION_1_2;
   2706     break;
   2707   case TLS1_3_VERSION:
   2708     tls_ver_out->tls_ver = MHD_TLS_VERSION_1_3;
   2709     break;
   2710   case SSL3_VERSION:
   2711   default:
   2712     tls_ver_out->tls_ver = MHD_TLS_VERSION_UNKNOWN;
   2713     break;
   2714   }
   2715 
   2716   return true;
   2717 }
   2718 
   2719 
   2720 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ enum mhd_TlsAlpnProt
   2721 mhd_tls_open_conn_get_alpn_prot (struct mhd_TlsOpenConnData *restrict c_tls)
   2722 {
   2723   const unsigned char *sel_prot;
   2724   unsigned int sel_prot_len;
   2725 #ifdef mhd_HAVE_OPENSSL_ACME
   2726   mhd_assert (!c_tls->is_acme);
   2727 #endif /* mhd_HAVE_OPENSSL_ACME */
   2728 
   2729   SSL_get0_alpn_selected (c_tls->sess,
   2730                           &sel_prot,
   2731                           &sel_prot_len);
   2732 
   2733 #ifndef OPENSSL_NO_NEXTPROTONEG
   2734   if ((NULL == sel_prot)
   2735       || (0 == sel_prot_len))
   2736   {
   2737     SSL_get0_next_proto_negotiated (c_tls->sess,
   2738                                     &sel_prot,
   2739                                     &sel_prot_len);
   2740   }
   2741 #endif /* ! OPENSSL_NO_NEXTPROTONEG */
   2742 
   2743   mhd_assert (sel_prot_len == (size_t)sel_prot_len);
   2744 
   2745   return mhd_tls_alpn_decode_n ((size_t)sel_prot_len,
   2746                                 sel_prot);
   2747 }
   2748 
   2749 
   2750 #ifdef mhd_HAVE_TLS_ACME
   2751 #  ifdef mhd_HAVE_OPENSSL_ACME
   2752 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ bool
   2753 mhd_tls_open_conn_is_acme (struct mhd_TlsOpenConnData *restrict c_tls)
   2754 {
   2755   return c_tls->is_acme;
   2756 }
   2757 
   2758 
   2759 #  endif /* mhd_HAVE_OPENSSL_ACME */
   2760 #endif /* mhd_HAVE_TLS_ACME */