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:34:49 +0200
commitd3dada39f12351abc04f22743fa9c892dcf06276 (patch)
tree6751247287f4b6e51d74345032dcd47321a1e98e
parent777aa2927b7d9238e505fd2cfc0e616cce60f9e8 (diff)
downloadgnutls-d3dada39f12351abc04f22743fa9c892dcf06276.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--NEWS3
-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
6 files changed, 17 insertions, 7 deletions
diff --git a/NEWS b/NEWS
index 5cae3d4ef9..2a925dae7e 100644
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,9 @@ See the end for copying conditions.
** libgnutls: Added gnutls_certificate_get_issuer() to
compensate for the deprecated gnutls_certificate_get_x509_cas().
+** libgnutls: Limited allowed wildcards to gnutls_x509_crt_check_hostname()
+to prevent denial of service attacks.
+
** API and ABI modifications:
gnutls_certificate_get_issuer: ADDED
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 f0bc694352..abdc73324d 100644
--- a/lib/gnutls_str.c
+++ b/lib/gnutls_str.c
@@ -521,12 +521,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--)
@@ -546,7 +552,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 1b92815706..b315c481a8 100644
--- a/lib/gnutls_str.h
+++ b/lib/gnutls_str.h
@@ -91,7 +91,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 9549c418b4..16aa360b6c 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;
}