From c8f4979ebf1a701e2222661556b3e735b99b3341 Mon Sep 17 00:00:00 2001 From: Mike Gorse Date: Thu, 8 Jan 2026 16:19:37 -0600 Subject: [PATCH] soup-auth-ntlm: Use unsigned ints for byte counts in md4sum Otherwise, the variables could overflow if the password is long enough, leading to an out-of-bounds memory access. This is CVE-2026-0719. Closes #477. --- libsoup/auth/soup-auth-ntlm.c | 13 ++++--- tests/ntlm-test.c | 64 +++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 5 deletions(-) diff --git a/libsoup/auth/soup-auth-ntlm.c b/libsoup/auth/soup-auth-ntlm.c index 7108a32c3..ef26ff40a 100644 --- a/libsoup/auth/soup-auth-ntlm.c +++ b/libsoup/auth/soup-auth-ntlm.c @@ -604,7 +604,7 @@ soup_auth_ntlm_class_init (SoupAuthNTLMClass *auth_ntlm_class) } static void md4sum (const unsigned char *in, - int nbytes, + size_t nbytes, unsigned char digest[16]); typedef guint32 DES_KS[16][2]; /* Single-key DES key schedule */ @@ -650,7 +650,7 @@ soup_ntlm_nt_hash (const char *password, guchar hash[21]) { unsigned char *buf, *p; - p = buf = g_malloc (strlen (password) * 2); + p = buf = g_malloc_n (strlen (password), 2); while (*password) { *p++ = *password++; @@ -1092,15 +1092,16 @@ calc_response (const guchar *key, const guchar *plaintext, guchar *results) #define ROT(val, n) ( ((val) << (n)) | ((val) >> (32 - (n))) ) static void -md4sum (const unsigned char *in, int nbytes, unsigned char digest[16]) +md4sum (const unsigned char *in, size_t nbytes, unsigned char digest[16]) { unsigned char *M; guint32 A, B, C, D, AA, BB, CC, DD, X[16]; - int pbytes, nbits = nbytes * 8, i, j; + size_t pbytes, nbits = nbytes * 8; + int i, j; /* There is *always* padding of at least one bit. */ pbytes = ((119 - (nbytes % 64)) % 64) + 1; - M = alloca (nbytes + pbytes + 8); + M = g_malloc (nbytes + pbytes + 8); memcpy (M, in, nbytes); memset (M + nbytes, 0, pbytes + 8); M[nbytes] = 0x80; @@ -1200,6 +1201,8 @@ md4sum (const unsigned char *in, int nbytes, unsigned char digest[16]) digest[13] = (D >> 8) & 0xFF; digest[14] = (D >> 16) & 0xFF; digest[15] = (D >> 24) & 0xFF; + + g_free (M); } diff --git a/tests/ntlm-test.c b/tests/ntlm-test.c index a92a21c8c..5080f8e61 100644 --- a/tests/ntlm-test.c +++ b/tests/ntlm-test.c @@ -714,6 +714,67 @@ do_retrying_test (TestServer *ts, soup_test_session_abort_unref (session); } +static gboolean +long_password_test_authenticate (SoupMessage *msg, + SoupAuth *auth, + gboolean retrying, + gpointer user) +{ + size_t l = 2147483647; + char *password; + char tmp[10000]; + size_t i; + + password = (char *)g_malloc (l); + + for (i = 0; i < 10000; i++) { + tmp[i] = 'A'; + } + for (i = 0; i < l/10000; i++) { + memcpy (password + i * 10000, tmp, 10000); + } + memcpy (password + l - 1 - 10000, tmp, 10000); + + soup_auth_authenticate (auth, "alice", password); + + g_free (password); + return TRUE; +} + +static void +do_long_password_test (TestServer *ts, + gconstpointer data) +{ + SoupSession *session; + SoupMessage *msg; + GUri *uri; + GBytes *body; + +#ifndef __SANITIZE_ADDRESS__ + g_test_skip ("Slow, allocates a large amount of memory, and needs asan"); + return; +#endif + + session = soup_test_session_new (NULL); + soup_session_add_feature_by_type (session, SOUP_TYPE_AUTH_NTLM); + soup_session_set_proxy_resolver(session, NULL); + + uri = g_uri_parse_relative (ts->uri, "/alice", SOUP_HTTP_URI_FLAGS, NULL); + msg = soup_message_new_from_uri ("GET", uri); + g_signal_connect (msg, "authenticate", + G_CALLBACK (long_password_test_authenticate), NULL); + g_uri_unref (uri); + + body = soup_session_send_and_read (session, msg, NULL, NULL); + + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + + g_bytes_unref (body); + g_object_unref (msg); + + soup_test_session_abort_unref (session); +} + int main (int argc, char **argv) { @@ -737,6 +798,9 @@ main (int argc, char **argv) g_test_add ("/ntlm/retry", TestServer, NULL, setup_server, do_retrying_test, teardown_server); + g_test_add ("/ntlm/long-password", TestServer, NULL, + setup_server, do_long_password_test, teardown_server); + ret = g_test_run (); test_cleanup (); -- GitLab