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, "\nSession 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, "\nServer Name: %s
\n", dns);
+ snprintf (tmp2, "\nServer 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,
"| Protocol version: | %s |
\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, "| Certificate Type: | %s |
\n", tmp);
+ snprintf (tmp2, "| Certificate Type: | %s |
\n", tmp);
}
tmp = gnutls_kx_get_name (kx_alg);
if (tmp == NULL)
tmp = str_unknown;
- sprintf (tmp2, "| Key Exchange: | %s |
\n", tmp);
+ snprintf (tmp2, "| Key Exchange: | %s |
\n", tmp);
tmp = gnutls_compression_get_name (gnutls_compression_get (session));
if (tmp == NULL)
tmp = str_unknown;
- sprintf (tmp2, "| Compression | %s |
\n", tmp);
+ snprintf (tmp2, "| Compression | %s |
\n", tmp);
tmp = gnutls_cipher_get_name (gnutls_cipher_get (session));
if (tmp == NULL)
tmp = str_unknown;
- sprintf (tmp2, "| Cipher | %s |
\n", tmp);
+ snprintf (tmp2, "| Cipher | %s |
\n", tmp);
tmp = gnutls_mac_get_name (gnutls_mac_get (session));
if (tmp == NULL)
tmp = str_unknown;
- sprintf (tmp2, "| MAC | %s |
\n", tmp);
+ snprintf (tmp2, "| MAC | %s |
\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, "| 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);