From c303c52ed56a406736e0db9cce9627d47b94cfb5 Mon Sep 17 00:00:00 2001 From: Tomáš Mráz Date: Aug 14 2009 12:24:51 +0000 Subject: - fix CVE-2009-2730 - handling of NUL chars in certificate CNs and SANs --- diff --git a/gnutls-2.4.2-cve-2009-2730.patch b/gnutls-2.4.2-cve-2009-2730.patch new file mode 100644 index 0000000..d7886b0 --- /dev/null +++ b/gnutls-2.4.2-cve-2009-2730.patch @@ -0,0 +1,250 @@ +diff -up gnutls-2.4.2/lib/gnutls_str.c.decoding gnutls-2.4.2/lib/gnutls_str.c +--- gnutls-2.4.2/lib/gnutls_str.c.decoding 2008-09-15 22:04:19.000000000 +0200 ++++ gnutls-2.4.2/lib/gnutls_str.c 2009-08-14 14:21:11.000000000 +0200 +@@ -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,35 +331,42 @@ _gnutls_hex2bin (const opaque * hex_data + + /* 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) +-{ +- /* find the first different character */ +- for (; *certname && *hostname && toupper(*certname) == toupper(*hostname); certname++, 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++, certnamesize--) + ; +- +- /* the strings are the same */ +- if (strlen (certname) == 0 && strlen (hostname) == 0) ++ ++ /* the strings are the same */ ++ if (certnamesize == 0 && *hostname == '\0') + return 1; +- ++ + if (*certname == '*') + { + /* 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 (*hostname == '\0' || *hostname == '.') +- break; +- hostname++; ++ 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++; + } + + return 0; +diff -up gnutls-2.4.2/lib/gnutls_str.h.decoding gnutls-2.4.2/lib/gnutls_str.h +--- gnutls-2.4.2/lib/gnutls_str.h.decoding 2008-09-15 22:04:19.000000000 +0200 ++++ gnutls-2.4.2/lib/gnutls_str.h 2009-08-14 14:18:31.000000000 +0200 +@@ -62,7 +62,7 @@ char *_gnutls_bin2hex (const void *old, + 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 -up gnutls-2.4.2/lib/openpgp/pgp.c.decoding gnutls-2.4.2/lib/openpgp/pgp.c +--- gnutls-2.4.2/lib/openpgp/pgp.c.decoding 2008-09-15 22:04:19.000000000 +0200 ++++ gnutls-2.4.2/lib/openpgp/pgp.c 2009-08-14 14:20:13.000000000 +0200 +@@ -566,7 +566,7 @@ gnutls_openpgp_crt_check_hostname (gnutl + + if (ret == 0) + { +- if (_gnutls_hostname_compare (dnsname, hostname)) ++ if (_gnutls_hostname_compare (dnsname, dnsnamesize, hostname)) + return 1; + } + } +diff -up gnutls-2.4.2/lib/x509/common.c.decoding gnutls-2.4.2/lib/x509/common.c +--- gnutls-2.4.2/lib/x509/common.c.decoding 2008-09-15 22:04:19.000000000 +0200 ++++ gnutls-2.4.2/lib/x509/common.c 2009-08-14 14:18:31.000000000 +0200 +@@ -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 @@ _gnutls_x509_oid_data2string (const char + { + 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 @@ _gnutls_x509_oid_data2string (const char + 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 -up gnutls-2.4.2/lib/x509/output.c.decoding gnutls-2.4.2/lib/x509/output.c +--- gnutls-2.4.2/lib/x509/output.c.decoding 2008-09-15 22:04:19.000000000 +0200 ++++ gnutls-2.4.2/lib/x509/output.c 2009-08-14 14:18:31.000000000 +0200 +@@ -272,6 +272,17 @@ print_crldist (gnutls_string * str, gnut + 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 @@ print_san (gnutls_string * str, gnutls_x + 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,16 @@ print_san (gnutls_string * str, gnutls_x + } + + if (err == GNUTLS_SAN_OTHERNAME_XMPP) ++ { ++ 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 -up gnutls-2.4.2/lib/x509/rfc2818_hostname.c.decoding gnutls-2.4.2/lib/x509/rfc2818_hostname.c +--- gnutls-2.4.2/lib/x509/rfc2818_hostname.c.decoding 2008-09-15 22:04:19.000000000 +0200 ++++ gnutls-2.4.2/lib/x509/rfc2818_hostname.c 2009-08-14 14:22:02.000000000 +0200 +@@ -74,17 +74,17 @@ gnutls_x509_crt_check_hostname (gnutls_x + if (ret == GNUTLS_SAN_DNSNAME) + { + found_dnsname = 1; +- if (_gnutls_hostname_compare (dnsname, hostname)) ++ if (_gnutls_hostname_compare (dnsname, dnsnamesize, hostname)) + { + return 1; + } + } + else if (ret == GNUTLS_SAN_IPADDRESS) + { +- 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)) ++ 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, dnsnamesize, hostname)) + { + return 1; + } +@@ -104,7 +104,7 @@ gnutls_x509_crt_check_hostname (gnutls_x + return 0; + } + +- if (_gnutls_hostname_compare (dnsname, hostname)) ++ if (_gnutls_hostname_compare (dnsname, dnsnamesize, hostname)) + { + return 1; + } diff --git a/gnutls.spec b/gnutls.spec index 165ec62..757dd25 100644 --- a/gnutls.spec +++ b/gnutls.spec @@ -1,7 +1,7 @@ Summary: A TLS protocol implementation Name: gnutls Version: 2.4.2 -Release: 3%{?dist} +Release: 4%{?dist} # The libgnutls library is LGPLv2+, utilities and remaining libraries are GPLv3+ License: GPLv3+ and LGPLv2+ Group: System Environment/Libraries @@ -17,6 +17,7 @@ Source0: %{name}-%{version}-nosrp.tar.bz2 Source1: libgnutls-config Patch1: gnutls-2.4.0-nosrp.patch Patch5: gnutls-1.4.1-cve-2008-4989.patch +Patch6: gnutls-2.4.2-cve-2009-2730.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) Requires: libgcrypt >= 1.2.2 @@ -70,6 +71,7 @@ This package contains Guile bindings for the library. %setup -q %patch1 -p1 -b .nosrp %patch5 -p1 -b .chain-verify +%patch6 -p1 -b .decoding for i in auth_srp_rsa.c auth_srp_sb64.c auth_srp_passwd.c auth_srp.c gnutls_srp.c ext_srp.c; do touch lib/$i @@ -150,6 +152,10 @@ fi %{_datadir}/guile/site/gnutls.scm %changelog +* Fri Aug 14 2009 Tomas Mraz 2.4.2-4 +- fix CVE-2009-2730 - handling of NUL chars in certificate + CNs and SANs + * Tue Nov 11 2008 Tomas Mraz 2.4.2-3 - fix chain verification issue CVE-2008-4989 (#470079)