summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2011-05-05 22:31:05 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2011-05-05 22:31:44 +0200
commit05d654f81bbab1dfd9b75a4375804cceb1808873 (patch)
treecc0d3a4f63d1a56ee8cbcd15f6e607bef5cc6c0d
parent12c03890ea08be56536c1c8ea70b19d8a8137564 (diff)
downloadgnutls-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--THANKS1
-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.c4
5 files changed, 14 insertions, 7 deletions
diff --git a/THANKS b/THANKS
index 14eaca317f..ef6cb28de0 100644
--- a/THANKS
+++ b/THANKS
@@ -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;
}