diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2011-05-05 22:31:05 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2011-05-05 22:31:44 +0200 |
commit | 05d654f81bbab1dfd9b75a4375804cceb1808873 (patch) | |
tree | cc0d3a4f63d1a56ee8cbcd15f6e607bef5cc6c0d | |
parent | 12c03890ea08be56536c1c8ea70b19d8a8137564 (diff) | |
download | gnutls-05d654f81bbab1dfd9b75a4375804cceb1808873.tar.gz |
_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.
-rw-r--r-- | THANKS | 1 | ||||
-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 | 4 |
5 files changed, 14 insertions, 7 deletions
@@ -112,6 +112,7 @@ Micah Anderson <micah [at] riseup.net> Michael Rommel <rommel [at] layer-7.net> Mark Brand <mabrand [at] mabrand.nl> Vitaly Kruglikov <vitaly.kruglikov [at] palm.com> +Kalle Olavi Niemitalo <kon [at] iki.fi> ---------------------------------------------------------------------- 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; } |