From: Nikos Mavrogiannopoulos Date: Thu, 5 May 2011 20:31:05 +0000 (+0200) Subject: _gnutls_hostname_compare() was incredibly slow when over ten wildcards were present... X-Git-Tag: gnutls_2_99_2~98 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=05d654f81bbab1dfd9b75a4375804cceb1808873;p=thirdparty%2Fgnutls.git _gnutls_hostname_compare() was incredibly slow when over ten wildcards were present. Set a limit on 6 wildcards to avoid any denial of service attack. Reported by Kalle Olavi Niemitalo. --- diff --git a/THANKS b/THANKS index 14eaca317f..ef6cb28de0 100644 --- a/THANKS +++ b/THANKS @@ -112,6 +112,7 @@ Micah Anderson Michael Rommel Mark Brand Vitaly Kruglikov +Kalle Olavi Niemitalo ---------------------------------------------------------------------- Copying and distribution of this file, with or without modification, diff --git a/lib/gnutls_str.c b/lib/gnutls_str.c index eec1ed1def..f599f9ab6e 100644 --- a/lib/gnutls_str.c +++ b/lib/gnutls_str.c @@ -530,12 +530,18 @@ _gnutls_hex2bin (const opaque * hex_data, int hex_size, opaque * bin_data, * return 1 on success or 0 on error * * note: certnamesize is required as X509 certs can contain embedded NULs in - * the strings such as CN or subjectAltName + * the strings such as CN or subjectAltName. + * + * @level: is used for recursion. Use 0 when you call this function. */ int _gnutls_hostname_compare (const char *certname, - size_t certnamesize, const char *hostname) + size_t certnamesize, const char *hostname, int level) { + + if (level > 5) + return 0; + /* find the first different character */ for (; *certname && *hostname && c_toupper (*certname) == c_toupper (*hostname); certname++, hostname++, certnamesize--) @@ -555,7 +561,7 @@ _gnutls_hostname_compare (const char *certname, while (1) { /* Use a recursive call to allow multiple wildcards */ - if (_gnutls_hostname_compare (certname, certnamesize, hostname)) + if (_gnutls_hostname_compare (certname, certnamesize, hostname, level+1)) return 1; /* wildcards are only allowed to match a single domain diff --git a/lib/gnutls_str.h b/lib/gnutls_str.h index 39d9047eb1..92179559e3 100644 --- a/lib/gnutls_str.h +++ b/lib/gnutls_str.h @@ -95,7 +95,7 @@ int _gnutls_hex2bin (const opaque * hex_data, int hex_size, opaque * bin_data, size_t * bin_size); int _gnutls_hostname_compare (const char *certname, size_t certnamesize, - const char *hostname); + const char *hostname, int level); #define MAX_CN 256 #define BUFFER_APPEND(b, x, s) { \ diff --git a/lib/openpgp/pgp.c b/lib/openpgp/pgp.c index e3c24c7a7b..9630448bed 100644 --- a/lib/openpgp/pgp.c +++ b/lib/openpgp/pgp.c @@ -595,7 +595,7 @@ gnutls_openpgp_crt_check_hostname (gnutls_openpgp_crt_t key, the terminating zero. */ dnsnamesize--; - if (_gnutls_hostname_compare (dnsname, dnsnamesize, hostname)) + if (_gnutls_hostname_compare (dnsname, dnsnamesize, hostname, 0)) return 1; } } diff --git a/lib/x509/rfc2818_hostname.c b/lib/x509/rfc2818_hostname.c index 46606fd494..092f9f570d 100644 --- a/lib/x509/rfc2818_hostname.c +++ b/lib/x509/rfc2818_hostname.c @@ -75,7 +75,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, dnsnamesize, hostname)) + if (_gnutls_hostname_compare (dnsname, dnsnamesize, hostname, 0)) { return 1; } @@ -95,7 +95,7 @@ gnutls_x509_crt_check_hostname (gnutls_x509_crt_t cert, const char *hostname) return 0; } - if (_gnutls_hostname_compare (dnsname, dnsnamesize, hostname)) + if (_gnutls_hostname_compare (dnsname, dnsnamesize, hostname, 0)) { return 1; }