]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Corrected buffer overflow in gnutls-serv by Tomas Mraz.
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Sun, 5 Dec 2010 09:21:55 +0000 (10:21 +0100)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Sun, 5 Dec 2010 09:21:55 +0000 (10:21 +0100)
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.

NEWS
src/serv.c

diff --git a/NEWS b/NEWS
index 2a78328c4e030d3f9b8c50b5b61044b605f7691a..3bdd35c5a19813bf1c239ca961076e4ec59743d4 100644 (file)
--- 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
index d7782b90b25a1d0023f91edb8060e11099431ec4..1d45c9622182b8333b245b58c45155c49d9b76a9 100644 (file)
@@ -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<p>Session ID: <i>");
+  snprintf (tmp2, "\n<p>Session ID: <i>");
   for (i = 0; i < sesid_size; i++)
-    sprintf (tmp2, "%.2X", sesid[i]);
-  sprintf (tmp2, "</i></p>\n");
-  sprintf (tmp2,
+    snprintf (tmp2, "%.2X", sesid[i]);
+  snprintf (tmp2, "</i></p>\n");
+  snprintf (tmp2,
           "<h5>If your browser supports session resuming, then you should see the "
           "same session ID, when you press the <b>reload</b> button.</h5>\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<p>Server Name: %s</p>\n", dns);
+       snprintf (tmp2, "\n<p>Server Name: %s</p>\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, "<p>Connected as user '%s'.</p>\n",
+      snprintf (tmp2, "<p>Connected as user '%s'.</p>\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, "<p>Connected as user '%s'.</p>\n",
+      snprintf (tmp2, "<p>Connected as user '%s'.</p>\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,
               "<p> Connect using anonymous DH (prime of %d bits)</p>\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 <b>%d</b> bits.<br>\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,
           "<TABLE border=1><TR><TD>Protocol version:</TD><TD>%s</TD></TR>\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, "<TR><TD>Certificate Type:</TD><TD>%s</TD></TR>\n", tmp);
+      snprintf (tmp2, "<TR><TD>Certificate Type:</TD><TD>%s</TD></TR>\n", tmp);
     }
 
   tmp = gnutls_kx_get_name (kx_alg);
   if (tmp == NULL)
     tmp = str_unknown;
-  sprintf (tmp2, "<TR><TD>Key Exchange:</TD><TD>%s</TD></TR>\n", tmp);
+  snprintf (tmp2, "<TR><TD>Key Exchange:</TD><TD>%s</TD></TR>\n", tmp);
 
   tmp = gnutls_compression_get_name (gnutls_compression_get (session));
   if (tmp == NULL)
     tmp = str_unknown;
-  sprintf (tmp2, "<TR><TD>Compression</TD><TD>%s</TD></TR>\n", tmp);
+  snprintf (tmp2, "<TR><TD>Compression</TD><TD>%s</TD></TR>\n", tmp);
 
   tmp = gnutls_cipher_get_name (gnutls_cipher_get (session));
   if (tmp == NULL)
     tmp = str_unknown;
-  sprintf (tmp2, "<TR><TD>Cipher</TD><TD>%s</TD></TR>\n", tmp);
+  snprintf (tmp2, "<TR><TD>Cipher</TD><TD>%s</TD></TR>\n", tmp);
 
   tmp = gnutls_mac_get_name (gnutls_mac_get (session));
   if (tmp == NULL)
     tmp = str_unknown;
-  sprintf (tmp2, "<TR><TD>MAC</TD><TD>%s</TD></TR>\n", tmp);
+  snprintf (tmp2, "<TR><TD>MAC</TD><TD>%s</TD></TR>\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, "<TR><TD>Ciphersuite</TD><TD>%s</TD></TR></p></TABLE>\n",
+  snprintf (tmp2, "<TR><TD>Ciphersuite</TD><TD>%s</TD></TR></p></TABLE>\n",
           tmp);
 
   if (crtinfo)
     {
-      strcat (http_buffer, "<hr><PRE>");
-      strcat (http_buffer, crtinfo);
-      strcat (http_buffer, "\n</PRE>\n");
+      snprintf(tmp2, "<hr><PRE>%s\n</PRE>\n", crtinfo);
       free (crtinfo);
     }
 
-  strcat (http_buffer, "<hr><P>Your HTTP header was:<PRE>");
-  strcat (http_buffer, header);
-  strcat (http_buffer, "</PRE></P>");
-
-  strcat (http_buffer, "\n" HTTP_END);
+  snprintf(tmp2, "<hr><P>Your HTTP header was:<PRE>%s</PRE></P>\n" HTTP_END, header);
 
   *ret_length = strlen (http_buffer);