subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bre...@apache.org
Subject svn commit: r1613529 - in /subversion/branches/svn-auth-x509/subversion: include/svn_x509.h libsvn_subr/x509.h libsvn_subr/x509parse.c svn/auth-cmd.c tests/libsvn_subr/x509-test.c
Date Fri, 25 Jul 2014 22:45:46 GMT
Author: breser
Date: Fri Jul 25 22:45:46 2014
New Revision: 1613529

URL: http://svn.apache.org/r1613529
Log:
On svn-auth-x509 branch, Add support for determing all the hostnames the
cert can match.  This includes the Subject Alternate Name dNSNames.

* subversion/include/svn_x509.h
  (SVN_X509_CERTINFO_KEY_HOSTNAMES): New constant.

* subversion/libsvn_subr/x509.h
  (OID_SUBJECT_ALT_NAME): New constant.
  (x509_cert): Add dnsnames member.

* subversion/libsvn_subr/x509parse.c
  (x509_skip_ext): Rename to ...
  (x509_get_ext): and actually parse the extensions, pulling out the
    dNSNames Subject Alternate Names.
  (is_hostname, x509parse_get_hostnames): New functions.
  (svn_x509_parse_cert): Use the new functions to retrieve the hostnames
    that apply to the certificate and add them as a comma+space separated
    string in the new SVN_X509_CERTINFO_KEY_HOSTNAMES hash entry.

* subversion/svn/auth-cmd.c
  (show_cert): Display the hostnames parsed out of the certificate if there
    are any.
  (list_credential): Stop printing the hostname saved by the old style code.

* subversion/tests/libsvn_subr/x509-test.c
  (x509_test): Add the hostnames member.
  (cert_tests): Add hostnames members for the existing tests and add new
    test entries for some Subject Alt Name certificates.
  (compare_results): Test the SVN_X509_CERTINFO_KEY_HOSTNAMES key.

Modified:
    subversion/branches/svn-auth-x509/subversion/include/svn_x509.h
    subversion/branches/svn-auth-x509/subversion/libsvn_subr/x509.h
    subversion/branches/svn-auth-x509/subversion/libsvn_subr/x509parse.c
    subversion/branches/svn-auth-x509/subversion/svn/auth-cmd.c
    subversion/branches/svn-auth-x509/subversion/tests/libsvn_subr/x509-test.c

Modified: subversion/branches/svn-auth-x509/subversion/include/svn_x509.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/include/svn_x509.h?rev=1613529&r1=1613528&r2=1613529&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/include/svn_x509.h (original)
+++ subversion/branches/svn-auth-x509/subversion/include/svn_x509.h Fri Jul 25 22:45:46 2014
@@ -38,6 +38,7 @@
 #define SVN_X509_CERTINFO_KEY_VALID_FROM  "valid-from"
 #define SVN_X509_CERTINFO_KEY_VALID_TO    "valid-to"
 #define SVN_X509_CERTINFO_KEY_SHA1_DIGEST "sha1-digest"
+#define SVN_X509_CERTINFO_KEY_HOSTNAMES   "hostnames"
 
 #ifdef __cplusplus
 extern "C" {

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_subr/x509.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_subr/x509.h?rev=1613529&r1=1613528&r2=1613529&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_subr/x509.h (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_subr/x509.h Fri Jul 25 22:45:46 2014
@@ -73,6 +73,7 @@
 
 #define OID_X520                "\x55\x04"
 #define OID_PKCS9               "\x2A\x86\x48\x86\xF7\x0D\x01\x09"
+#define OID_SUBJECT_ALT_NAME    "\x55\x1D\x11"
 
 #ifdef __cplusplus
 extern "C" {
@@ -106,6 +107,7 @@ typedef struct _x509_cert {
 
   x509_buf issuer_id;
   x509_buf subject_id;
+  apr_array_header_t *dnsnames;
 
   x509_buf sig_oid2;
   x509_buf sig;

Modified: subversion/branches/svn-auth-x509/subversion/libsvn_subr/x509parse.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_subr/x509parse.c?rev=1613529&r1=1613528&r2=1613529&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/libsvn_subr/x509parse.c (original)
+++ subversion/branches/svn-auth-x509/subversion/libsvn_subr/x509parse.c Fri Jul 25 22:45:46
2014
@@ -46,6 +46,7 @@
  */
 
 #include <apr_pools.h>
+#include <apr_tables.h>
 #include "svn_hash.h"
 #include "svn_string.h"
 #include "svn_time.h"
@@ -528,7 +529,8 @@ x509_get_uid(const unsigned char **p,
  * X.509 v3 extensions (not parsed)
  */
 static svn_error_t *
-x509_skip_ext(const unsigned char **p,
+x509_get_ext(apr_array_header_t *dnsnames,
+             const unsigned char **p,
              const unsigned char *end)
 {
   svn_error_t *err;
@@ -541,6 +543,7 @@ x509_skip_ext(const unsigned char **p,
                      ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3);
   if (err)
     {
+      /* If there aren't extensions that's ok they aren't required */
       if (err->apr_err == SVN_ERR_ASN1_UNEXPECTED_TAG)
         {
           svn_error_clear(err);
@@ -550,8 +553,105 @@ x509_skip_ext(const unsigned char **p,
       return svn_error_trace(err);
     }
 
-  /* Skip extensions */
-  *p += len;
+  end = *p + len;
+
+  SVN_ERR(asn1_get_tag(p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE));
+
+  if (end != *p + len)
+    {
+      err = svn_error_create(SVN_ERR_X509_CERT_INVALID_EXTENSIONS, NULL, NULL);
+      return svn_error_create(SVN_ERR_ASN1_LENGTH_MISMATCH, err, NULL);
+    }
+
+  while (*p < end)
+    {
+      int ext_len;
+      const unsigned char *ext_start, *sna_end;
+      err = asn1_get_tag(p, end, &ext_len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+      if (err)
+        return svn_error_create(SVN_ERR_X509_CERT_INVALID_EXTENSIONS, err,
+                                NULL);
+      ext_start = *p;
+
+      err = asn1_get_tag(p, end, &len, ASN1_OID);
+      if (err)
+        return svn_error_create(SVN_ERR_X509_CERT_INVALID_EXTENSIONS, err,
+                                NULL);
+
+      /* skip all extensions except SubjectAltName */
+      if (len != sizeof(OID_SUBJECT_ALT_NAME) - 1 ||
+          memcmp(*p, OID_SUBJECT_ALT_NAME, sizeof(OID_SUBJECT_ALT_NAME) - 1) != 0)
+        {
+          *p += ext_len - (*p - ext_start);
+          continue;
+        }
+      *p += len;
+
+      err = asn1_get_tag(p, end, &len, ASN1_OCTET_STRING);
+      if (err)
+        return svn_error_create(SVN_ERR_X509_CERT_INVALID_EXTENSIONS, err,
+                                NULL);
+
+      /*   SubjectAltName ::= GeneralNames
+
+           GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
+
+           GeneralName ::= CHOICE {
+                otherName                       [0]     OtherName,
+                rfc822Name                      [1]     IA5String,
+                dNSName                         [2]     IA5String,
+                x400Address                     [3]     ORAddress,
+                directoryName                   [4]     Name,
+                ediPartyName                    [5]     EDIPartyName,
+                uniformResourceIdentifier       [6]     IA5String,
+                iPAddress                       [7]     OCTET STRING,
+                registeredID                    [8]     OBJECT IDENTIFIER } */
+      sna_end = *p + len;
+
+      err = asn1_get_tag(p, sna_end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+      if (err)
+        return svn_error_create(SVN_ERR_X509_CERT_INVALID_EXTENSIONS, err,
+                                NULL);
+
+      if (sna_end != *p + len)
+        {
+          err = svn_error_create(SVN_ERR_X509_CERT_INVALID_EXTENSIONS, NULL, NULL);
+          return svn_error_create(SVN_ERR_ASN1_LENGTH_MISMATCH, err, NULL);
+        }
+
+      while (*p < sna_end)
+        {
+          err = asn1_get_tag(p, sna_end, &len, ASN1_CONTEXT_SPECIFIC |
+                             ASN1_PRIMITIVE | 2);
+          if (err)
+            {
+              /* not not a dNSName */
+              if (err->apr_err == SVN_ERR_ASN1_UNEXPECTED_TAG)
+                {
+                  svn_error_clear(err);
+                  /* need to skip the tag and then find the length to
+                   * skip to ignore this SNA entry. */
+                  (*p)++;
+                  SVN_ERR(asn1_get_len(p, sna_end, &len));
+                  *p += len;
+                  continue;
+                }
+            }
+          else
+            {
+              /* We found a dNSName entry */
+              x509_buf *dnsname = apr_palloc(dnsnames->pool,
+                                              sizeof(x509_buf));
+              dnsname->tag = ASN1_IA5_STRING; /* implicit based on dNSName */
+              dnsname->len = len;
+              dnsname->p = *p;
+              APR_ARRAY_PUSH(dnsnames, x509_buf *) = dnsname;
+            }
+
+          *p += len;
+        }
+
+    }
 
   return SVN_NO_ERROR;
 }
@@ -753,6 +853,88 @@ x509parse_dn_gets(svn_stringbuf_t *buf, 
   }
 }
 
+static svn_boolean_t
+is_hostname(svn_string_t *str)
+{
+  int i;
+
+  for (i = 0; i < str->len; i++)
+    {
+      char c = str->data[i];
+
+      /* '-' is only legal when not at the start or end of a label */
+      if (c == '-')
+        {
+          if (i + 1 != str->len)
+            if (str->data[i + 1] == '.')
+              return FALSE; /* '-' preceeds a '.' */
+          else
+            return FALSE; /* '-' is at end of string */
+
+          /* determine the previous character. */
+          if (i == 0)
+            return FALSE; /* '-' is at start of string */
+          else
+            if (str->data[i - 1] == '.')
+              return FALSE; /* '-' follows a '.' */
+        }
+      else if (c != '*' && c != '.' && !svn_ctype_isalnum(c))
+        return FALSE; /* some character not allowed */
+    }
+
+  return TRUE;
+}
+
+static void
+x509parse_get_hostnames(svn_stringbuf_t *buf, x509_cert *crt,
+                        apr_pool_t *scratch_pool)
+{
+  if (crt->dnsnames->nelts > 0)
+    {
+      int i;
+
+      /* Subject Alt Names take priority */
+      for (i = 0; i < crt->dnsnames->nelts; i++)
+        {
+          x509_buf *dnsname = APR_ARRAY_IDX(crt->dnsnames, i, x509_buf *);
+          const svn_string_t *temp = svn_string_ncreate((const char *)dnsname->p,
+                                                        dnsname->len,
+                                                        scratch_pool);
+
+          if (i > 0)
+            svn_stringbuf_appendcstr(buf, ", ");
+
+          temp = fuzzy_escape(temp, scratch_pool);
+          svn_stringbuf_appendbytes(buf, temp->data, temp->len);
+        }
+    }
+  else
+    {
+      const x509_name *name = &crt->subject;
+      const svn_string_t *utf8_value = NULL;
+
+      /* no SAN then get the hostname from the CommonName on the cert */
+      while (name != NULL)
+        {
+          if (memcmp(name->oid.p, OID_X520, 2) == 0)
+            {
+              if (name->oid.p[2] == X520_COMMON_NAME)
+                {
+                  utf8_value = x509name_to_utf8_string(name, scratch_pool);
+                  if (is_hostname(utf8_value))
+                    break;
+                  else
+                    utf8_value = NULL;
+                }
+            }
+          name = name->next;
+        }
+
+      if (utf8_value)
+        svn_stringbuf_appendbytes(buf, utf8_value->data, utf8_value->len);
+    }
+}
+
 /*
  * Parse one certificate.
  */
@@ -768,7 +950,7 @@ svn_x509_parse_cert(apr_hash_t **certinf
   const unsigned char *p;
   const unsigned char *end;
   x509_cert *crt;
-  svn_stringbuf_t *issuer, *subject;
+  svn_stringbuf_t *issuer, *subject, *hostnames;
   svn_checksum_t *sha1_digest;
 
   crt = apr_pcalloc(scratch_pool, sizeof(*crt));
@@ -874,7 +1056,8 @@ svn_x509_parse_cert(apr_hash_t **certinf
   }
 
   if (crt->version == 3) {
-    SVN_ERR(x509_skip_ext(&p, end));
+    crt->dnsnames = apr_array_make(scratch_pool, 3, sizeof(x509_buf *));
+    SVN_ERR(x509_get_ext(crt->dnsnames, &p, end));
   }
 
   if (p != end) {
@@ -912,6 +1095,11 @@ svn_x509_parse_cert(apr_hash_t **certinf
   x509parse_dn_gets(issuer, &crt->issuer, scratch_pool);
   svn_hash_sets(*certinfo, SVN_X509_CERTINFO_KEY_ISSUER, issuer->data);
 
+  hostnames = svn_stringbuf_create_empty(result_pool);
+  x509parse_get_hostnames(hostnames, crt, scratch_pool);
+  if (!svn_stringbuf_isempty(hostnames))
+    svn_hash_sets(*certinfo, SVN_X509_CERTINFO_KEY_HOSTNAMES, hostnames->data);
+
   svn_hash_sets(*certinfo, SVN_X509_CERTINFO_KEY_VALID_FROM,
                 svn_time_to_human_cstring(crt->valid_from, result_pool));
 

Modified: subversion/branches/svn-auth-x509/subversion/svn/auth-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/svn/auth-cmd.c?rev=1613529&r1=1613528&r2=1613529&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/svn/auth-cmd.c (original)
+++ subversion/branches/svn-auth-x509/subversion/svn/auth-cmd.c Fri Jul 25 22:45:46 2014
@@ -174,6 +174,7 @@ show_cert(const svn_string_t *pem_cert, 
 {
   const svn_string_t *der_cert;
   apr_hash_t *certinfo;
+  const char *v;
 
   /* Convert header-less PEM to DER by undoing base64 encoding. */
   der_cert = svn_base64_decode_string(pem_cert, scratch_pool);
@@ -196,6 +197,10 @@ show_cert(const svn_string_t *pem_cert, 
   SVN_ERR(svn_cmdline_printf(scratch_pool, _("Fingerprint: %s\n"),
                              (const char *)svn_hash_gets(certinfo,
                                              SVN_X509_CERTINFO_KEY_SHA1_DIGEST)));
+  v = svn_hash_gets(certinfo, SVN_X509_CERTINFO_KEY_HOSTNAMES);
+  if (v)
+    SVN_ERR(svn_cmdline_printf(scratch_pool, _("Hostnames: %s\n"), v));
+
 #if 0
   SVN_ERR(svn_cmdline_printf(scratch_pool, _("Subject: %s\n"), cert->subject_id.p));
   SVN_ERR(svn_cmdline_printf(iterpool, _("Issuer: %s\n"), value->data));
@@ -257,9 +262,9 @@ list_credential(const char *cred_kind,
         SVN_ERR(svn_cmdline_printf(iterpool, _("Username: %s\n"), value->data));
       else if (strcmp(key, SVN_CONFIG_AUTHN_ASCII_CERT_KEY) == 0)
        SVN_ERR(show_cert(value, iterpool));
+#if 0
       else if (strcmp(key, SVN_CONFIG_AUTHN_HOSTNAME_KEY) == 0)
         SVN_ERR(svn_cmdline_printf(iterpool, _("Hostname: %s\n"), value->data));
-#if 0
       else if (strcmp(key, SVN_CONFIG_AUTHN_VALID_FROM_KEY) == 0)
         SVN_ERR(svn_cmdline_printf(iterpool, _("Valid from: %s\n"),
                                    value->data));

Modified: subversion/branches/svn-auth-x509/subversion/tests/libsvn_subr/x509-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/tests/libsvn_subr/x509-test.c?rev=1613529&r1=1613528&r2=1613529&view=diff
==============================================================================
--- subversion/branches/svn-auth-x509/subversion/tests/libsvn_subr/x509-test.c (original)
+++ subversion/branches/svn-auth-x509/subversion/tests/libsvn_subr/x509-test.c Fri Jul 25
22:45:46 2014
@@ -42,6 +42,7 @@ struct x509_test {
    * timezone.  So we can't store exactly what the parser will output. */
   const char *valid_from;
   const char *valid_to;
+  const char *hostnames;
   const char *sha1_digest;
 };
 
@@ -78,6 +79,7 @@ static struct x509_test cert_tests[] = {
     "C=US, O=Thawte, Inc., CN=Thawte SSL CA",
     "2014-04-11T00:00:00.000000Z",
     "2016-04-07T23:59:59.000000Z",
+    "*.apache.org",
     "151d8ad1e1bac21466bc2836ba80b5fcf872f37c" },
   /* the expiration is after 2049 so the expiration is in the
    * generalized format, while the start date is still in the UTC
@@ -107,6 +109,7 @@ static struct x509_test cert_tests[] = {
     "C=AU, ST=Some-State, O=Internet Widgits Pty Ltd",
     "2014-06-27T17:31:51.000000Z",
     "2114-06-03T17:31:51.000000Z",
+    NULL,
     "db3a959e145acc2741f9eeecbeabce53cc5b7362" },
   /* The subject (except for country code) is UTF-8 encoded.
    * created with openssl using utf8-yes and string_mask=utf8only */
@@ -137,6 +140,7 @@ static struct x509_test cert_tests[] = {
     "C=AU, ST=Some-State, O=Internet Widgits Pty Ltd",
     "2014-07-02T18:36:10.000000Z",
     "2015-07-02T18:36:10.000000Z",
+    "www.example.com",
     "b3b9789d8a53868f418619565f6b56af0033bdd3" },
   /* The issuer and subject (except for the country code) is
    * UnversalString encoded.  Created with a hacked version of openssl
@@ -185,6 +189,7 @@ static struct x509_test cert_tests[] = {
     "C=AU, ST=Some-State, O=Internet Widgits Pty Ltd",
     "2014-07-22T22:37:30.000000Z",
     "2015-07-22T22:37:30.000000Z",
+    "www.example.com",
     "cfa15310189cf89f1dadc9c989db46f287fff7a7"
   },
   /* The issuer and subject (except for the country code) is BMPString
@@ -218,6 +223,7 @@ static struct x509_test cert_tests[] = {
     "C=AU, ST=Some-State, O=Internet Widgits Pty Ltd",
     "2014-07-22T23:02:09.000000Z",
     "2015-07-22T23:02:09.000000Z",
+    "www.example.com",
     "6e2cd969350979d3741b9abb66c71159a94ff971"
   },
   /* The issuer and subject (except for the country code) is T61String
@@ -253,8 +259,107 @@ static struct x509_test cert_tests[] = {
     "C=AU, ST=Some-State, O=Internet Widgits Pty Ltd",
     "2014-07-22T23:44:18.000000Z",
     "2015-07-22T23:44:18.000000Z",
+    "www.example.com",
     "787d1577ae77b79649d8f99cf4ed58a332dc48da"
   },
+  /* Certificate with several Subject Alt Name dNSNames.  Note that
+   * the CommonName is not duplicated in the Subject Alt Name to
+   * test that the Common Name is excluded when Subject Alt Name
+   * exists. */
+  { "MIIEMTCCAxmgAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJBVTET"
+    "MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ"
+    "dHkgTHRkMRwwGgYDVQQDExNJbnRlcm5ldCBXaWRnaXRzIENBMB4XDTE0MDcyNTE3"
+    "NDEwNFoXDTE1MDcyNTE3NDEwNFowdDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh"
+    "c2hpbmd0b24xEzARBgNVBAcTCk5vcnRoIEJlbmQxITAfBgNVBAoTGEludGVybmV0"
+    "IFdpZGdpdHMgUHR5IEx0ZDEYMBYGA1UEAxMPd3d3LmV4YW1wbGUuY29tMIIBIjAN"
+    "BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxlryoK6hMhGI/UlHi7v1m+Z3tCvg"
+    "ZG1twDFNvBACpFVbJtC/v+fiy1eG7ooZ1PsdCINQ1iXLh1igevlw/4w6iTDpeSZg"
+    "OCPYqK6ejnS0bKtSB4TuP8yiQtqwaVz4yPP88lXuQJDRJzgaAR0VAhooLgEpl1z1"
+    "n9wQO15AW5swzpKcEOi4n6Zmf1t7oxOt9awAOhkL1FfFwkpbiK9yQv3TPVo+xzbx"
+    "BJxwx55RY8Dpiu0kuiTYWsd02pocb0uIqd7a5B4y05PhJseqwyX0Mw57HBBnbru1"
+    "lCetP4PkoM2gf7Uoj9e61nmM1mustKTIPvh7tZHWW3UW9JxAFG+6FkKDewIDAQAB"
+    "o4HeMIHbMAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJh"
+    "dGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBQ4A9k8VwI0wv7u5rB4+1D9cuHiqTAf"
+    "BgNVHSMEGDAWgBS6O+MdRDDrD715AXdrnuNZ7wDSyjALBgNVHQ8EBAMCBeAwUwYD"
+    "VR0RBEwwSoINKi5leGFtcGxlLmNvbYIRKi5mb28uZXhhbXBsZS5jb22CESouYmFy"
+    "LmV4YW1wbGUuY29tghN6aWctemFnLmV4YW1wbGUuY29tMA0GCSqGSIb3DQEBBQUA"
+    "A4IBAQAf4IrSOL741IUkyFQrDdof39Cp87VdNEo4Bl8fUSuCjqZONxJfiAFx7GcB"
+    "Cd7h7Toe6CYCeQLHSEXQ1S1eWYLIq0ZoP3Q/huJdoH7yskDyC5Faexph0obKM5hj"
+    "+EYGW2W/UYBzEZai+eePBovARDlupiMaTJGvtdU/AcgMhXCoGNK6egesXoiNgfFh"
+    "h+lXUNWUWm2gZlKwRJff8tkR7bIG7MGzyL6Rqav2/tQdbFVXN5AFPdYPFLf0Vo5m"
+    "eGYM87TILfSo7n7Kh0aZovwcuF/vPUWRJl3B1HaPt9k6DhcFyAji0SJyZWyM4v88"
+    "GSq5Dk8dnTdL2otToll+r4IqFLlp",
+    "C=US, ST=Washington, L=North Bend, O=Internet Widgits Pty Ltd, "
+    "CN=www.example.com",
+    "C=AU, ST=Some-State, O=Internet Widgits Pty Ltd, CN=Internet Widgits CA",
+    "2014-07-25T17:41:04.000000Z",
+    "2015-07-25T17:41:04.000000Z",
+    "*.example.com, *.foo.example.com, *.bar.example.com, zig-zag.example.com",
+    "9c365d27b7b6cc438576a8e465685ea7a4f61129"
+  },
+  /* This is a CA cert that has a Common Name that doesn't look like
+   * a hostname.  Make sure that the hostnames field remains blank for it. */
+  { "MIIEEjCCAvqgAwIBAgIJAKJarRWbvbCjMA0GCSqGSIb3DQEBBQUAMGMxCzAJBgNV"
+    "BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX"
+    "aWRnaXRzIFB0eSBMdGQxHDAaBgNVBAMTE0ludGVybmV0IFdpZGdpdHMgQ0EwHhcN"
+    "MTQwNzI1MTc0MTAzWhcNMjQwNzIyMTc0MTAzWjBjMQswCQYDVQQGEwJBVTETMBEG"
+    "A1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkg"
+    "THRkMRwwGgYDVQQDExNJbnRlcm5ldCBXaWRnaXRzIENBMIIBIjANBgkqhkiG9w0B"
+    "AQEFAAOCAQ8AMIIBCgKCAQEAv0f0TAiE13WHaFv8j6M9uuniO40+Aj8cuhZtJ1GC"
+    "GI/mW56wq2BJrP6N4+jyxYbZ/13S3ypPu+N087Nc/4xaPtUD/eKqMlU+o8gHM/Lf"
+    "BEs2dUuBsvkNM0KoC04NPNTOYDnfHOrzx8iHhqlDedwmP8FeQn3rNS8k4qDyJpG3"
+    "Ay8ICz5mB07Cy6NISohTxMtatfW5yKmhnhiS92X42QAEgI1pGB7jJl1g3u+KY1Bf"
+    "/10kcramYSYIM1uB7XHQjZI4bhEhQwuIWePMOSCOykdmbemM3ijF9f531Olq+0Nz"
+    "t7lA1b/aW4PGGJsZ6uIIjKMaX4npP+HHUaNGVssgTnTehQIDAQABo4HIMIHFMB0G"
+    "A1UdDgQWBBS6O+MdRDDrD715AXdrnuNZ7wDSyjCBlQYDVR0jBIGNMIGKgBS6O+Md"
+    "RDDrD715AXdrnuNZ7wDSyqFnpGUwYzELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNv"
+    "bWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEcMBoG"
+    "A1UEAxMTSW50ZXJuZXQgV2lkZ2l0cyBDQYIJAKJarRWbvbCjMAwGA1UdEwQFMAMB"
+    "Af8wDQYJKoZIhvcNAQEFBQADggEBAI442H8CpePFvOtdvcosu2N8juJrzACuayDI"
+    "Ze32EtHFN611azduqkWBgMJ3Fv74o0A7u5Gl8A7RZnfBTMX7cvpfHvWefau0xqgm"
+    "Mn8CcTUGel0qudCCMe+kPppmkgNaZFvawSqcAA/u2yni2yx8BakYYDZzyfmEf9dm"
+    "hZi5SmxFFba5UhNKOye0GKctT13s/7EgfFNyVhZA7hWU26Xm88QnGnN/qxJdpq+e"
+    "+Glctn9tyke4b1VZ2Yr+R4OktrId44ZQcRD44+88v5ThP8DQsvkXcjREMFAIPkvG"
+    "CEDOIem4l9KFfnsHn8/4KvoBRkmCkGaSwOwUdUG+jIjBpY/82kM=",
+    "C=AU, ST=Some-State, O=Internet Widgits Pty Ltd, CN=Internet Widgits CA",
+    "C=AU, ST=Some-State, O=Internet Widgits Pty Ltd, CN=Internet Widgits CA",
+    "2014-07-25T17:41:03.000000Z",
+    "2024-07-22T17:41:03.000000Z",
+    NULL,
+    "b9decce236aa1da07b2bf088160bffe1469b9a4a"
+  },
+  /* Cert with a IP SAN entry.  Make sure we properly skip them. */
+  { "MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJBVTET"
+    "MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ"
+    "dHkgTHRkMRwwGgYDVQQDExNJbnRlcm5ldCBXaWRnaXRzIENBMB4XDTE0MDcyNTE4"
+    "NDMyOFoXDTE1MDcyNTE4NDMyOFowczELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh"
+    "c2hpbmd0b24xEzARBgNVBAcTCk5vcnRoIEJlbmQxITAfBgNVBAoTGEludGVybmV0"
+    "IFdpZGdpdHMgUHR5IEx0ZDEXMBUGA1UEAxMOaXAuZXhhbXBsZS5jb20wggEiMA0G"
+    "CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDXKkSxg89tu5/n+lIC8ajj1T9vsO5B"
+    "nRH5Sne7UPc6pGMTNFi1MOVjdDWkmuCUzoI+HKLDc69/4V5RU12N1QNgsgcOzCSo"
+    "qgxa+dQk2s1shz1zhyaHkpdeMZU3/p9D4v+nRGAdYifwl/VOTwjWWucNzHDBwvb6"
+    "+Wm4pXE94Y5p8fY/lZi7VgtxdoPdSHGkIAps8psZGPjqKpLEjnLMp1n0v9cZhBF6"
+    "OoMUZpQuwcjT8vMQppgIWhZFLiH2jn7FTYWZyB0Dh9nMd097NQA87VtVfNc+g0oY"
+    "qLe3YldJgvVfyeSLhnyv68fBfGcTj310pNrGeE/m4tyxupiUT8BitfxPAgMBAAGj"
+    "geQwgeEwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0"
+    "ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFI09JZlhKV44Z+I5d58V/ZDqQ7yZMB8G"
+    "A1UdIwQYMBaAFDjQVnIU9pQI1nM8jjmxYiicMTdGMAsGA1UdDwQEAwIF4DBZBgNV"
+    "HREEUjBQgg0qLmV4YW1wbGUuY29tghEqLmZvby5leGFtcGxlLmNvbYcEfwAAAYIR"
+    "Ki5iYXIuZXhhbXBsZS5jb22CE3ppZy16YWcuZXhhbXBsZS5jb20wDQYJKoZIhvcN"
+    "AQEFBQADggEBAEK+XIGwavf+5Ht44ifHrGog0CDr4ESg7wFjzk+BJwYDtIPp9b8A"
+    "EG8qbfmOS+2trG3zc74baf2rmrfn0YGZ/GV826NMTaf7YU1/tJQTo+RX9g3aHg6f"
+    "pUBfIyAV8ELq84sgwd1PIgleVgIiDrz+a0UZ05Z5S+GbR2pwNH6+fO0O5E9clt2a"
+    "Cute1UMBqAMGKiFaP8HD6SUFTdTKZNxHtQzYmmuvoC1nzVatMFdkTuQgSQ/uNlzg"
+    "+yUFoufMZhs3gPx9PfXGOQ7f3nKE+WCK4KNGv+OILYsk4zUjMznfAwBRs9PyITN2"
+    "BKe64WsF6ZxTq3zLVGy5I8LpbtlvSmAaBp4=",
+    "C=US, ST=Washington, L=North Bend, O=Internet Widgits Pty Ltd, "
+    "CN=ip.example.com",
+    "C=AU, ST=Some-State, O=Internet Widgits Pty Ltd, CN=Internet Widgits CA",
+    "2014-07-25T18:43:28.000000Z",
+    "2015-07-25T18:43:28.000000Z",
+    "*.example.com, *.foo.example.com, *.bar.example.com, zig-zag.example.com",
+    "3525fb617c232fdc738d736c1cbd5d97b19b51e4"
+  },
   { NULL }
 };
 
@@ -333,6 +438,17 @@ compare_results(struct x509_test *xt,
                         xt->subject,
                         pool));
 
+  v = svn_hash_gets(certinfo, SVN_X509_CERTINFO_KEY_HOSTNAMES);
+  if (!v != !xt->hostnames || (v && strcmp(v, xt->hostnames)))
+    {
+      /* both should have a value or neither should have a value and
+       * if they have a value they should match. */
+      return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+                               "Hostnames didn't match for cert '%s', "
+                               "expected '%s', got '%s'", xt->subject,
+                               xt->hostnames, v);
+    }
+
   v = svn_hash_gets(certinfo, SVN_X509_CERTINFO_KEY_SHA1_DIGEST);
   if (!v)
     return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,



Mime
View raw message