libmicrohttpd2

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

tls_multi_funcs.c (24806B)


      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       return true;
    159 #endif
    160 #ifdef MHD_SUPPORT_OPENSSL
    161     if (mhd_tls_open_is_edge_trigg_supported (s)
    162         && mhd_tls_open_is_inited_fine ())
    163       return true;
    164 #endif
    165 #ifdef MHD_SUPPORT_MBEDTLS
    166     if (mhd_tls_mbed_is_edge_trigg_supported (s)
    167         && mhd_tls_mbed_is_inited_fine ())
    168       return true;
    169 #endif
    170     return false;
    171   case MHD_TLS_BACKEND_GNUTLS:
    172 #ifdef MHD_SUPPORT_GNUTLS
    173     /* Ignore "backend inited" status here,
    174        it will be checked on daemon TLS init */
    175     return mhd_tls_gnu_is_edge_trigg_supported (s);
    176 #endif
    177     break;
    178   case MHD_TLS_BACKEND_OPENSSL:
    179 #ifdef MHD_SUPPORT_OPENSSL
    180     /* Ignore "backend inited" status here,
    181        it will be checked on daemon TLS init */
    182     return mhd_tls_open_is_edge_trigg_supported (s);
    183 #endif
    184     break;
    185   case MHD_TLS_BACKEND_MBEDTLS:
    186 #ifdef MHD_SUPPORT_MBEDTLS
    187     /* Ignore "backend inited" status here,
    188        it will be checked on daemon TLS init */
    189     return mhd_tls_mbed_is_edge_trigg_supported (s);
    190 #endif
    191     break;
    192   default:
    193     mhd_UNREACHABLE ();
    194     break;
    195   }
    196   return false;
    197 }
    198 
    199 
    200 /**
    201  * Initialise selected TLS backend for the daemon
    202  * @param route the selected TLS backend
    203  * @param d the daemon handle
    204  * @param s the daemon settings
    205  * @param d_tls the daemon's TLS settings, backend-specific data is allocated
    206  *              and initialised
    207  * @return #MHD_SC_OK on success (the backend-specific data is allocated),
    208  *         error code otherwise
    209  */
    210 static MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_
    211 MHD_FN_PAR_OUT_ (5) mhd_StatusCodeInt
    212 tls_daemon_init_try (enum mhd_TlsMultiRoute route,
    213                      struct MHD_Daemon *restrict d,
    214                      bool sk_edge_trigg,
    215                      struct DaemonOptions *restrict s,
    216                      struct mhd_TlsMultiDaemonData *restrict d_tls)
    217 {
    218   mhd_StatusCodeInt res;
    219 
    220 #ifndef MHD_SUPPORT_OPENSSL
    221   (void) sk_edge_trigg; /* Unused, mute compiler warning */
    222 #endif /* ! MHD_SUPPORT_OPENSSL */
    223 
    224   switch (route)
    225   {
    226 #ifdef MHD_SUPPORT_GNUTLS
    227   case mhd_TLS_MULTI_ROUTE_GNU:
    228     if (! mhd_tls_gnu_is_inited_fine ())
    229       return MHD_SC_TLS_BACKEND_UNAVAILABLE;
    230     res = mhd_tls_gnu_daemon_init (d,
    231                                    sk_edge_trigg,
    232                                    s,
    233                                    &(d_tls->data.gnutls));
    234     if (MHD_SC_OK == res)
    235     {
    236       mhd_M_DEBUG_PRINT ("GnuTLS backend initialised successfully " \
    237                          "for the daemon");
    238       d_tls->choice = route;
    239       return MHD_SC_OK;
    240     }
    241     mhd_M_DEBUG_PRINT1 ("Failed to initialise GnuTLS backend for " \
    242                         "the daemon, error code: %u", (unsigned) res);
    243     return res;
    244 #endif
    245 #ifdef MHD_SUPPORT_OPENSSL
    246   case mhd_TLS_MULTI_ROUTE_OPEN:
    247     if (! mhd_tls_open_is_inited_fine ())
    248       return MHD_SC_TLS_BACKEND_UNAVAILABLE;
    249     res = mhd_tls_open_daemon_init (d,
    250                                     sk_edge_trigg,
    251                                     s,
    252                                     &(d_tls->data.openssl));
    253     if (MHD_SC_OK == res)
    254     {
    255       mhd_M_DEBUG_PRINT ("OpenSSL backend initialised successfully " \
    256                          "for the daemon");
    257       d_tls->choice = route;
    258       return MHD_SC_OK;
    259     }
    260     mhd_M_DEBUG_PRINT1 ("Failed to initialise OpenSSL backend for " \
    261                         "the daemon, error code: %u", (unsigned) res);
    262     return res;
    263 #endif
    264 #ifdef MHD_SUPPORT_MBEDTLS
    265   case mhd_TLS_MULTI_ROUTE_MBED:
    266     if (! mhd_tls_mbed_is_inited_fine ())
    267       return MHD_SC_TLS_BACKEND_UNAVAILABLE;
    268     res = mhd_tls_mbed_daemon_init (d,
    269                                     sk_edge_trigg,
    270                                     s,
    271                                     &(d_tls->data.mbedtls));
    272     if (MHD_SC_OK == res)
    273     {
    274       mhd_M_DEBUG_PRINT ("MbedTLS backend initialised successfully " \
    275                          "for the daemon");
    276       d_tls->choice = route;
    277       return MHD_SC_OK;
    278     }
    279     mhd_M_DEBUG_PRINT1 ("Failed to initialise MbedTLS backend for " \
    280                         "the daemon, error code: %u", (unsigned) res);
    281     return res;
    282 #endif
    283   case mhd_TLS_MULTI_ROUTE_NONE:
    284   default:
    285     break;
    286   }
    287   mhd_assert (0 && "Impossible value");
    288   mhd_UNREACHABLE ();
    289   return MHD_SC_INTERNAL_ERROR;
    290 }
    291 
    292 
    293 MHD_INTERNAL MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_
    294 MHD_FN_PAR_OUT_ (4) mhd_StatusCodeInt
    295 mhd_tls_multi_daemon_init (struct MHD_Daemon *restrict d,
    296                            bool sk_edge_trigg,
    297                            struct DaemonOptions *restrict s,
    298                            struct mhd_TlsMultiDaemonData **restrict p_d_tls)
    299 {
    300   mhd_StatusCodeInt res;
    301   struct mhd_TlsMultiDaemonData *restrict d_tls;
    302   d_tls = (struct mhd_TlsMultiDaemonData *)
    303           mhd_calloc (1,
    304                       sizeof (struct mhd_TlsMultiDaemonData));
    305   if (NULL == d_tls)
    306     return MHD_SC_DAEMON_MEM_ALLOC_FAILURE;
    307 
    308   res = MHD_SC_INTERNAL_ERROR; /* Mute compiler warning, the value should not be used */
    309   switch (s->tls)
    310   {
    311   case MHD_TLS_BACKEND_ANY:
    312     if (1)
    313     {
    314       size_t i;
    315       enum mhd_TlsMultiRoute backends[] = {
    316 #ifdef MHD_SUPPORT_GNUTLS
    317         mhd_TLS_MULTI_ROUTE_GNU,
    318 #endif
    319 #ifdef MHD_SUPPORT_OPENSSL
    320         mhd_TLS_MULTI_ROUTE_OPEN,
    321 #endif
    322 #ifdef MHD_SUPPORT_MBEDTLS
    323         mhd_TLS_MULTI_ROUTE_MBED,
    324 #endif
    325         mhd_TLS_MULTI_ROUTE_NONE  /* Not used */
    326       };
    327       /* Try backends one-by-one */
    328       for (i = 0; i < mhd_ARR_NUM_ELEMS (backends) - 1; ++i)
    329       {
    330         res = tls_daemon_init_try (backends[i],
    331                                    d,
    332                                    sk_edge_trigg,
    333                                    s,
    334                                    d_tls);
    335         if (MHD_SC_OK == res)
    336           break;
    337       }
    338     }
    339     break;
    340 #ifdef MHD_SUPPORT_GNUTLS
    341   case MHD_TLS_BACKEND_GNUTLS:
    342     mhd_assert (mhd_tls_gnu_is_inited_fine ()); /* Must be checked earlier */
    343     res = tls_daemon_init_try (mhd_TLS_MULTI_ROUTE_GNU,
    344                                d,
    345                                sk_edge_trigg,
    346                                s,
    347                                d_tls);
    348     break;
    349 #endif /* MHD_SUPPORT_GNUTLS */
    350 #ifdef MHD_SUPPORT_OPENSSL
    351   case MHD_TLS_BACKEND_OPENSSL:
    352     mhd_assert (mhd_tls_open_is_inited_fine ()); /* Must be checked earlier */
    353     res = tls_daemon_init_try (mhd_TLS_MULTI_ROUTE_OPEN,
    354                                d,
    355                                sk_edge_trigg,
    356                                s,
    357                                d_tls);
    358 #endif /* MHD_SUPPORT_OPENSSL */
    359     break;
    360 #ifdef MHD_SUPPORT_MBEDTLS
    361   case MHD_TLS_BACKEND_MBEDTLS:
    362     mhd_assert (mhd_tls_mbed_is_inited_fine ()); /* Must be checked earlier */
    363     res = tls_daemon_init_try (mhd_TLS_MULTI_ROUTE_MBED,
    364                                d,
    365                                sk_edge_trigg,
    366                                s,
    367                                d_tls);
    368 #endif /* MHD_SUPPORT_MBEDTLS */
    369     break;
    370 
    371 #ifndef MHD_SUPPORT_GNUTLS
    372   case MHD_TLS_BACKEND_GNUTLS:
    373 #endif /* ! MHD_SUPPORT_GNUTLS */
    374 #ifndef MHD_SUPPORT_OPENSSL
    375   case MHD_TLS_BACKEND_OPENSSL:
    376 #endif /* ! MHD_SUPPORT_OPENSSL */
    377 #ifndef MHD_SUPPORT_MBEDTLS
    378   case MHD_TLS_BACKEND_MBEDTLS:
    379 #endif /* ! MHD_SUPPORT_MBEDTLS */
    380   case MHD_TLS_BACKEND_NONE:
    381   default:
    382     mhd_UNREACHABLE ();
    383     res = MHD_SC_TLS_BACKEND_UNSUPPORTED;
    384     break;
    385   }
    386   mhd_assert (NULL != d_tls);
    387   if (MHD_SC_OK == res)
    388   {
    389     *p_d_tls = d_tls;
    390     return MHD_SC_OK;
    391   }
    392   free (d_tls);
    393   return res;
    394 }
    395 
    396 
    397 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_
    398 MHD_FN_PAR_INOUT_ (1) void
    399 mhd_tls_multi_daemon_deinit (struct mhd_TlsMultiDaemonData *restrict d_tls)
    400 {
    401   switch (d_tls->choice)
    402   {
    403 #ifdef MHD_SUPPORT_GNUTLS
    404   case mhd_TLS_MULTI_ROUTE_GNU:
    405     mhd_tls_gnu_daemon_deinit (d_tls->data.gnutls);
    406     break;
    407 #endif
    408 #ifdef MHD_SUPPORT_OPENSSL
    409   case mhd_TLS_MULTI_ROUTE_OPEN:
    410     mhd_tls_open_daemon_deinit (d_tls->data.openssl);
    411     break;
    412 #endif
    413 #ifdef MHD_SUPPORT_MBEDTLS
    414   case mhd_TLS_MULTI_ROUTE_MBED:
    415     mhd_tls_mbed_daemon_deinit (d_tls->data.mbedtls);
    416     break;
    417 #endif
    418   case mhd_TLS_MULTI_ROUTE_NONE:
    419   default:
    420     mhd_UNREACHABLE ();
    421     break;
    422   }
    423   free (d_tls);
    424 }
    425 
    426 
    427 #ifdef mhd_HAVE_TLS_THREAD_CLEANUP
    428 /**
    429  * Perform clean-up of TLS resources before thread closing.
    430  * Must be called before thread is closed, after any use of TLS functions
    431  * in the thread, but before de-initialisation of daemon's TLS data.
    432  * @param d_tls the pointer to the daemon's TLS settings
    433  */
    434 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_
    435 MHD_FN_PAR_INOUT_ (1) void
    436 mhd_tls_multi_thread_cleanup (struct mhd_TlsMultiDaemonData *restrict d_tls)
    437 {
    438   switch (d_tls->choice)
    439   {
    440 #ifdef MHD_SUPPORT_GNUTLS
    441   case mhd_TLS_MULTI_ROUTE_GNU:
    442     mhd_tls_gnu_thread_cleanup (d_tls->data.gnutls);
    443     break;
    444 #endif
    445 #ifdef MHD_SUPPORT_OPENSSL
    446   case mhd_TLS_MULTI_ROUTE_OPEN:
    447     mhd_tls_open_thread_cleanup (d_tls->data.openssl);
    448     break;
    449 #endif
    450 #ifdef MHD_SUPPORT_MBEDTLS
    451   case mhd_TLS_MULTI_ROUTE_MBED:
    452     mhd_tls_mbed_thread_cleanup (d_tls->data.mbedtls);
    453     break;
    454 #endif
    455   case mhd_TLS_MULTI_ROUTE_NONE:
    456   default:
    457     mhd_UNREACHABLE ();
    458     break;
    459   }
    460 }
    461 
    462 
    463 #endif /* mhd_HAVE_TLS_THREAD_CLEANUP */
    464 
    465 /* ** Connection initialisation / de-initialisation ** */
    466 
    467 MHD_INTERNAL size_t
    468 mhd_tls_multi_conn_get_tls_size (struct mhd_TlsMultiDaemonData *restrict d_tls)
    469 {
    470   size_t data_size;
    471 
    472   data_size = sizeof(struct mhd_TlsMultiConnData);
    473   switch (d_tls->choice)
    474   {
    475 #ifdef MHD_SUPPORT_GNUTLS
    476   case mhd_TLS_MULTI_ROUTE_GNU:
    477     data_size += mhd_tls_gnu_conn_get_tls_size (d_tls->data.gnutls);
    478     break;
    479 #endif
    480 #ifdef MHD_SUPPORT_OPENSSL
    481   case mhd_TLS_MULTI_ROUTE_OPEN:
    482     data_size += mhd_tls_open_conn_get_tls_size (d_tls->data.openssl);
    483     break;
    484 #endif
    485 #ifdef MHD_SUPPORT_MBEDTLS
    486   case mhd_TLS_MULTI_ROUTE_MBED:
    487     data_size += mhd_tls_mbed_conn_get_tls_size (d_tls->data.mbedtls);
    488     break;
    489 #endif
    490   case mhd_TLS_MULTI_ROUTE_NONE:
    491   default:
    492     mhd_UNREACHABLE ();
    493   }
    494 
    495   return data_size;
    496 }
    497 
    498 
    499 MHD_INTERNAL MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_
    500 MHD_FN_PAR_OUT_ (3) bool
    501 mhd_tls_multi_conn_init (const struct mhd_TlsMultiDaemonData *restrict d_tls,
    502                          struct mhd_ConnSocket *sk,
    503                          struct mhd_TlsMultiConnData *restrict c_tls)
    504 {
    505   c_tls->choice = d_tls->choice;
    506   switch (c_tls->choice)
    507   {
    508 #ifdef MHD_SUPPORT_GNUTLS
    509   case mhd_TLS_MULTI_ROUTE_GNU:
    510     /* Assume the same alignment requirements for both structures */
    511     c_tls->data.gnutls = (struct mhd_TlsGnuConnData *) (c_tls + 1);
    512     return mhd_tls_gnu_conn_init (d_tls->data.gnutls,
    513                                   sk,
    514                                   c_tls->data.gnutls);
    515 #endif
    516 #ifdef MHD_SUPPORT_OPENSSL
    517   case mhd_TLS_MULTI_ROUTE_OPEN:
    518     /* Assume the same alignment requirements for both structures */
    519     c_tls->data.openssl = (struct mhd_TlsOpenConnData *) (c_tls + 1);
    520     return mhd_tls_open_conn_init (d_tls->data.openssl,
    521                                    sk,
    522                                    c_tls->data.openssl);
    523 #endif
    524 #ifdef MHD_SUPPORT_MBEDTLS
    525   case mhd_TLS_MULTI_ROUTE_MBED:
    526     /* Assume the same alignment requirements for both structures */
    527     c_tls->data.mbedtls = (struct mhd_TlsMbedConnData *) (c_tls + 1);
    528     return mhd_tls_mbed_conn_init (d_tls->data.mbedtls,
    529                                    sk,
    530                                    c_tls->data.mbedtls);
    531 #endif
    532   case mhd_TLS_MULTI_ROUTE_NONE:
    533   default:
    534     mhd_UNREACHABLE ();
    535     break;
    536   }
    537 
    538   return false;
    539 }
    540 
    541 
    542 /**
    543  * De-initialise connection TLS settings.
    544  * The provided pointer is not freed/deallocated.
    545  * @param c_tls the initialised connection TLS settings
    546  */
    547 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ void
    548 mhd_tls_multi_conn_deinit (struct mhd_TlsMultiConnData *restrict c_tls)
    549 {
    550   switch (c_tls->choice)
    551   {
    552 #ifdef MHD_SUPPORT_GNUTLS
    553   case mhd_TLS_MULTI_ROUTE_GNU:
    554     mhd_tls_gnu_conn_deinit (c_tls->data.gnutls);
    555     break;
    556 #endif
    557 #ifdef MHD_SUPPORT_OPENSSL
    558   case mhd_TLS_MULTI_ROUTE_OPEN:
    559     mhd_tls_open_conn_deinit (c_tls->data.openssl);
    560     break;
    561 #endif
    562 #ifdef MHD_SUPPORT_MBEDTLS
    563   case mhd_TLS_MULTI_ROUTE_MBED:
    564     mhd_tls_mbed_conn_deinit (c_tls->data.mbedtls);
    565     break;
    566 #endif
    567   case mhd_TLS_MULTI_ROUTE_NONE:
    568   default:
    569     mhd_UNREACHABLE ();
    570   }
    571 }
    572 
    573 
    574 /* ** TLS connection establishing ** */
    575 
    576 MHD_INTERNAL MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_
    577 enum mhd_TlsProcedureResult
    578 mhd_tls_multi_conn_handshake (struct mhd_TlsMultiConnData *restrict c_tls)
    579 {
    580   switch (c_tls->choice)
    581   {
    582 #ifdef MHD_SUPPORT_GNUTLS
    583   case mhd_TLS_MULTI_ROUTE_GNU:
    584     return mhd_tls_gnu_conn_handshake (c_tls->data.gnutls);
    585 #endif
    586 #ifdef MHD_SUPPORT_OPENSSL
    587   case mhd_TLS_MULTI_ROUTE_OPEN:
    588     return mhd_tls_open_conn_handshake (c_tls->data.openssl);
    589 #endif
    590 #ifdef MHD_SUPPORT_MBEDTLS
    591   case mhd_TLS_MULTI_ROUTE_MBED:
    592     return mhd_tls_mbed_conn_handshake (c_tls->data.mbedtls);
    593 #endif
    594   case mhd_TLS_MULTI_ROUTE_NONE:
    595   default:
    596     mhd_UNREACHABLE ();
    597     break;
    598   }
    599   return mhd_TLS_PROCED_FAILED;
    600 }
    601 
    602 
    603 MHD_INTERNAL MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_
    604 enum mhd_TlsProcedureResult
    605 mhd_tls_multi_conn_shutdown (struct mhd_TlsMultiConnData *restrict c_tls)
    606 {
    607   switch (c_tls->choice)
    608   {
    609 #ifdef MHD_SUPPORT_GNUTLS
    610   case mhd_TLS_MULTI_ROUTE_GNU:
    611     return mhd_tls_gnu_conn_shutdown (c_tls->data.gnutls);
    612 #endif
    613 #ifdef MHD_SUPPORT_OPENSSL
    614   case mhd_TLS_MULTI_ROUTE_OPEN:
    615     return mhd_tls_open_conn_shutdown (c_tls->data.openssl);
    616 #endif
    617 #ifdef MHD_SUPPORT_MBEDTLS
    618   case mhd_TLS_MULTI_ROUTE_MBED:
    619     return mhd_tls_mbed_conn_shutdown (c_tls->data.mbedtls);
    620 #endif
    621   case mhd_TLS_MULTI_ROUTE_NONE:
    622   default:
    623     mhd_UNREACHABLE ();
    624     break;
    625   }
    626   return mhd_TLS_PROCED_FAILED;
    627 }
    628 
    629 
    630 /* ** Data receiving and sending ** */
    631 
    632 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_
    633 MHD_FN_PAR_OUT_SIZE_ (3,2)
    634 MHD_FN_PAR_OUT_ (4) enum mhd_SocketError
    635 mhd_tls_multi_conn_recv (struct mhd_TlsMultiConnData *restrict c_tls,
    636                          size_t buf_size,
    637                          char buf[MHD_FN_PAR_DYN_ARR_SIZE_ (buf_size)],
    638                          size_t *restrict received)
    639 {
    640   switch (c_tls->choice)
    641   {
    642 #ifdef MHD_SUPPORT_GNUTLS
    643   case mhd_TLS_MULTI_ROUTE_GNU:
    644     return mhd_tls_gnu_conn_recv (c_tls->data.gnutls,
    645                                   buf_size,
    646                                   buf,
    647                                   received);
    648 #endif
    649 #ifdef MHD_SUPPORT_OPENSSL
    650   case mhd_TLS_MULTI_ROUTE_OPEN:
    651     return mhd_tls_open_conn_recv (c_tls->data.openssl,
    652                                    buf_size,
    653                                    buf,
    654                                    received);
    655 #endif
    656 #ifdef MHD_SUPPORT_MBEDTLS
    657   case mhd_TLS_MULTI_ROUTE_MBED:
    658     return mhd_tls_mbed_conn_recv (c_tls->data.mbedtls,
    659                                    buf_size,
    660                                    buf,
    661                                    received);
    662 #endif
    663   case mhd_TLS_MULTI_ROUTE_NONE:
    664   default:
    665     mhd_UNREACHABLE ();
    666     break;
    667   }
    668   return mhd_SOCKET_ERR_INTERNAL;
    669 }
    670 
    671 
    672 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PURE_ bool
    673 mhd_tls_multi_conn_has_cstm_tr (struct mhd_TlsMultiConnData *restrict c_tls)
    674 {
    675   (void) c_tls; /* Could be unused if all underling functions are actually macros */
    676   switch (c_tls->choice)
    677   {
    678 #ifdef MHD_SUPPORT_GNUTLS
    679   case mhd_TLS_MULTI_ROUTE_GNU:
    680     return mhd_tls_gnu_conn_has_cstm_tr (c_tls->data.gnutls);
    681 #endif
    682 #ifdef MHD_SUPPORT_OPENSSL
    683   case mhd_TLS_MULTI_ROUTE_OPEN:
    684     return mhd_tls_open_conn_has_cstm_tr (c_tls->data.openssl);
    685 #endif
    686 #ifdef MHD_SUPPORT_MBEDTLS
    687   case mhd_TLS_MULTI_ROUTE_MBED:
    688     return mhd_tls_mbed_conn_has_cstm_tr (c_tls->data.mbedtls);
    689 #endif
    690   case mhd_TLS_MULTI_ROUTE_NONE:
    691   default:
    692     mhd_UNREACHABLE ();
    693     break;
    694   }
    695   return false;
    696 }
    697 
    698 
    699 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ bool
    700 mhd_tls_multi_conn_has_data_in (struct mhd_TlsMultiConnData *restrict c_tls)
    701 {
    702   switch (c_tls->choice)
    703   {
    704 #ifdef MHD_SUPPORT_GNUTLS
    705   case mhd_TLS_MULTI_ROUTE_GNU:
    706     return mhd_tls_gnu_conn_has_data_in (c_tls->data.gnutls);
    707 #endif
    708 #ifdef MHD_SUPPORT_OPENSSL
    709   case mhd_TLS_MULTI_ROUTE_OPEN:
    710     return mhd_tls_open_conn_has_data_in (c_tls->data.openssl);
    711 #endif
    712 #ifdef MHD_SUPPORT_MBEDTLS
    713   case mhd_TLS_MULTI_ROUTE_MBED:
    714     return mhd_tls_mbed_conn_has_data_in (c_tls->data.mbedtls);
    715 #endif
    716   case mhd_TLS_MULTI_ROUTE_NONE:
    717   default:
    718     mhd_UNREACHABLE ();
    719     break;
    720   }
    721   return false;
    722 }
    723 
    724 
    725 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_
    726 MHD_FN_PAR_IN_SIZE_ (3,2)
    727 MHD_FN_PAR_OUT_ (5) enum mhd_SocketError
    728 mhd_tls_multi_conn_send (struct mhd_TlsMultiConnData *restrict c_tls,
    729                          size_t buf_size,
    730                          const char buf[MHD_FN_PAR_DYN_ARR_SIZE_ (buf_size)],
    731                          bool push_data,
    732                          size_t *restrict sent)
    733 {
    734   (void) push_data; /* Could be unused if not supported by all backends */
    735   switch (c_tls->choice)
    736   {
    737 #ifdef MHD_SUPPORT_GNUTLS
    738   case mhd_TLS_MULTI_ROUTE_GNU:
    739     return mhd_tls_gnu_conn_send (c_tls->data.gnutls,
    740                                   buf_size,
    741                                   buf,
    742                                   push_data,
    743                                   sent);
    744 #endif
    745 #ifdef MHD_SUPPORT_OPENSSL
    746   case mhd_TLS_MULTI_ROUTE_OPEN:
    747     return mhd_tls_open_conn_send (c_tls->data.openssl,
    748                                    buf_size,
    749                                    buf,
    750                                    push_data,
    751                                    sent);
    752 #endif
    753 #ifdef MHD_SUPPORT_MBEDTLS
    754   case mhd_TLS_MULTI_ROUTE_MBED:
    755     return mhd_tls_mbed_conn_send (c_tls->data.mbedtls,
    756                                    buf_size,
    757                                    buf,
    758                                    push_data,
    759                                    sent);
    760 #endif
    761   case mhd_TLS_MULTI_ROUTE_NONE:
    762   default:
    763     mhd_UNREACHABLE ();
    764     break;
    765   }
    766   return mhd_SOCKET_ERR_INTERNAL;
    767 }
    768 
    769 
    770 /* ** TLS connection information ** */
    771 
    772 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_
    773 MHD_FN_PAR_OUT_ (2) void
    774 mhd_tls_multi_conn_get_tls_sess (
    775   struct mhd_TlsMultiConnData *restrict c_tls,
    776   union MHD_ConnInfoDynamicTlsSess *restrict tls_sess_out)
    777 {
    778   switch (c_tls->choice)
    779   {
    780 #ifdef MHD_SUPPORT_GNUTLS
    781   case mhd_TLS_MULTI_ROUTE_GNU:
    782     mhd_tls_gnu_conn_get_tls_sess (c_tls->data.gnutls,
    783                                    tls_sess_out);
    784     break;
    785 #endif
    786 #ifdef MHD_SUPPORT_OPENSSL
    787   case mhd_TLS_MULTI_ROUTE_OPEN:
    788     mhd_tls_open_conn_get_tls_sess (c_tls->data.openssl,
    789                                     tls_sess_out);
    790     break;
    791 #endif
    792 #ifdef MHD_SUPPORT_MBEDTLS
    793   case mhd_TLS_MULTI_ROUTE_MBED:
    794     mhd_tls_mbed_conn_get_tls_sess (c_tls->data.mbedtls,
    795                                     tls_sess_out);
    796     break;
    797 #endif
    798   case mhd_TLS_MULTI_ROUTE_NONE:
    799   default:
    800     mhd_UNREACHABLE ();
    801     break;
    802   }
    803 }
    804 
    805 
    806 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_
    807 MHD_FN_PAR_OUT_ (2) bool
    808 mhd_tls_multi_conn_get_tls_ver (struct mhd_TlsMultiConnData *restrict c_tls,
    809                                 struct mhd_StctTlsVersion *restrict tls_ver_out)
    810 {
    811   switch (c_tls->choice)
    812   {
    813 #ifdef MHD_SUPPORT_GNUTLS
    814   case mhd_TLS_MULTI_ROUTE_GNU:
    815     return mhd_tls_gnu_conn_get_tls_ver (c_tls->data.gnutls,
    816                                          tls_ver_out);
    817 #endif
    818 #ifdef MHD_SUPPORT_OPENSSL
    819   case mhd_TLS_MULTI_ROUTE_OPEN:
    820     return mhd_tls_open_conn_get_tls_ver (c_tls->data.openssl,
    821                                           tls_ver_out);
    822 #endif
    823 #ifdef MHD_SUPPORT_MBEDTLS
    824   case mhd_TLS_MULTI_ROUTE_MBED:
    825     return mhd_tls_mbed_conn_get_tls_ver (c_tls->data.mbedtls,
    826                                           tls_ver_out);
    827 #endif
    828   case mhd_TLS_MULTI_ROUTE_NONE:
    829   default:
    830     mhd_UNREACHABLE ();
    831     break;
    832   }
    833   return false;
    834 }
    835 
    836 
    837 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ enum mhd_TlsAlpnProt
    838 mhd_tls_multi_conn_get_alpn_prot (struct mhd_TlsMultiConnData *restrict c_tls)
    839 {
    840   switch (c_tls->choice)
    841   {
    842 #ifdef MHD_SUPPORT_GNUTLS
    843   case mhd_TLS_MULTI_ROUTE_GNU:
    844     return mhd_tls_gnu_conn_get_alpn_prot (c_tls->data.gnutls);
    845 #endif
    846 #ifdef MHD_SUPPORT_OPENSSL
    847   case mhd_TLS_MULTI_ROUTE_OPEN:
    848     return mhd_tls_open_conn_get_alpn_prot (c_tls->data.openssl);
    849 #endif
    850 #ifdef MHD_SUPPORT_MBEDTLS
    851   case mhd_TLS_MULTI_ROUTE_MBED:
    852     return mhd_tls_mbed_conn_get_alpn_prot (c_tls->data.mbedtls);
    853 #endif
    854   case mhd_TLS_MULTI_ROUTE_NONE:
    855   default:
    856     mhd_UNREACHABLE ();
    857     break;
    858   }
    859   return mhd_TLS_ALPN_PROT_NOT_SELECTED;
    860 }