libmicrohttpd2

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

commit f6be94488bc2abba9790d26ceab6a8555f7147e6
parent 0b1474f85b01b99dede7881c71a89c6748b0fd61
Author: Evgeny Grin (Karlson2k) <k2k@drgrin.dev>
Date:   Mon,  1 Dec 2025 18:15:25 +0100

TLS: unified ALPN ids decoding

Diffstat:
Msrc/mhd2/Makefile.am | 1+
Asrc/mhd2/mhd_tls_internal.c | 90+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/mhd2/mhd_tls_internal.h | 116+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/mhd2/tls_gnu_funcs.c | 38++++++++++----------------------------
Msrc/mhd2/tls_open_funcs.c | 28+++++-----------------------
5 files changed, 222 insertions(+), 51 deletions(-)

diff --git a/src/mhd2/Makefile.am b/src/mhd2/Makefile.am @@ -245,6 +245,7 @@ upgrade_OPTSOURCES = \ tls_common_OPTSOURCES = \ mhd_tls_enums.h mhd_tls_ver_stct.h tls_dh_params.h \ + mhd_tls_internal.c mhd_tls_internal.h \ mhd_tls_common.c mhd_tls_common.h \ mhd_tls_choice.h mhd_tls_funcs.h \ conn_tls_check.c conn_tls_check.h diff --git a/src/mhd2/mhd_tls_internal.c b/src/mhd2/mhd_tls_internal.c @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */ +/* + This file is part of GNU libmicrohttpd. + Copyright (C) 2024-2025 Evgeny Grin (Karlson2k) + + GNU libmicrohttpd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + GNU libmicrohttpd is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + Alternatively, you can redistribute GNU libmicrohttpd and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version, together + with the eCos exception, as follows: + + As a special exception, if other files instantiate templates or + use macros or inline functions from this file, or you compile this + file and link it with other works to produce a work based on this + file, this file does not by itself cause the resulting work to be + covered by the GNU General Public License. However the source code + for this file must still be made available in accordance with + section (3) of the GNU General Public License v2. + + This exception does not invalidate any other reasons why a work + based on this file might be covered by the GNU General Public + License. + + You should have received copies of the GNU Lesser General Public + License and the GNU General Public License along with this library; + if not, see <https://www.gnu.org/licenses/>. +*/ + +/** + * @file src/mhd2/mhd_tls_internal.c + * @brief The TLS handling internal functions + * @author Karlson2k (Evgeny Grin) + */ + +#include "mhd_sys_options.h" + +#include "sys_null_macro.h" +#include "sys_sizet_type.h" + +#include <string.h> + +#include "mhd_assert.h" +#include "mhd_unreachable.h" + +#include "mhd_tls_internal.h" + +MHD_INTERNAL +MHD_FN_PAR_IN_SIZE_ (2, 1) enum mhd_TlsAlpnProt +mhd_tls_alpn_decode_n (size_t alnp_id_size, + const unsigned char *alnp_id) +{ + mhd_assert ((NULL != alnp_id) || (0u == alnp_id_size)); + + if (NULL == alnp_id) + return mhd_TLS_ALPN_PROT_NOT_SELECTED; + +#ifdef MHD_SUPPORT_HTTP2 + if ((alnp_id_size == mhd_ALPN_H2_LEN) && + (0 == memcmp (alnp_id, + mhd_ALPN_H2, + mhd_ALPN_H2_LEN))) + return mhd_TLS_ALPN_PROT_HTTP2; +#endif /* MHD_SUPPORT_HTTP2 */ + + if ((alnp_id_size == mhd_ALPN_H1_1_LEN) && + (0 == memcmp (alnp_id, + mhd_ALPN_H1_1, + mhd_ALPN_H1_1_LEN))) + return mhd_TLS_ALPN_PROT_HTTP1_1; + + if ((alnp_id_size == mhd_ALPN_H1_0_LEN) && + (0 == memcmp (alnp_id, + mhd_ALPN_H1_0, + mhd_ALPN_H1_0_LEN))) + return mhd_TLS_ALPN_PROT_HTTP1_0; + + mhd_UNREACHABLE_D ("ALPN can negotiate only one of the provided values"); + + return mhd_TLS_ALPN_PROT_ERROR; +} diff --git a/src/mhd2/mhd_tls_internal.h b/src/mhd2/mhd_tls_internal.h @@ -0,0 +1,116 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */ +/* + This file is part of GNU libmicrohttpd. + Copyright (C) 2024-2025 Evgeny Grin (Karlson2k) + + GNU libmicrohttpd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + GNU libmicrohttpd is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + Alternatively, you can redistribute GNU libmicrohttpd and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version, together + with the eCos exception, as follows: + + As a special exception, if other files instantiate templates or + use macros or inline functions from this file, or you compile this + file and link it with other works to produce a work based on this + file, this file does not by itself cause the resulting work to be + covered by the GNU General Public License. However the source code + for this file must still be made available in accordance with + section (3) of the GNU General Public License v2. + + This exception does not invalidate any other reasons why a work + based on this file might be covered by the GNU General Public + License. + + You should have received copies of the GNU Lesser General Public + License and the GNU General Public License along with this library; + if not, see <https://www.gnu.org/licenses/>. +*/ + +/** + * @file src/mhd2/mhd_tls_internal.h + * @brief The TLS handling internal functions and data + * @author Karlson2k (Evgeny Grin) + */ + +#ifndef MHD_TLS_INTERNAL_H +#define MHD_TLS_INTERNAL_H 1 + +#include "mhd_sys_options.h" + +#ifndef MHD_SUPPORT_HTTPS +#error This header should be used only if HTTPS is enabled +#endif + +#include "sys_sizet_type.h" + +#include "mhd_str_macros.h" + +#include "mhd_tls_enums.h" + +/** + * Registered ALPN value for HTTP/1.0 + */ +#define mhd_ALPN_H1_0 "http/1.0" + +/** + * Registered ALPN value for HTTP/1.1 + */ +#define mhd_ALPN_H1_1 "http/1.1" + +/** + * Registered ALPN value for HTTP/2 + */ +#define mhd_ALPN_H2 "h2" + +/** + * Registered ALPN value for HTTP/3 + */ +#define mhd_ALPN_H3 "h3" + +/** + * The length of #mhd_ALPN_H1_0 + */ +#define mhd_ALPN_H1_0_LEN mhd_SSTR_LEN (mhd_ALPN_H1_0) + +/** + * The length of #mhd_ALPN_H1_1 + */ +#define mhd_ALPN_H1_1_LEN mhd_SSTR_LEN (mhd_ALPN_H1_1) + +/** + * The length of #mhd_ALPN_H2_1 + */ +#define mhd_ALPN_H2_LEN mhd_SSTR_LEN (mhd_ALPN_H2) + +/** + * The length of #mhd_ALPN_H2_1 + */ +#define mhd_ALPN_H3_LEN mhd_SSTR_LEN (mhd_ALPN_H3) + +/** + * Decode provided ALPN identifier + * @param alnp_id_size the size in bytes of the @a alpn_str + * @param alnp_id the ALPN identifier, does not need to be zero-terminated, + * could be NULL + * @return the decoded protocol, + * #mhd_TLS_ALPN_PROT_NOT_SELECTED if @a alnp_str is NULL, + * #mhd_TLS_ALPN_PROT_ERROR if @a alnp_str does not match any known + * string identifier, + */ +MHD_INTERNAL enum mhd_TlsAlpnProt +mhd_tls_alpn_decode_n (size_t alnp_id_size, + const unsigned char *alnp_id) +MHD_FN_PAR_IN_SIZE_ (2, 1); + + +#endif /* ! MHD_TLS_INTERNAL_H */ diff --git a/src/mhd2/tls_gnu_funcs.c b/src/mhd2/tls_gnu_funcs.c @@ -65,6 +65,8 @@ #include "mhd_conn_socket.h" +#include "mhd_tls_internal.h" + #include "tls_gnu_tls_lib.h" #include "mhd_tls_ver_stct.h" @@ -96,13 +98,13 @@ mhd_tls_gnu_debug_print (int level, const char *msg) #endif /* mhd_USE_TLS_DEBUG_MESSAGES */ #ifdef mhd_TLS_GNU_HAS_ALPN -static const char mhd_alpn_str_http1_0[] = "http/1.0"; /* Registered value for HTTP/1.0 */ -static const char mhd_alpn_str_http1_1[] = "http/1.1"; /* Registered value for HTTP/1.1 */ +static const char mhd_alpn_str_http1_0[] = mhd_ALPN_H1_0; +static const char mhd_alpn_str_http1_1[] = mhd_ALPN_H1_1; # ifdef MHD_SUPPORT_HTTP2 -static const char mhd_alpn_str_http2[] = "h2"; /* Registered value for HTTP/2 over TLS */ +static const char mhd_alpn_str_http2[] = mhd_ALPN_H2; # endif # if 0 /* Disabled code */ -static const char alpn_http_3[] = "h3"; /* Registered value for HTTP/3 */ +static const char alpn_http_3[] = mhd_ALPN_H3; # endif static const gnutls_datum_t mhd_alpn_dat_http1_0 = { (unsigned char *) mhd_DROP_CONST (mhd_alpn_str_http1_0), @@ -877,7 +879,7 @@ mhd_tls_gnu_conn_get_tls_ver (struct mhd_TlsGnuConnData *restrict c_tls, else if (GNUTLS_VERSION_UNKNOWN == gtls_tls_ver) return false; /* The TLS version cannot be detected */ else - /* The TLS version is know for GnuTLS, but cannot be mapped */ + /* The TLS version is known for GnuTLS, but cannot be mapped */ tls_ver_out->tls_ver = MHD_TLS_VERSION_UNKNOWN; return true; @@ -890,30 +892,10 @@ mhd_tls_gnu_conn_get_alpn_prot (struct mhd_TlsGnuConnData *restrict c_tls) #ifdef mhd_TLS_GNU_HAS_ALPN gnutls_datum_t sel_prot; - if (GNUTLS_E_SUCCESS != + if (GNUTLS_E_SUCCESS == gnutls_alpn_get_selected_protocol (c_tls->sess, &sel_prot)) - return mhd_TLS_ALPN_PROT_NOT_SELECTED; - -# ifdef MHD_SUPPORT_HTTP2 - if ((sel_prot.size == mhd_alpn_dat_http2.size) - && (0 == memcmp (sel_prot.data, - mhd_alpn_dat_http2.data, - sel_prot.size))) - return mhd_TLS_ALPN_PROT_HTTP2; -# endif /* MHD_SUPPORT_HTTP2 */ - - if ((sel_prot.size == mhd_alpn_dat_http1_1.size) - && (0 == memcmp (sel_prot.data, - mhd_alpn_dat_http1_1.data, - sel_prot.size))) - return mhd_TLS_ALPN_PROT_HTTP1_1; - - if ((sel_prot.size == mhd_alpn_dat_http1_0.size) - && (0 == memcmp (sel_prot.data, - mhd_alpn_dat_http1_0.data, - sel_prot.size))) - return mhd_TLS_ALPN_PROT_HTTP1_0; - + return mhd_tls_alpn_decode_n (sel_prot.size, + sel_prot.data); #endif /* mhd_TLS_GNU_HAS_ALPN */ return mhd_TLS_ALPN_PROT_NOT_SELECTED; diff --git a/src/mhd2/tls_open_funcs.c b/src/mhd2/tls_open_funcs.c @@ -60,6 +60,8 @@ #include "mhd_conn_socket.h" +#include "mhd_tls_internal.h" + #include "tls_open_tls_lib.h" #include "mhd_tls_ver_stct.h" @@ -1344,28 +1346,8 @@ mhd_tls_open_conn_get_alpn_prot (struct mhd_TlsOpenConnData *restrict c_tls) } #endif /* ! OPENSSL_NO_NEXTPROTONEG */ - if (NULL == sel_prot) - return mhd_TLS_ALPN_PROT_NOT_SELECTED; - -#ifdef MHD_SUPPORT_HTTP2 - if ((sel_prot_len == sizeof(alpn_code_http2)) - && (0 == memcmp (sel_prot, - alpn_code_http2, - sel_prot_len))) - return mhd_TLS_ALPN_PROT_HTTP2; -#endif /* MHD_SUPPORT_HTTP2 */ - - if ((sel_prot_len == sizeof(alpn_code_http1_1)) - && (0 == memcmp (sel_prot, - alpn_code_http1_1, - sel_prot_len))) - return mhd_TLS_ALPN_PROT_HTTP1_1; - - if ((sel_prot_len == sizeof(alpn_code_http1_0)) - && (0 == memcmp (sel_prot, - alpn_code_http1_0, - sel_prot_len))) - return mhd_TLS_ALPN_PROT_HTTP1_0; + mhd_assert (sel_prot_len == (size_t) sel_prot_len); - return mhd_TLS_ALPN_PROT_NOT_SELECTED; + return mhd_tls_alpn_decode_n ((size_t) sel_prot_len, + sel_prot); }