From: Nikos Mavrogiannopoulos Date: Sun, 5 Dec 2010 09:21:55 +0000 (+0100) Subject: Corrected buffer overflow in gnutls-serv by Tomas Mraz. X-Git-Tag: gnutls_2_11_5~17 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=86ecfeed9948097dd9f34f2cefc49654521b3e69;p=thirdparty%2Fgnutls.git Corrected buffer overflow in gnutls-serv by Tomas Mraz. The gnutls-serv uses fixed allocated buffer for the response which can be pretty long if a client certificate is presented to it and the http header is large. This causes buffer overflow and heap corruption which then leads to random segfaults or aborts. It was reported originally here: https://bugzilla.redhat.com/show_bug.cgi?id=659259 The attached patch changes sprintf calls in peer_print_info() to snprintf so the buffer is never overflowed. --- diff --git a/NEWS b/NEWS index 2a78328c4e..3bdd35c5a1 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,13 @@ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. See the end for copying conditions. +* Version 2.11.6 (unreleased) + +** gnutls-serv: Corrected a buffer overflow. Reported and patch by Tomas Mraz. + +** API and ABI modifications: +No changes since last version. + * Version 2.11.5 (released 2010-12-01) ** libgnutls: Reverted default behavior for verification and diff --git a/src/serv.c b/src/serv.c index d7782b90b2..1d45c96221 100644 --- a/src/serv.c +++ b/src/serv.c @@ -409,7 +409,7 @@ static const char DEFAULT_DATA[] = /* Creates html with the current session information. */ -#define tmp2 &http_buffer[strlen(http_buffer)] +#define tmp2 &http_buffer[strlen(http_buffer)], len-strlen(http_buffer) static char * peer_print_info (gnutls_session_t session, int *ret_length, const char *header) @@ -419,7 +419,7 @@ peer_print_info (gnutls_session_t session, int *ret_length, size_t i, sesid_size; char *http_buffer; gnutls_kx_algorithm_t kx_alg; - size_t len = 5 * 1024 + strlen (header); + size_t len = 20 * 1024 + strlen (header); char *crtinfo = NULL; size_t ncrtinfo = 0; @@ -483,11 +483,11 @@ peer_print_info (gnutls_session_t session, int *ret_length, /* print session_id */ gnutls_session_get_id (session, sesid, &sesid_size); - sprintf (tmp2, "\n

Session ID: "); + snprintf (tmp2, "\n

Session ID: "); for (i = 0; i < sesid_size; i++) - sprintf (tmp2, "%.2X", sesid[i]); - sprintf (tmp2, "

\n"); - sprintf (tmp2, + snprintf (tmp2, "%.2X", sesid[i]); + snprintf (tmp2, "

\n"); + snprintf (tmp2, "
If your browser supports session resuming, then you should see the " "same session ID, when you press the reload button.
\n"); @@ -501,7 +501,7 @@ peer_print_info (gnutls_session_t session, int *ret_length, if (gnutls_server_name_get (session, dns, &dns_size, &type, 0) == 0) { - sprintf (tmp2, "\n

Server Name: %s

\n", dns); + snprintf (tmp2, "\n

Server Name: %s

\n", dns); } } @@ -512,7 +512,7 @@ peer_print_info (gnutls_session_t session, int *ret_length, #ifdef ENABLE_SRP if (kx_alg == GNUTLS_KX_SRP) { - sprintf (tmp2, "

Connected as user '%s'.

\n", + snprintf (tmp2, "

Connected as user '%s'.

\n", gnutls_srp_server_get_username (session)); } #endif @@ -520,7 +520,7 @@ peer_print_info (gnutls_session_t session, int *ret_length, #ifdef ENABLE_PSK if (kx_alg == GNUTLS_KX_PSK) { - sprintf (tmp2, "

Connected as user '%s'.

\n", + snprintf (tmp2, "

Connected as user '%s'.

\n", gnutls_psk_server_get_username (session)); } #endif @@ -528,7 +528,7 @@ peer_print_info (gnutls_session_t session, int *ret_length, #ifdef ENABLE_ANON if (kx_alg == GNUTLS_KX_ANON_DH) { - sprintf (tmp2, + snprintf (tmp2, "

Connect using anonymous DH (prime of %d bits)

\n", gnutls_dh_get_prime_bits (session)); } @@ -536,7 +536,7 @@ peer_print_info (gnutls_session_t session, int *ret_length, if (kx_alg == GNUTLS_KX_DHE_RSA || kx_alg == GNUTLS_KX_DHE_DSS) { - sprintf (tmp2, + snprintf (tmp2, "Ephemeral DH using prime of %d bits.
\n", gnutls_dh_get_prime_bits (session)); } @@ -547,7 +547,7 @@ peer_print_info (gnutls_session_t session, int *ret_length, tmp = gnutls_protocol_get_name (gnutls_protocol_get_version (session)); if (tmp == NULL) tmp = str_unknown; - sprintf (tmp2, + snprintf (tmp2, "\n", tmp); @@ -558,50 +558,44 @@ peer_print_info (gnutls_session_t session, int *ret_length, (session)); if (tmp == NULL) tmp = str_unknown; - sprintf (tmp2, "\n", tmp); + snprintf (tmp2, "\n", tmp); } tmp = gnutls_kx_get_name (kx_alg); if (tmp == NULL) tmp = str_unknown; - sprintf (tmp2, "\n", tmp); + snprintf (tmp2, "\n", tmp); tmp = gnutls_compression_get_name (gnutls_compression_get (session)); if (tmp == NULL) tmp = str_unknown; - sprintf (tmp2, "\n", tmp); + snprintf (tmp2, "\n", tmp); tmp = gnutls_cipher_get_name (gnutls_cipher_get (session)); if (tmp == NULL) tmp = str_unknown; - sprintf (tmp2, "\n", tmp); + snprintf (tmp2, "\n", tmp); tmp = gnutls_mac_get_name (gnutls_mac_get (session)); if (tmp == NULL) tmp = str_unknown; - sprintf (tmp2, "\n", tmp); + snprintf (tmp2, "\n", tmp); tmp = gnutls_cipher_suite_get_name (kx_alg, gnutls_cipher_get (session), gnutls_mac_get (session)); if (tmp == NULL) tmp = str_unknown; - sprintf (tmp2, "

Protocol version:%s
Certificate Type:%s
Certificate Type:%s
Key Exchange:%s
Key Exchange:%s
Compression%s
Compression%s
Cipher%s
Cipher%s
MAC%s
MAC%s
Ciphersuite%s
\n", + snprintf (tmp2, "Ciphersuite%s

\n", tmp); if (crtinfo) { - strcat (http_buffer, "
");
-      strcat (http_buffer, crtinfo);
-      strcat (http_buffer, "\n
\n"); + snprintf(tmp2, "
%s\n
\n", crtinfo); free (crtinfo); } - strcat (http_buffer, "

Your HTTP header was:

");
-  strcat (http_buffer, header);
-  strcat (http_buffer, "

"); - - strcat (http_buffer, "\n" HTTP_END); + snprintf(tmp2, "

Your HTTP header was:

%s

\n" HTTP_END, header); *ret_length = strlen (http_buffer);