use MHD_check_response_header_s_token_ci() as it was designed, avoid crash on add_connection followed immediately by daemon destruction; enforce minimum psk length

This commit is contained in:
Christian Grothoff
2026-07-29 17:13:37 +02:00
parent 669daf7a46
commit 70f1ba0b22
3 changed files with 44 additions and 10 deletions
+3 -1
View File
@@ -1583,7 +1583,9 @@ typedef void
* @param username the user name claimed by the other side
* @param[out] psk to be set to the pre-shared-key; should be allocated with malloc(),
* will be freed by MHD
* @param[out] psk_size to be set to the number of bytes in @a psk
* @param[out] psk_size to be set to the number of bytes in @a psk;
* must be at least 16 (RFC 4279 section 7.1), otherwise
* MHD discards the key and fails the authentication
* @return 0 on success, -1 on errors
*/
typedef int
+9 -6
View File
@@ -8293,7 +8293,6 @@ MHD_queue_response (struct MHD_Connection *connection,
#ifdef UPGRADE_SUPPORT
if (NULL != response->upgrade_handler)
{
struct MHD_HTTP_Res_Header *conn_header;
if (0 == (daemon->options & MHD_ALLOW_UPGRADE))
{
#ifdef HAVE_MESSAGES
@@ -8321,12 +8320,16 @@ MHD_queue_response (struct MHD_Connection *connection,
#endif
return MHD_NO;
}
conn_header = response->first_header;
mhd_assert (NULL != conn_header);
mhd_assert (MHD_str_equal_caseless_ (conn_header->header,
/* MHD_add_response_header() keeps the "Connection" header first, so
response->first_header could be read directly here; look it up by
name instead, so that this does not silently break if that ever
stops being true. */
mhd_assert (NULL != response->first_header);
mhd_assert (MHD_str_equal_caseless_ (response->first_header->header,
MHD_HTTP_HEADER_CONNECTION));
if (! MHD_str_has_s_token_caseless_ (conn_header->value,
"upgrade"))
if (! MHD_check_response_header_s_token_ci (response,
MHD_HTTP_HEADER_CONNECTION,
"upgrade"))
{
#ifdef HAVE_MESSAGES
MHD_DLOG (daemon,
+32 -3
View File
@@ -2483,6 +2483,16 @@ MHD_tls_push_func_ (gnutls_transport_ptr_t trnsp,
#endif /* MHD_TLSLIB_DONT_SUPPRESS_SIGPIPE */
/**
* The shortest pre-shared key #MHD_OPTION_GNUTLS_PSK_CRED_HANDLER may
* hand back, in bytes. RFC 4279 section 7.1 requires at least 16 bytes
* of entropy in a PSK and recommends the length of the hash of the
* negotiated cipher suite; anything shorter is brute-forceable offline
* from a single recorded handshake, so MHD refuses it rather than let
* the application weaken the connection by accident.
*/
#define MHD_PSK_MIN_SIZE 16
/**
* Function called by GNUtls to obtain the PSK for a given session.
*
@@ -2528,6 +2538,15 @@ psk_gnutls_adapter (gnutls_session_t session,
&app_psk,
&app_psk_size))
return -1;
if (MHD_PSK_MIN_SIZE > app_psk_size)
{
#ifdef HAVE_MESSAGES
MHD_DLOG (daemon,
_ ("PSK authentication failed: PSK too short.\n"));
#endif
free (app_psk);
return -1;
}
if (UINT_MAX < app_psk_size)
{
#ifdef HAVE_MESSAGES
@@ -2537,6 +2556,9 @@ psk_gnutls_adapter (gnutls_session_t session,
free (app_psk);
return -1;
}
/* @a app_psk_size is at least MHD_PSK_MIN_SIZE here, so this is never
gnutls_malloc(0) -- whose result is implementation defined and would
be reported below as an allocation failure. */
if (NULL == (key->data = gnutls_malloc (app_psk_size)))
{
#ifdef HAVE_MESSAGES
@@ -9193,12 +9215,19 @@ close_all_connections (struct MHD_Daemon *daemon)
mhd_assert (daemon->shutdown);
#ifdef MHD_USE_THREADS
/* Remove externally added new connections that are
* not processed by the daemon thread. */
/* Remove new connections that MHD_add_connection() queued and that were
* never processed. This is not limited to daemons with an internal
* polling thread: internal_add_connection() queues whenever the daemon
* is thread-safe, which is every daemon that was not started with
* MHD_USE_NO_THREAD_SAFETY, and new_connections_list_process_()
* asserts the same condition. An application driving an external
* event loop can therefore call MHD_add_connection() and then
* MHD_stop_daemon() before the next MHD_run(), and this list is what
* holds the connection at that point. */
MHD_mutex_lock_chk_ (&daemon->new_connections_mutex);
while (NULL != (pos = daemon->new_connections_tail))
{
mhd_assert (MHD_D_IS_USING_THREADS_ (daemon));
mhd_assert (MHD_D_IS_THREAD_SAFE_ (daemon));
DLL_remove (daemon->new_connections_head,
daemon->new_connections_tail,
pos);