libmicrohttpd2

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

tls_multi_funcs.c (30963B)


      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_multi_funcs.c
     41  * @brief  The implementation of MultiTLS wrapper functions
     42  * @author Karlson2k (Evgeny Grin)
     43  */
     44 
     45 #include "mhd_sys_options.h"
     46 
     47 #include "sys_bool_type.h"
     48 
     49 #include "mhd_assert.h"
     50 #include "mhd_unreachable.h"
     51 
     52 #include "compat_calloc.h"
     53 #include "sys_malloc.h"
     54 
     55 #include "mhd_arr_num_elems.h"
     56 
     57 #include "tls_multi_tls_lib.h"
     58 
     59 #include "tls_multi_daemon_data.h"
     60 #include "tls_multi_conn_data.h"
     61 #include "tls_multi_funcs.h"
     62 
     63 /* Include all supported TLS backends headers */
     64 #if defined(MHD_SUPPORT_GNUTLS)
     65 #  include "tls_gnu_funcs.h"
     66 #endif
     67 #if defined(MHD_SUPPORT_OPENSSL)
     68 #  include "tls_open_funcs.h"
     69 #endif
     70 #if defined(MHD_SUPPORT_MBEDTLS)
     71 #  include "tls_mbed_funcs.h"
     72 #endif
     73 
     74 #include "daemon_options.h"
     75 #include "daemon_logger.h"
     76 
     77 #ifdef mhd_USE_TLS_DEBUG_MESSAGES
     78 #  include <stdio.h> /* For TLS debug printing */
     79 #endif
     80 
     81 #include "mhd_public_api.h"
     82 
     83 #ifdef mhd_USE_TLS_DEBUG_MESSAGES
     84 #  define mhd_M_DEBUG_PRINT(msg) \
     85           do { fprintf (stderr, "## MultiTLS: " msg "\n"); \
     86                fflush (stderr); } while (0)
     87 #  define mhd_M_DEBUG_PRINT1(msg, arg1) \
     88           do { fprintf (stderr, "## MultiTLS: " msg "\n", arg1); \
     89                fflush (stderr); } while (0)
     90 #else
     91 #  define mhd_M_DEBUG_PRINT(msg)        ((void) 0)
     92 #  define mhd_M_DEBUG_PRINT1(msg, arg1)  ((void) 0)
     93 #endif
     94 
     95 
     96 /* ** Global initialisation / de-initialisation ** */
     97 
     98 MHD_INTERNAL void
     99 mhd_tls_multi_global_init_once (void)
    100 {
    101 #if defined(MHD_SUPPORT_GNUTLS)
    102   mhd_tls_gnu_global_init_once ();
    103 #endif
    104 #if defined(MHD_SUPPORT_OPENSSL)
    105   mhd_tls_open_global_init_once ();
    106 #endif
    107 #if defined(MHD_SUPPORT_MBEDTLS)
    108   mhd_tls_mbed_global_init_once ();
    109 #endif
    110 }
    111 
    112 
    113 MHD_INTERNAL void
    114 mhd_tls_multi_global_deinit (void)
    115 {
    116   /* Note: the order is reversed to match the initialisation */
    117 #if defined(MHD_SUPPORT_OPENSSL)
    118   mhd_tls_open_global_deinit ();
    119 #endif
    120 #if defined(MHD_SUPPORT_GNUTLS)
    121   mhd_tls_gnu_global_deinit ();
    122 #endif
    123 #if defined(MHD_SUPPORT_MBEDTLS)
    124   mhd_tls_mbed_global_deinit ();
    125 #endif
    126 }
    127 
    128 
    129 MHD_INTERNAL void
    130 mhd_tls_multi_global_re_init (void)
    131 {
    132 #if defined(MHD_SUPPORT_GNUTLS)
    133   mhd_tls_gnu_global_re_init ();
    134 #endif
    135 #if defined(MHD_SUPPORT_OPENSSL)
    136   mhd_tls_open_global_re_init ();
    137 #endif
    138 #if defined(MHD_SUPPORT_MBEDTLS)
    139   mhd_tls_mbed_global_re_init ();
    140 #endif
    141 }
    142 
    143 
    144 /* ** Daemon initialisation / de-initialisation ** */
    145 
    146 MHD_INTERNAL MHD_FN_PURE_ bool
    147 mhd_tls_multi_is_edge_trigg_supported (struct DaemonOptions *s)
    148 {
    149   switch (s->tls)
    150   {
    151   case MHD_TLS_BACKEND_NONE:
    152     mhd_UNREACHABLE ();
    153     return false;
    154   case MHD_TLS_BACKEND_ANY:
    155 #ifdef MHD_SUPPORT_GNUTLS
    156     if (mhd_tls_gnu_is_edge_trigg_supported (s)
    157         && mhd_tls_gnu_is_inited_fine ())
    158 #  ifdef mhd_HAVE_TLS_ACME
    159       if (mhd_tls_gnu_is_acme_alpn_supported (s)
    160           || !s->acme_alpn_required)
    161 #  endif /* mhd_HAVE_TLS_ACME */
    162       return true;
    163 #endif
    164 #ifdef MHD_SUPPORT_OPENSSL
    165     if (mhd_tls_open_is_edge_trigg_supported (s)
    166         && mhd_tls_open_is_inited_fine ())
    167 #  ifdef mhd_HAVE_TLS_ACME
    168       if (mhd_tls_open_is_acme_alpn_supported (s)
    169           || !s->acme_alpn_required)
    170 #  endif /* mhd_HAVE_TLS_ACME */
    171       return true;
    172 #endif
    173 #ifdef MHD_SUPPORT_MBEDTLS
    174     if (mhd_tls_mbed_is_edge_trigg_supported (s)
    175         && mhd_tls_mbed_is_inited_fine ())
    176 #  ifdef mhd_HAVE_TLS_ACME
    177       if (mhd_tls_mbed_is_acme_alpn_supported (s)
    178           || !s->acme_alpn_required)
    179 #  endif /* mhd_HAVE_TLS_ACME */
    180       return true;
    181 #endif
    182     return false;
    183   case MHD_TLS_BACKEND_GNUTLS:
    184 #ifdef MHD_SUPPORT_GNUTLS
    185     /* Ignore "backend inited" status here,
    186        it will be checked on daemon TLS init */
    187     return mhd_tls_gnu_is_edge_trigg_supported (s);
    188 #endif
    189     break;
    190   case MHD_TLS_BACKEND_OPENSSL:
    191 #ifdef MHD_SUPPORT_OPENSSL
    192     /* Ignore "backend inited" status here,
    193        it will be checked on daemon TLS init */
    194     return mhd_tls_open_is_edge_trigg_supported (s);
    195 #endif
    196     break;
    197   case MHD_TLS_BACKEND_MBEDTLS:
    198 #ifdef MHD_SUPPORT_MBEDTLS
    199     /* Ignore "backend inited" status here,
    200        it will be checked on daemon TLS init */
    201     return mhd_tls_mbed_is_edge_trigg_supported (s);
    202 #endif
    203     break;
    204   default:
    205     mhd_UNREACHABLE ();
    206     break;
    207   }
    208   return false;
    209 }
    210 
    211 
    212 #ifdef mhd_HAVE_TLS_ACME
    213 MHD_INTERNAL MHD_FN_PURE_ bool
    214 mhd_tls_multi_is_acme_alpn_supported (struct DaemonOptions *s)
    215 {
    216   switch (s->tls)
    217   {
    218   case MHD_TLS_BACKEND_NONE:
    219     mhd_UNREACHABLE ();
    220     return false;
    221   case MHD_TLS_BACKEND_ANY:
    222 #  ifdef MHD_SUPPORT_GNUTLS
    223     if (mhd_tls_gnu_is_acme_alpn_supported (s)
    224         && mhd_tls_gnu_is_inited_fine ())
    225       return true;
    226 #  endif
    227 #  ifdef MHD_SUPPORT_OPENSSL
    228     if (mhd_tls_open_is_acme_alpn_supported (s)
    229         && mhd_tls_open_is_inited_fine ())
    230       return true;
    231 #  endif
    232 #  ifdef MHD_SUPPORT_MBEDTLS
    233     if (mhd_tls_mbed_is_acme_alpn_supported (s)
    234         && mhd_tls_mbed_is_inited_fine ())
    235       return true;
    236 #  endif
    237     return false;
    238   case MHD_TLS_BACKEND_GNUTLS:
    239 #  ifdef MHD_SUPPORT_GNUTLS
    240     /* Ignore "backend inited" status here,
    241        it will be checked on daemon TLS init */
    242     return mhd_tls_gnu_is_acme_alpn_supported (s);
    243 #  endif
    244     break;
    245   case MHD_TLS_BACKEND_OPENSSL:
    246 #  ifdef MHD_SUPPORT_OPENSSL
    247     /* Ignore "backend inited" status here,
    248        it will be checked on daemon TLS init */
    249     return mhd_tls_open_is_acme_alpn_supported (s);
    250 #  endif
    251     break;
    252   case MHD_TLS_BACKEND_MBEDTLS:
    253 #  ifdef MHD_SUPPORT_MBEDTLS
    254     /* Ignore "backend inited" status here,
    255        it will be checked on daemon TLS init */
    256     return mhd_tls_mbed_is_acme_alpn_supported (s);
    257 #  endif
    258     break;
    259   default:
    260     mhd_UNREACHABLE ();
    261     break;
    262   }
    263   return false;
    264 }
    265 
    266 
    267 #endif /* mhd_HAVE_TLS_ACME */
    268 
    269 /**
    270  * Initialise selected TLS backend for the daemon
    271  * @param route the selected TLS backend
    272  * @param d the daemon handle
    273  * @param s the daemon settings
    274  * @param d_tls the daemon's TLS settings, backend-specific data is allocated
    275  *              and initialised
    276  * @return #MHD_SC_OK on success (the backend-specific data is allocated),
    277  *         error code otherwise
    278  */
    279 static MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_
    280 MHD_FN_PAR_OUT_ (5) mhd_StatusCodeInt
    281 tls_daemon_init_try (enum mhd_TlsMultiRoute route,
    282                      struct MHD_Daemon *restrict d,
    283                      bool sk_edge_trigg,
    284                      struct DaemonOptions *restrict s,
    285                      struct mhd_TlsMultiDaemonData *restrict d_tls)
    286 {
    287   mhd_StatusCodeInt res;
    288 
    289 #ifndef MHD_SUPPORT_OPENSSL
    290   (void)sk_edge_trigg;  /* Unused, mute compiler warning */
    291 #endif /* ! MHD_SUPPORT_OPENSSL */
    292 
    293   switch (route)
    294   {
    295 #ifdef MHD_SUPPORT_GNUTLS
    296   case mhd_TLS_MULTI_ROUTE_GNU:
    297     if (!mhd_tls_gnu_is_inited_fine ())
    298       return MHD_SC_TLS_BACKEND_UNAVAILABLE;
    299     res = mhd_tls_gnu_daemon_init (d,
    300                                    sk_edge_trigg,
    301                                    s,
    302                                    &(d_tls->data.gnutls));
    303     if (MHD_SC_OK == res)
    304     {
    305       mhd_M_DEBUG_PRINT ("GnuTLS backend initialised successfully " \
    306                          "for the daemon");
    307       d_tls->choice = route;
    308       return MHD_SC_OK;
    309     }
    310     mhd_M_DEBUG_PRINT1 ("Failed to initialise GnuTLS backend for " \
    311                         "the daemon, error code: %u", (unsigned)res);
    312     return res;
    313 #endif
    314 #ifdef MHD_SUPPORT_OPENSSL
    315   case mhd_TLS_MULTI_ROUTE_OPEN:
    316     if (!mhd_tls_open_is_inited_fine ())
    317       return MHD_SC_TLS_BACKEND_UNAVAILABLE;
    318     res = mhd_tls_open_daemon_init (d,
    319                                     sk_edge_trigg,
    320                                     s,
    321                                     &(d_tls->data.openssl));
    322     if (MHD_SC_OK == res)
    323     {
    324       mhd_M_DEBUG_PRINT ("OpenSSL backend initialised successfully " \
    325                          "for the daemon");
    326       d_tls->choice = route;
    327       return MHD_SC_OK;
    328     }
    329     mhd_M_DEBUG_PRINT1 ("Failed to initialise OpenSSL backend for " \
    330                         "the daemon, error code: %u", (unsigned)res);
    331     return res;
    332 #endif
    333 #ifdef MHD_SUPPORT_MBEDTLS
    334   case mhd_TLS_MULTI_ROUTE_MBED:
    335     if (!mhd_tls_mbed_is_inited_fine ())
    336       return MHD_SC_TLS_BACKEND_UNAVAILABLE;
    337     res = mhd_tls_mbed_daemon_init (d,
    338                                     sk_edge_trigg,
    339                                     s,
    340                                     &(d_tls->data.mbedtls));
    341     if (MHD_SC_OK == res)
    342     {
    343       mhd_M_DEBUG_PRINT ("MbedTLS backend initialised successfully " \
    344                          "for the daemon");
    345       d_tls->choice = route;
    346       return MHD_SC_OK;
    347     }
    348     mhd_M_DEBUG_PRINT1 ("Failed to initialise MbedTLS backend for " \
    349                         "the daemon, error code: %u", (unsigned)res);
    350     return res;
    351 #endif
    352   case mhd_TLS_MULTI_ROUTE_NONE:
    353   default:
    354     break;
    355   }
    356   mhd_assert (0 && "Impossible value");
    357   mhd_UNREACHABLE ();
    358   return MHD_SC_INTERNAL_ERROR;
    359 }
    360 
    361 
    362 MHD_INTERNAL MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_
    363 MHD_FN_PAR_OUT_ (4) mhd_StatusCodeInt
    364 mhd_tls_multi_daemon_init (struct MHD_Daemon *restrict d,
    365                            bool sk_edge_trigg,
    366                            struct DaemonOptions *restrict s,
    367                            struct mhd_TlsMultiDaemonData **restrict p_d_tls)
    368 {
    369   mhd_StatusCodeInt res;
    370   struct mhd_TlsMultiDaemonData *restrict d_tls;
    371   d_tls = (struct mhd_TlsMultiDaemonData *)
    372           mhd_calloc (1,
    373                       sizeof (struct mhd_TlsMultiDaemonData));
    374   if (NULL == d_tls)
    375     return MHD_SC_DAEMON_MEM_ALLOC_FAILURE;
    376 
    377   d_tls->choice = mhd_TLS_MULTI_ROUTE_NONE;
    378 #ifndef HAVE_NULL_PTR_ALL_ZEROS
    379 #  ifdef MHD_SUPPORT_GNUTLS
    380   d_tls->data.gnutls = NULL;
    381 #  endif /* MHD_SUPPORT_GNUTLS */
    382 #  ifdef MHD_SUPPORT_OPENSSL
    383   d_tls->data.openssl = NULL;
    384 #  endif /* MHD_SUPPORT_OPENSSL */
    385 #  ifdef MHD_SUPPORT_MBEDTLS
    386   d_tls->data.mbedtls = NULL;
    387 #  endif /* MHD_SUPPORT_MBEDTLS */
    388 #endif /* ! HAVE_NULL_PTR_ALL_ZEROS */
    389 
    390   res = MHD_SC_INTERNAL_ERROR; /* Mute compiler warning, the value should not be used */
    391   switch (s->tls)
    392   {
    393   case MHD_TLS_BACKEND_ANY:
    394     if (1)
    395     {
    396       size_t i;
    397       enum mhd_TlsMultiRoute backends[] = {
    398 #ifdef MHD_SUPPORT_GNUTLS
    399         mhd_TLS_MULTI_ROUTE_GNU,
    400 #endif
    401 #ifdef MHD_SUPPORT_OPENSSL
    402         mhd_TLS_MULTI_ROUTE_OPEN,
    403 #endif
    404 #ifdef MHD_SUPPORT_MBEDTLS
    405         mhd_TLS_MULTI_ROUTE_MBED,
    406 #endif
    407         mhd_TLS_MULTI_ROUTE_NONE  /* Not used */
    408       };
    409       /* Try backends one-by-one */
    410       for (i = 0; i < mhd_ARR_NUM_ELEMS (backends) - 1; ++i)
    411       {
    412         res = tls_daemon_init_try (backends[i],
    413                                    d,
    414                                    sk_edge_trigg,
    415                                    s,
    416                                    d_tls);
    417         if (MHD_SC_OK == res)
    418           break;
    419       }
    420     }
    421     break;
    422 #ifdef MHD_SUPPORT_GNUTLS
    423   case MHD_TLS_BACKEND_GNUTLS:
    424     mhd_assert (mhd_tls_gnu_is_inited_fine ()); /* Must be checked earlier */
    425     res = tls_daemon_init_try (mhd_TLS_MULTI_ROUTE_GNU,
    426                                d,
    427                                sk_edge_trigg,
    428                                s,
    429                                d_tls);
    430     break;
    431 #endif /* MHD_SUPPORT_GNUTLS */
    432 #ifdef MHD_SUPPORT_OPENSSL
    433   case MHD_TLS_BACKEND_OPENSSL:
    434     mhd_assert (mhd_tls_open_is_inited_fine ()); /* Must be checked earlier */
    435     res = tls_daemon_init_try (mhd_TLS_MULTI_ROUTE_OPEN,
    436                                d,
    437                                sk_edge_trigg,
    438                                s,
    439                                d_tls);
    440 #endif /* MHD_SUPPORT_OPENSSL */
    441     break;
    442 #ifdef MHD_SUPPORT_MBEDTLS
    443   case MHD_TLS_BACKEND_MBEDTLS:
    444     mhd_assert (mhd_tls_mbed_is_inited_fine ()); /* Must be checked earlier */
    445     res = tls_daemon_init_try (mhd_TLS_MULTI_ROUTE_MBED,
    446                                d,
    447                                sk_edge_trigg,
    448                                s,
    449                                d_tls);
    450 #endif /* MHD_SUPPORT_MBEDTLS */
    451     break;
    452 
    453 #ifndef MHD_SUPPORT_GNUTLS
    454   case MHD_TLS_BACKEND_GNUTLS:
    455 #endif /* ! MHD_SUPPORT_GNUTLS */
    456 #ifndef MHD_SUPPORT_OPENSSL
    457   case MHD_TLS_BACKEND_OPENSSL:
    458 #endif /* ! MHD_SUPPORT_OPENSSL */
    459 #ifndef MHD_SUPPORT_MBEDTLS
    460   case MHD_TLS_BACKEND_MBEDTLS:
    461 #endif /* ! MHD_SUPPORT_MBEDTLS */
    462   case MHD_TLS_BACKEND_NONE:
    463   default:
    464     mhd_UNREACHABLE ();
    465     res = MHD_SC_TLS_BACKEND_UNSUPPORTED;
    466     break;
    467   }
    468   mhd_assert (NULL != d_tls);
    469   if (MHD_SC_OK == res)
    470   {
    471     *p_d_tls = d_tls;
    472     return MHD_SC_OK;
    473   }
    474   free (d_tls);
    475   return res;
    476 }
    477 
    478 
    479 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_
    480 MHD_FN_PAR_INOUT_ (1) void
    481 mhd_tls_multi_daemon_deinit (struct mhd_TlsMultiDaemonData *restrict d_tls)
    482 {
    483   switch (d_tls->choice)
    484   {
    485 #ifdef MHD_SUPPORT_GNUTLS
    486   case mhd_TLS_MULTI_ROUTE_GNU:
    487     mhd_tls_gnu_daemon_deinit (d_tls->data.gnutls);
    488     break;
    489 #endif
    490 #ifdef MHD_SUPPORT_OPENSSL
    491   case mhd_TLS_MULTI_ROUTE_OPEN:
    492     mhd_tls_open_daemon_deinit (d_tls->data.openssl);
    493     break;
    494 #endif
    495 #ifdef MHD_SUPPORT_MBEDTLS
    496   case mhd_TLS_MULTI_ROUTE_MBED:
    497     mhd_tls_mbed_daemon_deinit (d_tls->data.mbedtls);
    498     break;
    499 #endif
    500   case mhd_TLS_MULTI_ROUTE_NONE:
    501   default:
    502     mhd_UNREACHABLE ();
    503     break;
    504   }
    505   free (d_tls);
    506 }
    507 
    508 
    509 #ifdef mhd_HAVE_TLS_THREAD_CLEANUP
    510 /**
    511  * Perform clean-up of TLS resources before thread closing.
    512  * Must be called before thread is closed, after any use of TLS functions
    513  * in the thread, but before de-initialisation of daemon's TLS data.
    514  * @param d_tls the pointer to the daemon's TLS settings
    515  */
    516 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_
    517 MHD_FN_PAR_INOUT_ (1) void
    518 mhd_tls_multi_thread_cleanup (struct mhd_TlsMultiDaemonData *restrict d_tls)
    519 {
    520   switch (d_tls->choice)
    521   {
    522 #  ifdef MHD_SUPPORT_GNUTLS
    523   case mhd_TLS_MULTI_ROUTE_GNU:
    524     mhd_tls_gnu_thread_cleanup (d_tls->data.gnutls);
    525     break;
    526 #  endif
    527 #  ifdef MHD_SUPPORT_OPENSSL
    528   case mhd_TLS_MULTI_ROUTE_OPEN:
    529     mhd_tls_open_thread_cleanup (d_tls->data.openssl);
    530     break;
    531 #  endif
    532 #  ifdef MHD_SUPPORT_MBEDTLS
    533   case mhd_TLS_MULTI_ROUTE_MBED:
    534     mhd_tls_mbed_thread_cleanup (d_tls->data.mbedtls);
    535     break;
    536 #  endif
    537   case mhd_TLS_MULTI_ROUTE_NONE:
    538   default:
    539     mhd_UNREACHABLE ();
    540     break;
    541   }
    542 }
    543 
    544 
    545 #endif /* mhd_HAVE_TLS_THREAD_CLEANUP */
    546 
    547 /* ** Credentials creation / destruction ** */
    548 
    549 #ifdef mhd_HAVE_TLS_ACME
    550 
    551 MHD_INTERNAL MHD_FN_MUST_CHECK_RESULT_
    552 MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (2)
    553 MHD_FN_PAR_NONNULL_ (4) MHD_FN_PAR_NONNULL_ (6)
    554 MHD_FN_PAR_OUT_ (2)
    555 MHD_FN_PAR_IN_SIZE_ (4, 3) MHD_FN_PAR_IN_SIZE_ (6, 5)
    556 MHD_FN_PAR_IN_SIZE_ (8, 7)
    557 MHD_FN_PAR_CSTR_ (4) MHD_FN_PAR_CSTR_ (6) MHD_FN_PAR_CSTR_ (8)
    558 enum mhd_TlsCredCreateResult
    559 mhd_tls_multi_cred_create (struct mhd_TlsMultiDaemonData *restrict d_tls,
    560                            union mhd_TlsCredDataPtr *restrict pp_cred,
    561                            size_t cert_len,
    562                            const char *restrict cert,
    563                            size_t key_len,
    564                            const char *restrict key,
    565                            size_t pass_len,
    566                            const char *restrict pass)
    567 {
    568   switch (d_tls->choice)
    569   {
    570 #  ifdef MHD_SUPPORT_GNUTLS
    571   case mhd_TLS_MULTI_ROUTE_GNU:
    572     return mhd_tls_gnu_cred_create (d_tls->data.gnutls,
    573                                     pp_cred,
    574                                     cert_len,
    575                                     cert,
    576                                     key_len,
    577                                     key,
    578                                     pass_len,
    579                                     pass);
    580 #  endif
    581 #  ifdef MHD_SUPPORT_OPENSSL
    582   case mhd_TLS_MULTI_ROUTE_OPEN:
    583     return mhd_tls_open_cred_create (d_tls->data.openssl,
    584                                      pp_cred,
    585                                      cert_len,
    586                                      cert,
    587                                      key_len,
    588                                      key,
    589                                      pass_len,
    590                                      pass);
    591 #  endif
    592 #  ifdef MHD_SUPPORT_MBEDTLS
    593   case mhd_TLS_MULTI_ROUTE_MBED:
    594     return mhd_tls_mbed_cred_create (d_tls->data.mbedtls,
    595                                      pp_cred,
    596                                      cert_len,
    597                                      cert,
    598                                      key_len,
    599                                      key,
    600                                      pass_len,
    601                                      pass);
    602 #  endif
    603   case mhd_TLS_MULTI_ROUTE_NONE:
    604   default:
    605     mhd_UNREACHABLE ();
    606   }
    607 
    608   return mhd_TLS_CRED_CREATE_UNSUPPORTED;
    609 }
    610 
    611 
    612 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ void
    613 mhd_tls_multi_cred_destroy (struct mhd_TlsMultiDaemonData *restrict d_tls,
    614                             union mhd_TlsCredDataPtr cred)
    615 {
    616   switch (d_tls->choice)
    617   {
    618 #  ifdef MHD_SUPPORT_GNUTLS
    619   case mhd_TLS_MULTI_ROUTE_GNU:
    620     mhd_tls_gnu_cred_destroy (d_tls->data.gnutls,
    621                               cred);
    622     break;
    623 #  endif
    624 #  ifdef MHD_SUPPORT_OPENSSL
    625   case mhd_TLS_MULTI_ROUTE_OPEN:
    626     mhd_tls_open_cred_destroy (d_tls->data.openssl,
    627                                cred);
    628     break;
    629 #  endif
    630 #  ifdef MHD_SUPPORT_MBEDTLS
    631   case mhd_TLS_MULTI_ROUTE_MBED:
    632     mhd_tls_mbed_cred_destroy (d_tls->data.mbedtls,
    633                                cred);
    634     break;
    635 #  endif
    636   case mhd_TLS_MULTI_ROUTE_NONE:
    637   default:
    638     mhd_UNREACHABLE ();
    639   }
    640 }
    641 
    642 
    643 #endif /* mhd_HAVE_TLS_ACME */
    644 
    645 /* ** Connection initialisation / de-initialisation ** */
    646 
    647 MHD_INTERNAL size_t
    648 mhd_tls_multi_conn_get_tls_size (struct mhd_TlsMultiDaemonData *restrict d_tls)
    649 {
    650   size_t data_size;
    651 
    652   data_size = sizeof(struct mhd_TlsMultiConnData);
    653   switch (d_tls->choice)
    654   {
    655 #ifdef MHD_SUPPORT_GNUTLS
    656   case mhd_TLS_MULTI_ROUTE_GNU:
    657     data_size += mhd_tls_gnu_conn_get_tls_size (d_tls->data.gnutls);
    658     break;
    659 #endif
    660 #ifdef MHD_SUPPORT_OPENSSL
    661   case mhd_TLS_MULTI_ROUTE_OPEN:
    662     data_size += mhd_tls_open_conn_get_tls_size (d_tls->data.openssl);
    663     break;
    664 #endif
    665 #ifdef MHD_SUPPORT_MBEDTLS
    666   case mhd_TLS_MULTI_ROUTE_MBED:
    667     data_size += mhd_tls_mbed_conn_get_tls_size (d_tls->data.mbedtls);
    668     break;
    669 #endif
    670   case mhd_TLS_MULTI_ROUTE_NONE:
    671   default:
    672     mhd_UNREACHABLE ();
    673   }
    674 
    675   return data_size;
    676 }
    677 
    678 
    679 MHD_INTERNAL MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_
    680 MHD_FN_PAR_OUT_ (3) bool
    681 mhd_tls_multi_conn_init (const struct mhd_TlsMultiDaemonData *restrict d_tls,
    682                          struct mhd_ConnSocket *sk,
    683                          struct mhd_TlsMultiConnData *restrict c_tls)
    684 {
    685   c_tls->choice = d_tls->choice;
    686   switch (c_tls->choice)
    687   {
    688 #ifdef MHD_SUPPORT_GNUTLS
    689   case mhd_TLS_MULTI_ROUTE_GNU:
    690     /* Assume the same alignment requirements for both structures */
    691     c_tls->data.gnutls = (struct mhd_TlsGnuConnData *)(c_tls + 1);
    692     return mhd_tls_gnu_conn_init (d_tls->data.gnutls,
    693                                   sk,
    694                                   c_tls->data.gnutls);
    695 #endif
    696 #ifdef MHD_SUPPORT_OPENSSL
    697   case mhd_TLS_MULTI_ROUTE_OPEN:
    698     /* Assume the same alignment requirements for both structures */
    699     c_tls->data.openssl = (struct mhd_TlsOpenConnData *)(c_tls + 1);
    700     return mhd_tls_open_conn_init (d_tls->data.openssl,
    701                                    sk,
    702                                    c_tls->data.openssl);
    703 #endif
    704 #ifdef MHD_SUPPORT_MBEDTLS
    705   case mhd_TLS_MULTI_ROUTE_MBED:
    706     /* Assume the same alignment requirements for both structures */
    707     c_tls->data.mbedtls = (struct mhd_TlsMbedConnData *)(c_tls + 1);
    708     return mhd_tls_mbed_conn_init (d_tls->data.mbedtls,
    709                                    sk,
    710                                    c_tls->data.mbedtls);
    711 #endif
    712   case mhd_TLS_MULTI_ROUTE_NONE:
    713   default:
    714     mhd_UNREACHABLE ();
    715     break;
    716   }
    717 
    718   return false;
    719 }
    720 
    721 
    722 /**
    723  * De-initialise connection TLS settings.
    724  * The provided pointer is not freed/deallocated.
    725  * @param c_tls the initialised connection TLS settings
    726  */
    727 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ void
    728 mhd_tls_multi_conn_deinit (struct mhd_TlsMultiConnData *restrict c_tls)
    729 {
    730   switch (c_tls->choice)
    731   {
    732 #ifdef MHD_SUPPORT_GNUTLS
    733   case mhd_TLS_MULTI_ROUTE_GNU:
    734     mhd_tls_gnu_conn_deinit (c_tls->data.gnutls);
    735     break;
    736 #endif
    737 #ifdef MHD_SUPPORT_OPENSSL
    738   case mhd_TLS_MULTI_ROUTE_OPEN:
    739     mhd_tls_open_conn_deinit (c_tls->data.openssl);
    740     break;
    741 #endif
    742 #ifdef MHD_SUPPORT_MBEDTLS
    743   case mhd_TLS_MULTI_ROUTE_MBED:
    744     mhd_tls_mbed_conn_deinit (c_tls->data.mbedtls);
    745     break;
    746 #endif
    747   case mhd_TLS_MULTI_ROUTE_NONE:
    748   default:
    749     mhd_UNREACHABLE ();
    750   }
    751 }
    752 
    753 
    754 /* ** TLS connection establishing ** */
    755 
    756 MHD_INTERNAL MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_
    757 enum mhd_TlsProcedureResult
    758 mhd_tls_multi_conn_handshake (struct mhd_TlsMultiConnData *restrict c_tls)
    759 {
    760   switch (c_tls->choice)
    761   {
    762 #ifdef MHD_SUPPORT_GNUTLS
    763   case mhd_TLS_MULTI_ROUTE_GNU:
    764     return mhd_tls_gnu_conn_handshake (c_tls->data.gnutls);
    765 #endif
    766 #ifdef MHD_SUPPORT_OPENSSL
    767   case mhd_TLS_MULTI_ROUTE_OPEN:
    768     return mhd_tls_open_conn_handshake (c_tls->data.openssl);
    769 #endif
    770 #ifdef MHD_SUPPORT_MBEDTLS
    771   case mhd_TLS_MULTI_ROUTE_MBED:
    772     return mhd_tls_mbed_conn_handshake (c_tls->data.mbedtls);
    773 #endif
    774   case mhd_TLS_MULTI_ROUTE_NONE:
    775   default:
    776     mhd_UNREACHABLE ();
    777     break;
    778   }
    779   return mhd_TLS_PROCED_FAILED;
    780 }
    781 
    782 
    783 MHD_INTERNAL MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_
    784 enum mhd_TlsProcedureResult
    785 mhd_tls_multi_conn_shutdown (struct mhd_TlsMultiConnData *restrict c_tls)
    786 {
    787   switch (c_tls->choice)
    788   {
    789 #ifdef MHD_SUPPORT_GNUTLS
    790   case mhd_TLS_MULTI_ROUTE_GNU:
    791     return mhd_tls_gnu_conn_shutdown (c_tls->data.gnutls);
    792 #endif
    793 #ifdef MHD_SUPPORT_OPENSSL
    794   case mhd_TLS_MULTI_ROUTE_OPEN:
    795     return mhd_tls_open_conn_shutdown (c_tls->data.openssl);
    796 #endif
    797 #ifdef MHD_SUPPORT_MBEDTLS
    798   case mhd_TLS_MULTI_ROUTE_MBED:
    799     return mhd_tls_mbed_conn_shutdown (c_tls->data.mbedtls);
    800 #endif
    801   case mhd_TLS_MULTI_ROUTE_NONE:
    802   default:
    803     mhd_UNREACHABLE ();
    804     break;
    805   }
    806   return mhd_TLS_PROCED_FAILED;
    807 }
    808 
    809 
    810 /* ** Data receiving and sending ** */
    811 
    812 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_
    813 MHD_FN_PAR_OUT_SIZE_ (3, 2)
    814 MHD_FN_PAR_OUT_ (4) enum mhd_SocketError
    815 mhd_tls_multi_conn_recv (struct mhd_TlsMultiConnData *restrict c_tls,
    816                          size_t buf_size,
    817                          char buf[MHD_FN_PAR_DYN_ARR_SIZE_ (buf_size)],
    818                          size_t *restrict received)
    819 {
    820   switch (c_tls->choice)
    821   {
    822 #ifdef MHD_SUPPORT_GNUTLS
    823   case mhd_TLS_MULTI_ROUTE_GNU:
    824     return mhd_tls_gnu_conn_recv (c_tls->data.gnutls,
    825                                   buf_size,
    826                                   buf,
    827                                   received);
    828 #endif
    829 #ifdef MHD_SUPPORT_OPENSSL
    830   case mhd_TLS_MULTI_ROUTE_OPEN:
    831     return mhd_tls_open_conn_recv (c_tls->data.openssl,
    832                                    buf_size,
    833                                    buf,
    834                                    received);
    835 #endif
    836 #ifdef MHD_SUPPORT_MBEDTLS
    837   case mhd_TLS_MULTI_ROUTE_MBED:
    838     return mhd_tls_mbed_conn_recv (c_tls->data.mbedtls,
    839                                    buf_size,
    840                                    buf,
    841                                    received);
    842 #endif
    843   case mhd_TLS_MULTI_ROUTE_NONE:
    844   default:
    845     mhd_UNREACHABLE ();
    846     break;
    847   }
    848   return mhd_SOCKET_ERR_INTERNAL;
    849 }
    850 
    851 
    852 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PURE_ bool
    853 mhd_tls_multi_conn_has_cstm_tr (struct mhd_TlsMultiConnData *restrict c_tls)
    854 {
    855   (void)c_tls;  /* Could be unused if all underling functions are actually macros */
    856   switch (c_tls->choice)
    857   {
    858 #ifdef MHD_SUPPORT_GNUTLS
    859   case mhd_TLS_MULTI_ROUTE_GNU:
    860     return mhd_tls_gnu_conn_has_cstm_tr (c_tls->data.gnutls);
    861 #endif
    862 #ifdef MHD_SUPPORT_OPENSSL
    863   case mhd_TLS_MULTI_ROUTE_OPEN:
    864     return mhd_tls_open_conn_has_cstm_tr (c_tls->data.openssl);
    865 #endif
    866 #ifdef MHD_SUPPORT_MBEDTLS
    867   case mhd_TLS_MULTI_ROUTE_MBED:
    868     return mhd_tls_mbed_conn_has_cstm_tr (c_tls->data.mbedtls);
    869 #endif
    870   case mhd_TLS_MULTI_ROUTE_NONE:
    871   default:
    872     mhd_UNREACHABLE ();
    873     break;
    874   }
    875   return false;
    876 }
    877 
    878 
    879 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ bool
    880 mhd_tls_multi_conn_has_data_in (struct mhd_TlsMultiConnData *restrict c_tls)
    881 {
    882   switch (c_tls->choice)
    883   {
    884 #ifdef MHD_SUPPORT_GNUTLS
    885   case mhd_TLS_MULTI_ROUTE_GNU:
    886     return mhd_tls_gnu_conn_has_data_in (c_tls->data.gnutls);
    887 #endif
    888 #ifdef MHD_SUPPORT_OPENSSL
    889   case mhd_TLS_MULTI_ROUTE_OPEN:
    890     return mhd_tls_open_conn_has_data_in (c_tls->data.openssl);
    891 #endif
    892 #ifdef MHD_SUPPORT_MBEDTLS
    893   case mhd_TLS_MULTI_ROUTE_MBED:
    894     return mhd_tls_mbed_conn_has_data_in (c_tls->data.mbedtls);
    895 #endif
    896   case mhd_TLS_MULTI_ROUTE_NONE:
    897   default:
    898     mhd_UNREACHABLE ();
    899     break;
    900   }
    901   return false;
    902 }
    903 
    904 
    905 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_
    906 MHD_FN_PAR_IN_SIZE_ (3, 2)
    907 MHD_FN_PAR_OUT_ (5) enum mhd_SocketError
    908 mhd_tls_multi_conn_send (struct mhd_TlsMultiConnData *restrict c_tls,
    909                          size_t buf_size,
    910                          const char buf[MHD_FN_PAR_DYN_ARR_SIZE_ (buf_size)],
    911                          bool push_data,
    912                          size_t *restrict sent)
    913 {
    914   (void)push_data;  /* Could be unused if not supported by all backends */
    915   switch (c_tls->choice)
    916   {
    917 #ifdef MHD_SUPPORT_GNUTLS
    918   case mhd_TLS_MULTI_ROUTE_GNU:
    919     return mhd_tls_gnu_conn_send (c_tls->data.gnutls,
    920                                   buf_size,
    921                                   buf,
    922                                   push_data,
    923                                   sent);
    924 #endif
    925 #ifdef MHD_SUPPORT_OPENSSL
    926   case mhd_TLS_MULTI_ROUTE_OPEN:
    927     return mhd_tls_open_conn_send (c_tls->data.openssl,
    928                                    buf_size,
    929                                    buf,
    930                                    push_data,
    931                                    sent);
    932 #endif
    933 #ifdef MHD_SUPPORT_MBEDTLS
    934   case mhd_TLS_MULTI_ROUTE_MBED:
    935     return mhd_tls_mbed_conn_send (c_tls->data.mbedtls,
    936                                    buf_size,
    937                                    buf,
    938                                    push_data,
    939                                    sent);
    940 #endif
    941   case mhd_TLS_MULTI_ROUTE_NONE:
    942   default:
    943     mhd_UNREACHABLE ();
    944     break;
    945   }
    946   return mhd_SOCKET_ERR_INTERNAL;
    947 }
    948 
    949 
    950 /* ** TLS connection information ** */
    951 
    952 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_
    953 MHD_FN_PAR_OUT_ (2) void
    954 mhd_tls_multi_conn_get_tls_sess (
    955   struct mhd_TlsMultiConnData *restrict c_tls,
    956   union MHD_ConnInfoDynamicTlsSess *restrict tls_sess_out)
    957 {
    958   switch (c_tls->choice)
    959   {
    960 #ifdef MHD_SUPPORT_GNUTLS
    961   case mhd_TLS_MULTI_ROUTE_GNU:
    962     mhd_tls_gnu_conn_get_tls_sess (c_tls->data.gnutls,
    963                                    tls_sess_out);
    964     break;
    965 #endif
    966 #ifdef MHD_SUPPORT_OPENSSL
    967   case mhd_TLS_MULTI_ROUTE_OPEN:
    968     mhd_tls_open_conn_get_tls_sess (c_tls->data.openssl,
    969                                     tls_sess_out);
    970     break;
    971 #endif
    972 #ifdef MHD_SUPPORT_MBEDTLS
    973   case mhd_TLS_MULTI_ROUTE_MBED:
    974     mhd_tls_mbed_conn_get_tls_sess (c_tls->data.mbedtls,
    975                                     tls_sess_out);
    976     break;
    977 #endif
    978   case mhd_TLS_MULTI_ROUTE_NONE:
    979   default:
    980     mhd_UNREACHABLE ();
    981     break;
    982   }
    983 }
    984 
    985 
    986 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_
    987 MHD_FN_PAR_OUT_ (2) bool
    988 mhd_tls_multi_conn_get_tls_ver (struct mhd_TlsMultiConnData *restrict c_tls,
    989                                 struct mhd_StctTlsVersion *restrict tls_ver_out)
    990 {
    991   switch (c_tls->choice)
    992   {
    993 #ifdef MHD_SUPPORT_GNUTLS
    994   case mhd_TLS_MULTI_ROUTE_GNU:
    995     return mhd_tls_gnu_conn_get_tls_ver (c_tls->data.gnutls,
    996                                          tls_ver_out);
    997 #endif
    998 #ifdef MHD_SUPPORT_OPENSSL
    999   case mhd_TLS_MULTI_ROUTE_OPEN:
   1000     return mhd_tls_open_conn_get_tls_ver (c_tls->data.openssl,
   1001                                           tls_ver_out);
   1002 #endif
   1003 #ifdef MHD_SUPPORT_MBEDTLS
   1004   case mhd_TLS_MULTI_ROUTE_MBED:
   1005     return mhd_tls_mbed_conn_get_tls_ver (c_tls->data.mbedtls,
   1006                                           tls_ver_out);
   1007 #endif
   1008   case mhd_TLS_MULTI_ROUTE_NONE:
   1009   default:
   1010     mhd_UNREACHABLE ();
   1011     break;
   1012   }
   1013   return false;
   1014 }
   1015 
   1016 
   1017 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ enum mhd_TlsAlpnProt
   1018 mhd_tls_multi_conn_get_alpn_prot (struct mhd_TlsMultiConnData *restrict c_tls)
   1019 {
   1020   switch (c_tls->choice)
   1021   {
   1022 #ifdef MHD_SUPPORT_GNUTLS
   1023   case mhd_TLS_MULTI_ROUTE_GNU:
   1024     return mhd_tls_gnu_conn_get_alpn_prot (c_tls->data.gnutls);
   1025 #endif
   1026 #ifdef MHD_SUPPORT_OPENSSL
   1027   case mhd_TLS_MULTI_ROUTE_OPEN:
   1028     return mhd_tls_open_conn_get_alpn_prot (c_tls->data.openssl);
   1029 #endif
   1030 #ifdef MHD_SUPPORT_MBEDTLS
   1031   case mhd_TLS_MULTI_ROUTE_MBED:
   1032     return mhd_tls_mbed_conn_get_alpn_prot (c_tls->data.mbedtls);
   1033 #endif
   1034   case mhd_TLS_MULTI_ROUTE_NONE:
   1035   default:
   1036     mhd_UNREACHABLE ();
   1037     break;
   1038   }
   1039   return mhd_TLS_ALPN_PROT_NOT_SELECTED;
   1040 }
   1041 
   1042 
   1043 #ifdef mhd_HAVE_TLS_ACME
   1044 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ bool
   1045 mhd_tls_multi_conn_is_acme (struct mhd_TlsMultiConnData *restrict c_tls)
   1046 {
   1047   switch (c_tls->choice)
   1048   {
   1049 #  ifdef MHD_SUPPORT_GNUTLS
   1050   case mhd_TLS_MULTI_ROUTE_GNU:
   1051     return mhd_tls_gnu_conn_is_acme (c_tls->data.gnutls);
   1052 #  endif
   1053 #  ifdef MHD_SUPPORT_OPENSSL
   1054   case mhd_TLS_MULTI_ROUTE_OPEN:
   1055     return mhd_tls_open_conn_is_acme (c_tls->data.openssl);
   1056 #  endif
   1057 #  ifdef MHD_SUPPORT_MBEDTLS
   1058   case mhd_TLS_MULTI_ROUTE_MBED:
   1059     return mhd_tls_mbed_conn_is_acme (c_tls->data.mbedtls);
   1060 #  endif
   1061   case mhd_TLS_MULTI_ROUTE_NONE:
   1062   default:
   1063     mhd_UNREACHABLE ();
   1064     break;
   1065   }
   1066   return false;
   1067 }
   1068 
   1069 
   1070 #endif /* mhd_HAVE_TLS_ACME */