summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomas Hoger <thoger@redhat.com>2009-08-04 10:39:24 +0200
committerSimon Josefsson <simon@josefsson.org>2009-08-07 01:02:26 +0200
commit59780bd1fff8cc4e6f5725127b6fe9c17f499a1c (patch)
tree48e22ec46535c699eb849ed08556e2d633e85688
parent8df937cada22cbb1a5b6e32614e8ab155cdc1bee (diff)
downloadgnutls-59780bd1fff8cc4e6f5725127b6fe9c17f499a1c.tar.gz
GnuTLS vs. NULL chars in CNs
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>
-rw-r--r--lib/gnutls_str.c12
-rw-r--r--lib/gnutls_str.h2
-rw-r--r--lib/openpgp/pgp.c2
-rw-r--r--lib/x509/rfc2818_hostname.c6
4 files changed, 13 insertions, 9 deletions
diff --git a/lib/gnutls_str.c b/lib/gnutls_str.c
index f1bc46e001..0dc5b5a5e2 100644
--- a/lib/gnutls_str.c
+++ b/lib/gnutls_str.c
@@ -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;
}
diff --git a/lib/gnutls_str.h b/lib/gnutls_str.h
index 1a5dec6c9e..8b4910e908 100644
--- a/lib/gnutls_str.h
+++ b/lib/gnutls_str.h
@@ -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
diff --git a/lib/openpgp/pgp.c b/lib/openpgp/pgp.c
index f23b0ccda2..fa7c0a9efa 100644
--- a/lib/openpgp/pgp.c
+++ b/lib/openpgp/pgp.c
@@ -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;
}
}
diff --git a/lib/x509/rfc2818_hostname.c b/lib/x509/rfc2818_hostname.c
index 45cc90bb17..f3dadb1f9c 100644
--- a/lib/x509/rfc2818_hostname.c
+++ b/lib/x509/rfc2818_hostname.c
@@ -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;
}