#
# Upstream: http://lists.gnu.org/archive/html/help-gnutls/2009-08/msg00011.html
# Patch: adapted from upstream commits:
# http://git.savannah.gnu.org/cgit/gnutls.git/commit/?h=gnutls_2_8_x&id=a431be86124f900c4082e82d32917f86fcce461a
# http://git.savannah.gnu.org/cgit/gnutls.git/commit/?h=gnutls_2_8_x&id=74b6d92f9675ce4e03642c4d6ced4a3a614b07f6
# http://git.savannah.gnu.org/cgit/gnutls.git/commit/?h=gnutls_2_8_x&id=40081594e3de518b998f3e5177ed5a9f7707f2e8
# http://git.savannah.gnu.org/cgit/gnutls.git/patch/?id=5a58e9d33448235377afd5fbfcee1683dc70eae3
# http://git.savannah.gnu.org/cgit/gnutls.git/patch/?id=1ea190d216767dd4ab93b87361cbcb9d4fb3aafc
# Description: fix improper handling of '\0' in Common Name (CN) and Subject
# Alternative Name (SAN) in X.509 certificates
#
diff -Nur -x '*.orig' -x '*~' gnutls26-2.4.2/lib/gnutls_str.c gnutls26-2.4.2.new/lib/gnutls_str.c
--- gnutls26-2.4.2/lib/gnutls_str.c 2008-09-15 15:04:19.000000000 -0500
+++ gnutls26-2.4.2.new/lib/gnutls_str.c 2009-08-14 13:52:59.222006047 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2002, 2004, 2005, 2007, 2008 Free Software Foundation
+ * Copyright (C) 2002, 2004, 2005, 2007, 2008, 2009 Free Software Foundation
*
* Author: Nikos Mavrogiannopoulos
*
@@ -331,16 +331,21 @@
/* 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 NULs 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++)
+ for (; *certname && *hostname && toupper(*certname) == toupper(*hostname); certname++, hostname++, certnamesize--)
;
/* the strings are the same */
- if (strlen (certname) == 0 && strlen (hostname) == 0)
+ if (certnamesize == 0 && *hostname == '\0')
return 1;
if (*certname == '*')
@@ -348,15 +353,16 @@
/* a wildcard certificate */
certname++;
-
+ certnamesize--;
+
while (1)
{
/* Use a recursive call to allow multiple wildcards */
- if (_gnutls_hostname_compare (certname, hostname))
- {
- return 1;
- }
- /* wildcards are only allowed to match a single domain component or component fragment */
+ if (_gnutls_hostname_compare (certname, certnamesize, hostname))
+ return 1;
+
+ /* wildcards are only allowed to match a single domain
+ component or component fragment */
if (*hostname == '\0' || *hostname == '.')
break;
hostname++;
diff -Nur -x '*.orig' -x '*~' gnutls26-2.4.2/lib/gnutls_str.h gnutls26-2.4.2.new/lib/gnutls_str.h
--- gnutls26-2.4.2/lib/gnutls_str.h 2008-09-15 15:04:19.000000000 -0500
+++ gnutls26-2.4.2.new/lib/gnutls_str.h 2009-08-14 13:49:43.534007138 -0500
@@ -62,7 +62,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, const char *hostname);
+int _gnutls_hostname_compare (const char *certname, size_t certnamesize, const char *hostname);
#define MAX_CN 256
#endif
diff -Nur -x '*.orig' -x '*~' gnutls26-2.4.2/lib/openpgp/pgp.c gnutls26-2.4.2.new/lib/openpgp/pgp.c
--- gnutls26-2.4.2/lib/openpgp/pgp.c 2008-09-15 15:04:19.000000000 -0500
+++ gnutls26-2.4.2.new/lib/openpgp/pgp.c 2009-08-14 13:53:35.954006279 -0500
@@ -566,7 +566,7 @@
if (ret == 0)
{
- if (_gnutls_hostname_compare (dnsname, hostname))
+ if (_gnutls_hostname_compare (dnsname, dnsnamesize, hostname))
return 1;
}
}
diff -Nur -x '*.orig' -x '*~' gnutls26-2.4.2/lib/x509/common.c gnutls26-2.4.2.new/lib/x509/common.c
--- gnutls26-2.4.2/lib/x509/common.c 2008-09-15 15:04:19.000000000 -0500
+++ gnutls26-2.4.2.new/lib/x509/common.c 2009-08-14 13:49:43.538006866 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation
*
* Author: Nikos Mavrogiannopoulos
*
@@ -241,6 +241,10 @@
{
str[len] = 0;
+ /* Refuse to deal with strings containing NULs. */
+ if (strlen (str) != len)
+ return GNUTLS_E_ASN1_DER_ERROR;
+
if (res)
_gnutls_str_cpy (res, *res_size, str);
*res_size = len;
@@ -291,25 +295,27 @@
non_printable = 0;
}
- if (res)
+ if (non_printable == 0)
{
- if (non_printable == 0)
- {
- str[len] = 0;
- _gnutls_str_cpy (res, *res_size, str);
- *res_size = len;
- }
- else
+ str[len] = 0;
+
+ /* Refuse to deal with strings containing NULs. */
+ if (strlen (str) != len)
+ return GNUTLS_E_ASN1_DER_ERROR;
+
+ if (res)
+ _gnutls_str_cpy (res, *res_size, str);
+ *res_size = len;
+ }
+ else
+ {
+ result = _gnutls_x509_data2hex (str, len, res, res_size);
+ if (result < 0)
{
- result = _gnutls_x509_data2hex (str, len, res, res_size);
- if (result < 0)
- {
- gnutls_assert ();
- return result;
- }
+ gnutls_assert ();
+ return result;
}
}
-
}
return 0;
diff -Nur -x '*.orig' -x '*~' gnutls26-2.4.2/lib/x509/output.c gnutls26-2.4.2.new/lib/x509/output.c
--- gnutls26-2.4.2/lib/x509/output.c 2008-09-15 15:04:19.000000000 -0500
+++ gnutls26-2.4.2.new/lib/x509/output.c 2009-08-14 13:49:43.538006866 -0500
@@ -272,6 +272,17 @@
return;
}
+ if ((err == GNUTLS_SAN_DNSNAME
+ || err == GNUTLS_SAN_RFC822NAME
+ || err == GNUTLS_SAN_URI) &&
+ strlen (buffer) != size)
+ {
+ adds (str, _("warning: distributionPoint contains an embedded NUL, "
+ "replacing with '!'\n"));
+ while (strlen (buffer) < size)
+ buffer[strlen (buffer)] = '!';
+ }
+
switch (err)
{
case GNUTLS_SAN_DNSNAME:
@@ -423,6 +434,17 @@
return;
}
+ if ((err == GNUTLS_SAN_DNSNAME
+ || err == GNUTLS_SAN_RFC822NAME
+ || err == GNUTLS_SAN_URI) &&
+ strlen (buffer) != size)
+ {
+ adds (str, _("warning: SAN contains an embedded NUL, "
+ "replacing with '!'\n"));
+ while (strlen (buffer) < size)
+ buffer[strlen (buffer)] = '!';
+ }
+
switch (err)
{
case GNUTLS_SAN_DNSNAME:
@@ -481,7 +503,17 @@
}
if (err == GNUTLS_SAN_OTHERNAME_XMPP)
- addf (str, _("\t\t\tXMPP Address: %.*s\n"), size, buffer);
+ {
+ if (strlen (buffer) != size)
+ {
+ adds (str, _("warning: SAN contains an embedded NUL, "
+ "replacing with '!'\n"));
+ while (strlen (buffer) < size)
+ buffer[strlen (buffer)] = '!';
+ }
+
+ addf (str, _("\t\t\tXMPP Address: %.*s\n"), size, buffer);
+ }
else
{
addf (str, _("\t\t\totherName OID: %.*s\n"), oidsize, oid);
diff -Nur -x '*.orig' -x '*~' gnutls26-2.4.2/lib/x509/rfc2818_hostname.c gnutls26-2.4.2.new/lib/x509/rfc2818_hostname.c
--- gnutls26-2.4.2/lib/x509/rfc2818_hostname.c 2008-09-15 15:04:19.000000000 -0500
+++ gnutls26-2.4.2.new/lib/x509/rfc2818_hostname.c 2009-08-14 13:54:12.614006798 -0500
@@ -74,7 +74,7 @@
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 @@
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 @@
return 0;
}
- if (_gnutls_hostname_compare (dnsname, hostname))
+ if (_gnutls_hostname_compare (dnsname, dnsnamesize, hostname))
{
return 1;
}