diff options
author | Tomas Hoger <thoger@redhat.com> | 2009-08-04 10:39:24 +0200 |
---|---|---|
committer | Simon Josefsson <simon@josefsson.org> | 2009-08-07 01:02:26 +0200 |
commit | 59780bd1fff8cc4e6f5725127b6fe9c17f499a1c (patch) | |
tree | 48e22ec46535c699eb849ed08556e2d633e85688 | |
parent | 8df937cada22cbb1a5b6e32614e8ab155cdc1bee (diff) | |
download | gnutls-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.c | 12 | ||||
-rw-r--r-- | lib/gnutls_str.h | 2 | ||||
-rw-r--r-- | lib/openpgp/pgp.c | 2 | ||||
-rw-r--r-- | lib/x509/rfc2818_hostname.c | 6 |
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; } |