Openwall GNU/*/Linux - a small security-enhanced Linux distro for servers
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date: Fri, 14 Aug 2009 16:35:38 -0500
From: Jamie Strandboge <jamie@...onical.com>
To: gnutls-devel@....org, oss-security@...ts.openwall.com
Cc: Jeff Cai <Jeff.Cai@....COM>, Simon Josefsson <simon@...efsson.org>
Subject: GnuTLS CVE-2009-2730 Patches (Was Re: GnuTLS 2.8.2)

On Fri, 14 Aug 2009, Simon Josefsson wrote:

> I don't have time/resources to produce releases for older branches.  If
> someone else wants to volunteer to work on fixing older releases, that
> would be appreciated.
> 

Attached are preliminary patches for 2.4.1, 2.0.4 and 1.2.9 backported
from the advisory[1]. This is a first pass, have only been very lightly
tested and have not been thoroughly looked at (you've been warned). They
are not intended for production use yet, but hopefully others will be
able to use them and provide feedback.

2.0.4 and 1.2.9 needed an additional patch[2] which adds wide wildcard
hostname matching. Ubuntu will likely carry this patch, but it may not
be appropriate for everyone. 2.x passes the nul-in-x509-names.c test
mentioned in the advisory. 1.2.9 does not pass the CN test yet, though
at first glance certtool output looks comparable to the others. These
patches are against Ubuntu sources and not clean tarballs.

Jamie

[1] http://lists.gnu.org/archive/html/help-gnutls/2009-08/msg00011.html
[2] http://git.savannah.gnu.org/cgit/gnutls.git/patch/?id=177e7ddb761999cd8b439e14a2bf43590756e230

-- 
Jamie Strandboge             | http://www.canonical.com

#
# 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;
 	}

#
# 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/patch/?id=177e7ddb761999cd8b439e14a2bf43590756e230
#        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. Also backported
#              177e7ddb761999cd8b439e14a2bf43590756e230 for added wide wildcard
#              hostname matching so _gnutls_hostname_compare() is up to date
#              with upstream GnuTLS.
#
diff -Nur -x '*.orig' -x '*~' gnutls13-2.0.4/lib/x509/common.c gnutls13-2.0.4.new/lib/x509/common.c
--- gnutls13-2.0.4/lib/x509/common.c	2007-11-15 09:24:56.000000000 -0600
+++ gnutls13-2.0.4.new/lib/x509/common.c	2009-08-14 15:12:06.698514568 -0500
@@ -239,6 +239,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;
@@ -289,25 +293,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 '*~' gnutls13-2.0.4/lib/x509/output.c gnutls13-2.0.4.new/lib/x509/output.c
--- gnutls13-2.0.4/lib/x509/output.c	2007-11-15 09:21:47.000000000 -0600
+++ gnutls13-2.0.4.new/lib/x509/output.c	2009-08-14 15:12:06.710506308 -0500
@@ -271,6 +271,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:
@@ -422,6 +433,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:
@@ -480,7 +502,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 '*~' gnutls13-2.0.4/lib/x509/rfc2818.h gnutls13-2.0.4.new/lib/x509/rfc2818.h
--- gnutls13-2.0.4/lib/x509/rfc2818.h	2007-11-15 09:24:56.000000000 -0600
+++ gnutls13-2.0.4.new/lib/x509/rfc2818.h	2009-08-14 15:13:03.362007683 -0500
@@ -22,5 +22,5 @@
  *
  */
 
-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
diff -Nur -x '*.orig' -x '*~' gnutls13-2.0.4/lib/x509/rfc2818_hostname.c gnutls13-2.0.4.new/lib/x509/rfc2818_hostname.c
--- gnutls13-2.0.4/lib/x509/rfc2818_hostname.c	2007-11-15 09:21:47.000000000 -0600
+++ gnutls13-2.0.4.new/lib/x509/rfc2818_hostname.c	2009-08-14 15:12:06.710506308 -0500
@@ -30,43 +30,45 @@
 
 /* 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)
 {
-  const char *cmpstr1, *cmpstr2;
-
-  if (strlen (certname) == 0 || strlen (hostname) == 0)
-    return 0;
-
-  if (strlen (certname) > 2 && strncmp (certname, "*.", 2) == 0)
+   /* find the first different character */
+  for (; *certname && *hostname && toupper(*certname) == toupper(*hostname); certname++, hostname++, certnamesize--)
+    ;
+ 
+   /* the strings are the same */
+  if (certnamesize == 0 && *hostname == '\0')
+    return 1;
+  
+  if (*certname == '*')
     {
       /* a wildcard certificate */
 
-      cmpstr1 = certname + 1;
-
-      /* find the first dot in hostname, compare from there on */
-      cmpstr2 = strchr (hostname, '.');
-
-      if (cmpstr2 == NULL)
-	{
-	  /* error, the hostname we're connecting to is only a local part */
-	  return 0;
-	}
+      certname++;
+      certnamesize--;
 
-      if (strcasecmp (cmpstr1, cmpstr2) == 0)
-	{
-	  return 1;
+      while (1)
+       	{
+	  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;
     }
 
-  if (strcasecmp (certname, hostname) == 0)
-    {
-      return 1;
-    }
-
   return 0;
 }
 
@@ -118,7 +120,7 @@
       if (ret == GNUTLS_SAN_DNSNAME)
 	{
 	  found_dnsname = 1;
-	  if (_gnutls_hostname_compare (dnsname, hostname))
+	  if (_gnutls_hostname_compare (dnsname, dnsnamesize, hostname))
 	    {
 	      return 1;
 	    }
@@ -128,7 +130,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;
 	    }
@@ -148,7 +150,7 @@
 	  return 0;
 	}
 
-      if (_gnutls_hostname_compare (dnsname, hostname))
+      if (_gnutls_hostname_compare (dnsname, dnsnamesize, hostname))
 	{
 	  return 1;
 	}
diff -Nur -x '*.orig' -x '*~' gnutls13-2.0.4/libextra/openpgp/pgp.c gnutls13-2.0.4.new/libextra/openpgp/pgp.c
--- gnutls13-2.0.4/libextra/openpgp/pgp.c	2007-11-15 09:24:56.000000000 -0600
+++ gnutls13-2.0.4.new/libextra/openpgp/pgp.c	2009-08-14 15:12:06.710506308 -0500
@@ -501,7 +501,7 @@
       dnsnamesize = sizeof (dnsname);
       ret = gnutls_openpgp_key_get_name (key, i, dnsname, &dnsnamesize);
       /* FIXME: ret is not used */
-      if (_gnutls_hostname_compare (dnsname, hostname))
+      if (_gnutls_hostname_compare (dnsname, dnsnamesize, hostname))
 	return 1;
     }
 
diff -Nur -x '*.orig' -x '*~' gnutls13-2.0.4/tests/hostname-check/hostname-check.c gnutls13-2.0.4.new/tests/hostname-check/hostname-check.c
--- gnutls13-2.0.4/tests/hostname-check/hostname-check.c	2007-11-15 09:21:47.000000000 -0600
+++ gnutls13-2.0.4.new/tests/hostname-check/hostname-check.c	2009-08-14 15:12:06.710506308 -0500
@@ -336,6 +336,154 @@
   "V4YbqvLUY2LG/bMEZGCcd8NL0eTHdwAXedIrHxSt6TTI2g==\n"
   "-----END CERTIFICATE-----\n";
 
+/* Certificate with multiple wildcards SAN but no CN. */
+char pem6[] =
+  "X.509 Certificate Information:\n"
+  "        Version: 3\n"
+  "        Serial Number (hex): 00\n"
+  "        Validity:\n"
+  "                Not Before: Sat May  3 11:00:51 UTC 2008\n"
+  "                Not After: Sat May 17 11:00:54 UTC 2008\n"
+  "        Subject: O=GnuTLS hostname check test CA\n"
+  "        Subject Public Key Algorithm: RSA\n"
+  "                Modulus (bits 1024):\n"
+  "                        d2:05:c1:65:cb:bd:1e:2e:eb:7b:87:07:94:4c:93:33\n"
+  "                        f3:81:83:7d:32:1b:71:4e:4e:7f:c7:bc:bf:4b:2f:f2\n"
+  "                        49:b5:cf:bf:c0:b8:e8:29:cc:f3:61:bd:2e:1d:e4:e8\n"
+  "                        19:dd:c5:bd:2e:f0:35:b1:fd:30:d7:f5:a8:7c:83:9a\n"
+  "                        13:9e:bf:25:ed:08:a6:05:9e:7b:4e:23:59:c3:0e:5a\n"
+  "                        f3:bf:54:c7:dc:d4:13:57:a1:0f:a2:9e:c8:ab:75:66\n"
+  "                        de:07:84:8d:68:ad:71:04:e0:9c:bd:cb:f6:08:7a:97\n"
+  "                        42:f8:10:94:29:01:4a:7e:61:d7:04:21:05:4c:f1:07\n"
+  "                Exponent:\n"
+  "                        01:00:01\n"
+  "        Extensions:\n"
+  "                Basic Constraints (critical):\n"
+  "                        Certificate Authority (CA): TRUE\n"
+  "                Subject Alternative Name (not critical):\n"
+  "                        DNSname: *.*.example.org\n"
+  "                Key Purpose (not critical):\n"
+  "                        TLS WWW Server.\n"
+  "                Subject Key Identifier (not critical):\n"
+  "                        5493e6599b283b4529378818aef9a4abbf4d9918\n"
+  "Other Information:\n"
+  "        Public Key Id:\n"
+  "                5493e6599b283b4529378818aef9a4abbf4d9918\n"
+  "\n"
+  "-----BEGIN CERTIFICATE-----\n"
+  "MIICIjCCAY2gAwIBAgIBADALBgkqhkiG9w0BAQUwKDEmMCQGA1UEChMdR251VExT\n"
+  "IGhvc3RuYW1lIGNoZWNrIHRlc3QgQ0EwHhcNMDgwNTAzMTEwMDUxWhcNMDgwNTE3\n"
+  "MTEwMDU0WjAoMSYwJAYDVQQKEx1HbnVUTFMgaG9zdG5hbWUgY2hlY2sgdGVzdCBD\n"
+  "QTCBnDALBgkqhkiG9w0BAQEDgYwAMIGIAoGA0gXBZcu9Hi7re4cHlEyTM/OBg30y\n"
+  "G3FOTn/HvL9LL/JJtc+/wLjoKczzYb0uHeToGd3FvS7wNbH9MNf1qHyDmhOevyXt\n"
+  "CKYFnntOI1nDDlrzv1TH3NQTV6EPop7Iq3Vm3geEjWitcQTgnL3L9gh6l0L4EJQp\n"
+  "AUp+YdcEIQVM8QcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAaBgNVHREEEzAR\n"
+  "gg8qLiouZXhhbXBsZS5vcmcwEwYDVR0lBAwwCgYIKwYBBQUHAwEwHQYDVR0OBBYE\n"
+  "FFST5lmbKDtFKTeIGK75pKu/TZkYMAsGCSqGSIb3DQEBBQOBgQAQ9PStleVvfmlK\n"
+  "wRs8RE/oOO+ouC3qLdnumNEITMRFh8Q12/X4yMLD3CH0aQ/hvHcP26PxAWzpNutk\n"
+  "swNx7AzsCu6pN1t1aI3jLgo8e4/zZi57e8QcRuXZPDJxtJxVhJZX/C4pSz802WhS\n"
+  "64NgtpHEMu9JUHFhtRwPcvVGYqPUUA==\n"
+  "-----END CERTIFICATE-----\n";
+
+/* Certificate with prefixed and suffixed wildcard SAN but no CN. */
+char pem7[] =
+  "X.509 Certificate Information:\n"
+  "        Version: 3\n"
+  "        Serial Number (hex): 00\n"
+  "        Validity:\n"
+  "                Not Before: Sat May  3 11:02:43 UTC 2008\n"
+  "                Not After: Sat May 17 11:02:45 UTC 2008\n"
+  "        Subject: O=GnuTLS hostname check test CA\n"
+  "        Subject Public Key Algorithm: RSA\n"
+  "                Modulus (bits 1024):\n"
+  "                        d2:05:c1:65:cb:bd:1e:2e:eb:7b:87:07:94:4c:93:33\n"
+  "                        f3:81:83:7d:32:1b:71:4e:4e:7f:c7:bc:bf:4b:2f:f2\n"
+  "                        49:b5:cf:bf:c0:b8:e8:29:cc:f3:61:bd:2e:1d:e4:e8\n"
+  "                        19:dd:c5:bd:2e:f0:35:b1:fd:30:d7:f5:a8:7c:83:9a\n"
+  "                        13:9e:bf:25:ed:08:a6:05:9e:7b:4e:23:59:c3:0e:5a\n"
+  "                        f3:bf:54:c7:dc:d4:13:57:a1:0f:a2:9e:c8:ab:75:66\n"
+  "                        de:07:84:8d:68:ad:71:04:e0:9c:bd:cb:f6:08:7a:97\n"
+  "                        42:f8:10:94:29:01:4a:7e:61:d7:04:21:05:4c:f1:07\n"
+  "                Exponent:\n"
+  "                        01:00:01\n"
+  "        Extensions:\n"
+  "                Basic Constraints (critical):\n"
+  "                        Certificate Authority (CA): TRUE\n"
+  "                Subject Alternative Name (not critical):\n"
+  "                        DNSname: foo*bar.example.org\n"
+  "                Key Purpose (not critical):\n"
+  "                        TLS WWW Server.\n"
+  "                Subject Key Identifier (not critical):\n"
+  "                        5493e6599b283b4529378818aef9a4abbf4d9918\n"
+  "Other Information:\n"
+  "        Public Key Id:\n"
+  "                5493e6599b283b4529378818aef9a4abbf4d9918\n"
+  "\n"
+  "-----BEGIN CERTIFICATE-----\n"
+  "MIICJjCCAZGgAwIBAgIBADALBgkqhkiG9w0BAQUwKDEmMCQGA1UEChMdR251VExT\n"
+  "IGhvc3RuYW1lIGNoZWNrIHRlc3QgQ0EwHhcNMDgwNTAzMTEwMjQzWhcNMDgwNTE3\n"
+  "MTEwMjQ1WjAoMSYwJAYDVQQKEx1HbnVUTFMgaG9zdG5hbWUgY2hlY2sgdGVzdCBD\n"
+  "QTCBnDALBgkqhkiG9w0BAQEDgYwAMIGIAoGA0gXBZcu9Hi7re4cHlEyTM/OBg30y\n"
+  "G3FOTn/HvL9LL/JJtc+/wLjoKczzYb0uHeToGd3FvS7wNbH9MNf1qHyDmhOevyXt\n"
+  "CKYFnntOI1nDDlrzv1TH3NQTV6EPop7Iq3Vm3geEjWitcQTgnL3L9gh6l0L4EJQp\n"
+  "AUp+YdcEIQVM8QcCAwEAAaNnMGUwDwYDVR0TAQH/BAUwAwEB/zAeBgNVHREEFzAV\n"
+  "ghNmb28qYmFyLmV4YW1wbGUub3JnMBMGA1UdJQQMMAoGCCsGAQUFBwMBMB0GA1Ud\n"
+  "DgQWBBRUk+ZZmyg7RSk3iBiu+aSrv02ZGDALBgkqhkiG9w0BAQUDgYEAPPNe38jc\n"
+  "8NsZQVKKLYc1Y4y8LRPhvnxkSnlcGa1RzYZY1s12BZ6OVIfyxD1Z9BcNdqRSq7bQ\n"
+  "kEicsGp5ugGQTNq6aSlzYOUD9/fUP3jDsH7HVb36aCF3waGCQWj+pLqK0LYcW2p/\n"
+  "xnr5+z4YevFBhn7l/fMhg8TzKejxYm7TECg=\n"
+  "-----END CERTIFICATE-----\n";
+
+/* Certificate with ending wildcard SAN but no CN. */
+char pem8[] =
+  "X.509 Certificate Information:\n"
+  "        Version: 3\n"
+  "        Serial Number (hex): 00\n"
+  "        Validity:\n"
+  "                Not Before: Sat May  3 11:24:38 UTC 2008\n"
+  "                Not After: Sat May 17 11:24:40 UTC 2008\n"
+  "        Subject: O=GnuTLS hostname check test CA\n"
+  "        Subject Public Key Algorithm: RSA\n"
+  "                Modulus (bits 1024):\n"
+  "                        d2:05:c1:65:cb:bd:1e:2e:eb:7b:87:07:94:4c:93:33\n"
+  "                        f3:81:83:7d:32:1b:71:4e:4e:7f:c7:bc:bf:4b:2f:f2\n"
+  "                        49:b5:cf:bf:c0:b8:e8:29:cc:f3:61:bd:2e:1d:e4:e8\n"
+  "                        19:dd:c5:bd:2e:f0:35:b1:fd:30:d7:f5:a8:7c:83:9a\n"
+  "                        13:9e:bf:25:ed:08:a6:05:9e:7b:4e:23:59:c3:0e:5a\n"
+  "                        f3:bf:54:c7:dc:d4:13:57:a1:0f:a2:9e:c8:ab:75:66\n"
+  "                        de:07:84:8d:68:ad:71:04:e0:9c:bd:cb:f6:08:7a:97\n"
+  "                        42:f8:10:94:29:01:4a:7e:61:d7:04:21:05:4c:f1:07\n"
+  "                Exponent:\n"
+  "                        01:00:01\n"
+  "        Extensions:\n"
+  "                Basic Constraints (critical):\n"
+  "                        Certificate Authority (CA): TRUE\n"
+  "                Subject Alternative Name (not critical):\n"
+  "                        DNSname: www.example.*\n"
+  "                Key Purpose (not critical):\n"
+  "                        TLS WWW Server.\n"
+  "                Subject Key Identifier (not critical):\n"
+  "                        5493e6599b283b4529378818aef9a4abbf4d9918\n"
+  "Other Information:\n"
+  "        Public Key Id:\n"
+  "                5493e6599b283b4529378818aef9a4abbf4d9918\n"
+  "\n"
+  "-----BEGIN CERTIFICATE-----\n"
+  "MIICIDCCAYugAwIBAgIBADALBgkqhkiG9w0BAQUwKDEmMCQGA1UEChMdR251VExT\n"
+  "IGhvc3RuYW1lIGNoZWNrIHRlc3QgQ0EwHhcNMDgwNTAzMTEyNDM4WhcNMDgwNTE3\n"
+  "MTEyNDQwWjAoMSYwJAYDVQQKEx1HbnVUTFMgaG9zdG5hbWUgY2hlY2sgdGVzdCBD\n"
+  "QTCBnDALBgkqhkiG9w0BAQEDgYwAMIGIAoGA0gXBZcu9Hi7re4cHlEyTM/OBg30y\n"
+  "G3FOTn/HvL9LL/JJtc+/wLjoKczzYb0uHeToGd3FvS7wNbH9MNf1qHyDmhOevyXt\n"
+  "CKYFnntOI1nDDlrzv1TH3NQTV6EPop7Iq3Vm3geEjWitcQTgnL3L9gh6l0L4EJQp\n"
+  "AUp+YdcEIQVM8QcCAwEAAaNhMF8wDwYDVR0TAQH/BAUwAwEB/zAYBgNVHREEETAP\n"
+  "gg13d3cuZXhhbXBsZS4qMBMGA1UdJQQMMAoGCCsGAQUFBwMBMB0GA1UdDgQWBBRU\n"
+  "k+ZZmyg7RSk3iBiu+aSrv02ZGDALBgkqhkiG9w0BAQUDgYEAZ7gLXtXwFW61dSAM\n"
+  "0Qt6IN68WBH7LCzetSF8ofG1WVUImCUU3pqXhXYtPGTrswOh2AavWTRbzVTtrFvf\n"
+  "WJg09Z7H6I70RPvAYGsK9t9qJ/4TPoYTGYQgsTbVpkv13O54O6jzemd8Zws/xMH5\n"
+  "7/q6C7P5OUmGOtfVe7UVDY0taQM=\n"
+  "-----END CERTIFICATE-----\n";
+
+
 void
 doit (void)
 {
@@ -475,6 +623,90 @@
   else
     success ("Hostname correctly does not match (%d)\n", ret);
 
+  success ("Testing pem6...\n");
+  data.data = pem6;
+  data.size = strlen (pem6);
+
+  ret = gnutls_x509_crt_import (cert, &data, GNUTLS_X509_FMT_PEM);
+  if (ret < 0)
+    fail ("gnutls_x509_crt_import: %d\n", ret);
+
+  ret = gnutls_x509_crt_check_hostname (cert, "foo.example.org");
+  if (ret)
+    fail ("Hostname incorrectly matches (%d)\n", ret);
+  else
+    success ("Hostname correctly does not match (%d)\n", ret);
+
+  ret = gnutls_x509_crt_check_hostname (cert, "bar.foo.example.org");
+  if (ret)
+    success ("Hostname correctly matches (%d)\n", ret);
+  else
+    fail ("Hostname incorrectly does not match (%d)\n", ret);
+
+  success ("Testing pem7...\n");
+  data.data = pem7;
+  data.size = strlen (pem7);
+
+  ret = gnutls_x509_crt_import (cert, &data, GNUTLS_X509_FMT_PEM);
+  if (ret < 0)
+    fail ("gnutls_x509_crt_import: %d\n", ret);
+
+  ret = gnutls_x509_crt_check_hostname (cert, "foo.bar.example.org");
+  if (ret)
+    fail ("Hostname incorrectly matches (%d)\n", ret);
+  else
+    success ("Hostname correctly does not match (%d)\n", ret);
+
+  ret = gnutls_x509_crt_check_hostname (cert, "foobar.bar.example.org");
+  if (ret)
+    fail ("Hostname incorrectly matches (%d)\n", ret);
+  else
+    success ("Hostname correctly does not match (%d)\n", ret);
+
+  ret = gnutls_x509_crt_check_hostname (cert, "foobar.example.org");
+  if (ret)
+    success ("Hostname correctly matches (%d)\n", ret);
+  else
+    fail ("Hostname incorrectly does not match (%d)\n", ret);
+
+  ret = gnutls_x509_crt_check_hostname (cert, "foobazbar.example.org");
+  if (ret)
+    success ("Hostname correctly matches (%d)\n", ret);
+  else
+    fail ("Hostname incorrectly does not match (%d)\n", ret);
+
+  success ("Testing pem8...\n");
+  data.data = pem8;
+  data.size = strlen (pem8);
+
+  ret = gnutls_x509_crt_import (cert, &data, GNUTLS_X509_FMT_PEM);
+  if (ret < 0)
+    fail ("gnutls_x509_crt_import: %d\n", ret);
+
+  ret = gnutls_x509_crt_check_hostname (cert, "www.example.org");
+  if (ret)
+    success ("Hostname correctly matches (%d)\n", ret);
+  else
+    fail ("Hostname incorrectly does not match (%d)\n", ret);
+
+  ret = gnutls_x509_crt_check_hostname (cert, "www.example.");
+  if (ret)
+    success ("Hostname correctly matches (%d)\n", ret);
+  else
+    fail ("Hostname incorrectly does not match (%d)\n", ret);
+
+  ret = gnutls_x509_crt_check_hostname (cert, "www.example.com");
+  if (ret)
+    success ("Hostname correctly matches (%d)\n", ret);
+  else
+    fail ("Hostname incorrectly does not match (%d)\n", ret);
+
+  ret = gnutls_x509_crt_check_hostname (cert, "www.example.foo.com");
+  if (ret)
+    fail ("Hostname incorrectly matches (%d)\n", ret);
+  else
+    success ("Hostname correctly does not match (%d)\n", ret);
+
   gnutls_x509_crt_deinit (cert);
 
   gnutls_global_deinit ();

#
# 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/patch/?id=177e7ddb761999cd8b439e14a2bf43590756e230
#        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. Also backported
#              177e7ddb761999cd8b439e14a2bf43590756e230 for added wide wildcard
#              hostname matching so _gnutls_hostname_compare() is up to date
#              with upstream GnuTLS.
#
diff -Nur -x '*.orig' -x '*~' gnutls12-1.2.9/lib/x509/common.c gnutls12-1.2.9.new/lib/x509/common.c
--- gnutls12-1.2.9/lib/x509/common.c	2005-05-26 10:21:36.000000000 -0500
+++ gnutls12-1.2.9.new/lib/x509/common.c	2009-08-14 15:45:54.126511370 -0500
@@ -220,6 +220,10 @@
     if (CHOICE == 0) {
 	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;
@@ -265,20 +269,23 @@
 		non_printable = 0;
 	}
 
-	if (res) {
-	    if (non_printable == 0) {
-		str[len] = 0;
-		_gnutls_str_cpy(res, *res_size, str);
-		*res_size = len;
-	    } else {
-		result = _gnutls_x509_data2hex(str, len, res, res_size);
-		if (result < 0) {
-		    gnutls_assert();
-		    return result;
-		}
+	if (non_printable == 0) {
+	    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) {
+		gnutls_assert();
+		return result;
 	    }
 	}
-
     }
 
     return 0;
diff -Nur -x '*.orig' -x '*~' gnutls12-1.2.9/lib/x509/rfc2818.h gnutls12-1.2.9.new/lib/x509/rfc2818.h
--- gnutls12-1.2.9/lib/x509/rfc2818.h	2005-05-26 10:21:36.000000000 -0500
+++ gnutls12-1.2.9.new/lib/x509/rfc2818.h	2009-08-14 15:45:54.158505664 -0500
@@ -22,5 +22,5 @@
  *
  */
 
-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
diff -Nur -x '*.orig' -x '*~' gnutls12-1.2.9/lib/x509/rfc2818_hostname.c gnutls12-1.2.9.new/lib/x509/rfc2818_hostname.c
--- gnutls12-1.2.9/lib/x509/rfc2818_hostname.c	2005-05-26 10:21:36.000000000 -0500
+++ gnutls12-1.2.9.new/lib/x509/rfc2818_hostname.c	2009-08-14 15:46:20.416107102 -0500
@@ -30,39 +30,43 @@
 #include <gnutls_errors.h>
 
 /* compare hostname against certificate, taking account of wildcards
- * return 1 on success or 0 on error 
+ * 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)
 {
-    const char *cmpstr1, *cmpstr2;
+    /* find the first different character */
+    for (; *certname && *hostname && toupper(*certname) == toupper(*hostname); certname++, hostname++, certnamesize--)
+      ;
+
+    /* the strings are the same */
+    if (certnamesize == 0 && *hostname == '\0')
+      return 1;
 
-    if (strlen(certname) == 0 || strlen(hostname) == 0)
-	return 0;
-
-    if (strlen(certname) > 2 && strncmp(certname, "*.", 2) == 0) {
+    if (*certname == '*') {
 	/* a wildcard certificate */
 
-	cmpstr1 = certname + 1;
-
-	/* find the first dot in hostname, compare from there on */
-	cmpstr2 = strchr(hostname, '.');
-
-	if (cmpstr2 == NULL) {
-	    /* error, the hostname we're connecting to is only a local part */
-	    return 0;
-	}
+	certname++;
+	certnamesize--;
 
-	if (strcasecmp(cmpstr1, cmpstr2) == 0) {
+	while (1) {
+	  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;
     }
 
-    if (strcasecmp(certname, hostname) == 0) {
-	return 1;
-    }
-
     return 0;
 }
 
@@ -113,7 +117,7 @@
 
 	if (ret == GNUTLS_SAN_DNSNAME) {
 	    found_dnsname = 1;
-	    if (_gnutls_hostname_compare(dnsname, hostname)) {
+	    if (_gnutls_hostname_compare(dnsname, dnsnamesize, hostname)) {
 		return 1;
 	    }
 	}
@@ -131,7 +135,7 @@
 	    return 1;
 	}
 
-	if (_gnutls_hostname_compare(dnsname, hostname)) {
+	if (_gnutls_hostname_compare(dnsname, dnsnamesize, hostname)) {
 	    return 1;
 	}
     }
diff -Nur -x '*.orig' -x '*~' gnutls12-1.2.9/libextra/openpgp/pgp.c gnutls12-1.2.9.new/libextra/openpgp/pgp.c
--- gnutls12-1.2.9/libextra/openpgp/pgp.c	2005-05-26 10:18:38.000000000 -0500
+++ gnutls12-1.2.9.new/libextra/openpgp/pgp.c	2009-08-14 15:45:54.158505664 -0500
@@ -498,7 +498,7 @@
 	dnsnamesize = sizeof(dnsname);
 	ret = gnutls_openpgp_key_get_name(key, i, dnsname, &dnsnamesize);
 
-	if (_gnutls_hostname_compare(dnsname, hostname)) {
+	if (_gnutls_hostname_compare(dnsname, dnsnamesize, hostname)) {
 	    return 1;
 	}
     }
diff -Nur -x '*.orig' -x '*~' gnutls12-1.2.9/src/certtool.c gnutls12-1.2.9.new/src/certtool.c
--- gnutls12-1.2.9/src/certtool.c	2005-11-07 12:52:12.000000000 -0600
+++ gnutls12-1.2.9.new/src/certtool.c	2009-08-14 15:45:54.162506490 -0500
@@ -1155,6 +1155,15 @@
 	if (ret < 0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
 	    fprintf(out, "\t\tFound unsupported alternative name.\n");
 	} else
+	    if ((ret == GNUTLS_SAN_DNSNAME
+		 || ret == GNUTLS_SAN_RFC822NAME
+		 || ret == GNUTLS_SAN_URI) &&
+		strlen (buffer) != size) {
+		    fprintf(out, "\nwarning: SAN contains an embedded NUL, "
+				   "replacing with '!'\n");
+		while (strlen (buffer) < size)
+		    buffer[strlen (buffer)] = '!';
+	    }
 	    switch (ret) {
 	    case GNUTLS_SAN_DNSNAME:
 		fprintf(out, "\t\tDNSname: %s\n", buffer);
@@ -1190,6 +1199,15 @@
 	if (ret < 0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
 	    fprintf(out, "\t\tError decoding: %s\n", gnutls_strerror(ret));
 	} else
+	    if ((ret == GNUTLS_SAN_DNSNAME
+		 || ret == GNUTLS_SAN_RFC822NAME
+		 || ret == GNUTLS_SAN_URI) &&
+		strlen (buffer) != size) {
+		    fprintf(out, "\nwarning: distributionPoint contains an embedded NUL, "
+				   "replacing with '!'\n");
+		while (strlen (buffer) < size)
+		    buffer[strlen (buffer)] = '!';
+	    }
 	    switch (ret) {
 	    case GNUTLS_SAN_DNSNAME:
 		fprintf(out, "\t\tDNSname: %s\n", buffer);


[ CONTENT OF TYPE application/pgp-signature SKIPPED ]

Powered by blists - more mailing lists

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Powered by Openwall GNU/*/Linux - Powered by OpenVZ