]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
GnuTLS vs. NULL chars in CNs
authorTomas Hoger <thoger@redhat.com>
Tue, 4 Aug 2009 08:39:24 +0000 (10:39 +0200)
committerSimon Josefsson <simon@josefsson.org>
Tue, 4 Aug 2009 11:14:50 +0000 (13:14 +0200)
Check cert name size in _gnutls_hostname_compare()

    This is needed to protect against NULL (\0) characters embedded in X509
    certificates' CNs or subjectAltNames, that can be used to fool SSL certificate
    verification as was demonstrated by Moxie Marlinspike on BH USA 2009:

    http://www.blackhat.com/html/bh-usa-09/bh-usa-09-archives.html#Marlinspike

Signed-off-by: Simon Josefsson <simon@josefsson.org>
lib/gnutls_str.c
lib/gnutls_str.h
lib/openpgp/pgp.c
lib/x509/rfc2818_hostname.c

index d29b642bf92fe96740c2979fd7b7b6a234083473..98c37370a1f96d6c4f089aac84d2bbd2a86159ce 100644 (file)
@@ -363,17 +363,20 @@ _gnutls_hex2bin (const opaque * hex_data, int hex_size, opaque * bin_data,
 
 /* compare hostname against certificate, taking account of wildcards
  * return 1 on success or 0 on error
+ *
+ * note: certnamesize is required as X509 certs can contain embedded NULLs in
+ * the strings such as CN or subjectAltName
  */
 int
-_gnutls_hostname_compare (const char *certname, const char *hostname)
+_gnutls_hostname_compare (const char *certname, size_t certnamesize, const char *hostname)
 {
   /* find the first different character */
   for (; *certname && *hostname && toupper (*certname) == toupper (*hostname);
-       certname++, hostname++)
+       certname++, hostname++, certnamesize--)
     ;
 
   /* the strings are the same */
-  if (strlen (certname) == 0 && strlen (hostname) == 0)
+  if (certnamesize == 0 && strlen (hostname) == 0)
     return 1;
 
   if (*certname == '*')
@@ -381,11 +384,12 @@ _gnutls_hostname_compare (const char *certname, const char *hostname)
       /* a wildcard certificate */
 
       certname++;
+      certnamesize--;
 
       while (1)
        {
          /* Use a recursive call to allow multiple wildcards */
-         if (_gnutls_hostname_compare (certname, hostname))
+         if (_gnutls_hostname_compare (certname, certnamesize, hostname))
            {
              return 1;
            }
index 1a5dec6c9e29bf1b76209a4dc8b68a1022b8abf8..8b4910e9084ee7e3f959eb572282dd322de2dbf1 100644 (file)
@@ -79,7 +79,7 @@ char *_gnutls_bin2hex (const void *old, size_t oldlen, char *buffer,
 int _gnutls_hex2bin (const opaque * hex_data, int hex_size, opaque * bin_data,
                     size_t * bin_size);
 
-int _gnutls_hostname_compare (const char *certname, const char *hostname);
+int _gnutls_hostname_compare (const char *certname, size_t certnamesize, const char *hostname);
 #define MAX_CN 256
 
 #endif
index f23b0ccda26103d03b6f695d52d5b482e305ea03..fa7c0a9efafb9c037eeab934206ea813e787851f 100644 (file)
@@ -585,7 +585,7 @@ gnutls_openpgp_crt_check_hostname (gnutls_openpgp_crt_t key,
 
       if (ret == 0)
        {
-         if (_gnutls_hostname_compare (dnsname, hostname))
+         if (_gnutls_hostname_compare (dnsname, dnsnamesize, hostname))
            return 1;
        }
     }
index 45cc90bb179268144497684eafda677080594384..f3dadb1f9c50b5ba9e69e5af70a95b99b0b5dd4e 100644 (file)
@@ -74,7 +74,7 @@ gnutls_x509_crt_check_hostname (gnutls_x509_crt_t cert, const char *hostname)
       if (ret == GNUTLS_SAN_DNSNAME)
        {
          found_dnsname = 1;
-         if (_gnutls_hostname_compare (dnsname, hostname))
+         if (_gnutls_hostname_compare (dnsname, dnsnamesize, hostname))
            {
              return 1;
            }
@@ -84,7 +84,7 @@ gnutls_x509_crt_check_hostname (gnutls_x509_crt_t cert, const char *hostname)
          found_dnsname = 1;    /* RFC 2818 is unclear whether the CN
                                   should be compared for IP addresses
                                   too, but we won't do it.  */
-         if (_gnutls_hostname_compare (dnsname, hostname))
+         if (_gnutls_hostname_compare (dnsname, dnsnamesize, hostname))
            {
              return 1;
            }
@@ -104,7 +104,7 @@ gnutls_x509_crt_check_hostname (gnutls_x509_crt_t cert, const char *hostname)
          return 0;
        }
 
-      if (_gnutls_hostname_compare (dnsname, hostname))
+      if (_gnutls_hostname_compare (dnsname, dnsnamesize, hostname))
        {
          return 1;
        }