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:
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);
}