Rewrite X.509 name-matching tests.

This replaces v3name_test.cc which is rather difficult to follow.
v3name_test.cc ran all pairs of names against each other, used a
default case-insensitivity rule, and then had a list of string
exceptions to that rule. This is hopefully easier for us to adjust
later. It also fixes a testing bug we wouldn't notice if an expected
"exception" didn't fire.

Sadly, we cannot use designated initializers in C++ yet. MSVC does not
support them until MSVC 2019.

Change-Id: Ia8e3bf5f57d33a9bf1fc929ba1e8cd2a270a8a24
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50725
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
diff --git a/crypto/CMakeLists.txt b/crypto/CMakeLists.txt
index 9c724b7..d73ce1e 100644
--- a/crypto/CMakeLists.txt
+++ b/crypto/CMakeLists.txt
@@ -552,7 +552,6 @@
   x509/x509_test.cc
   x509/x509_time_test.cc
   x509v3/tab_test.cc
-  x509v3/v3name_test.cc
 
   $<TARGET_OBJECTS:crypto_test_data>
   $<TARGET_OBJECTS:boringssl_gtest_main>
diff --git a/crypto/x509/x509_test.cc b/crypto/x509/x509_test.cc
index 77c383a..01f0bc7 100644
--- a/crypto/x509/x509_test.cc
+++ b/crypto/x509/x509_test.cc
@@ -3533,3 +3533,324 @@
   // Padding bits in BIT STRINGs must be zero in BER.
   EXPECT_FALSE(CertFromPEM(kNonZeroPadding));
 }
+
+TEST(X509Test, Names) {
+  bssl::UniquePtr<EVP_PKEY> key = PrivateKeyFromPEM(kP256Key);
+  ASSERT_TRUE(key);
+  bssl::UniquePtr<X509> root =
+      MakeTestCert("Root", "Root", key.get(), /*is_ca=*/true);
+  ASSERT_TRUE(root);
+  ASSERT_TRUE(X509_sign(root.get(), key.get(), EVP_sha256()));
+
+  struct {
+    std::vector<std::pair<int, std::string>> cert_subject;
+    std::vector<std::string> cert_dns_names;
+    std::vector<std::string> cert_emails;
+    std::vector<std::string> valid_dns_names;
+    std::vector<std::string> invalid_dns_names;
+    std::vector<std::string> valid_emails;
+    std::vector<std::string> invalid_emails;
+    unsigned flags;
+  } kTests[] = {
+      // DNS names only match DNS names and do so case-insensitively.
+      {
+          /*cert_subject=*/{},
+          /*cert_dns_names=*/{"example.com", "WWW.EXAMPLE.COM"},
+          /*cert_emails=*/{},
+          /*valid_dns_names=*/
+          {"example.com", "EXAMPLE.COM", "www.example.com", "WWW.EXAMPLE.COM"},
+          /*invalid_dns_names=*/{"test.example.com", "example.org"},
+          /*valid_emails=*/{},
+          /*invalid_emails=*/{"test@example.com", "example.com"},
+          /*flags=*/0,
+      },
+
+      // DNS wildcards match exactly one component.
+      {
+          /*cert_subject=*/{},
+          /*cert_dns_names=*/{"*.example.com", "*.EXAMPLE.ORG"},
+          /*cert_emails=*/{},
+          /*valid_dns_names=*/
+          {"www.example.com", "WWW.EXAMPLE.COM", "www.example.org",
+           "WWW.EXAMPLE.ORG"},
+          /*invalid_dns_names=*/{"example.com", "test.www.example.com"},
+          /*valid_emails=*/{},
+          /*invalid_emails=*/{"test@example.com", "www.example.com"},
+          /*flags=*/0,
+      },
+
+      // DNS wildcards can be disabled.
+      // TODO(davidben): Can we remove this feature? Does anyone use it?
+      {
+          /*cert_subject=*/{},
+          /*cert_dns_names=*/{"example.com", "*.example.com"},
+          /*cert_emails=*/{},
+          /*valid_dns_names=*/{"example.com"},
+          /*invalid_dns_names=*/{"www.example.com"},
+          /*valid_emails=*/{},
+          /*invalid_emails=*/{},
+          /*flags=*/X509_CHECK_FLAG_NO_WILDCARDS,
+      },
+
+      // Invalid DNS wildcards do not match.
+      {
+          /*cert_subject=*/{},
+          /*cert_dns_names=*/
+          {"a.*", "**.b.example", "*c.example", "d*.example", "e*e.example",
+           "*", ".", "..", "*."},
+          /*cert_emails=*/{},
+          /*valid_dns_names=*/{},
+          /*invalid_dns_names=*/
+          {"a.example", "test.b.example", "cc.example", "dd.example",
+           "eee.example", "f", "g."},
+          /*valid_emails=*/{},
+          /*invalid_emails=*/{},
+          /*flags=*/0,
+      },
+
+      // IDNs match like any other DNS labels.
+      {
+          /*cert_subject=*/{},
+          /*cert_dns_names=*/
+          {"xn--rger-koa.a.example", "*.xn--rger-koa.b.example",
+           "www.xn--rger-koa.c.example"},
+          /*cert_emails=*/{},
+          /*valid_dns_names=*/
+          {"xn--rger-koa.a.example", "www.xn--rger-koa.b.example",
+           "www.xn--rger-koa.c.example"},
+          /*invalid_dns_names=*/
+          {"www.xn--rger-koa.a.example", "xn--rger-koa.b.example",
+           "www.xn--rger-koa.d.example"},
+          /*valid_emails=*/{},
+          /*invalid_emails=*/{},
+          /*flags=*/0,
+      },
+
+      // For now, DNS names are also extracted out of the common name, but only
+      // there is no SAN list.
+      // TODO(https://crbug.com/boringssl/464): Remove this.
+      {
+          /*cert_subject=*/{{NID_commonName, "a.example"},
+                            {NID_commonName, "*.b.example"}},
+          /*cert_dns_names=*/{},
+          /*cert_emails=*/{},
+          /*valid_dns_names=*/
+          {"a.example", "A.EXAMPLE", "test.b.example", "TEST.B.EXAMPLE"},
+          /*invalid_dns_names=*/{},
+          /*valid_emails=*/{},
+          /*invalid_emails=*/{},
+          /*flags=*/0,
+      },
+      {
+          /*cert_subject=*/{{NID_commonName, "a.example"},
+                            {NID_commonName, "*.b.example"}},
+          /*cert_dns_names=*/{"example.com"},
+          /*cert_emails=*/{},
+          /*valid_dns_names=*/{},
+          /*invalid_dns_names=*/
+          {"a.example", "A.EXAMPLE", "test.b.example", "TEST.B.EXAMPLE"},
+          /*valid_emails=*/{},
+          /*invalid_emails=*/{},
+          /*flags=*/0,
+      },
+
+      // Other subject RDNs do not provide DNS names.
+      {
+          /*cert_subject=*/{{NID_organizationName, "example.com"}},
+          /*cert_dns_names=*/{},
+          /*cert_emails=*/{},
+          /*valid_dns_names=*/{},
+          /*invalid_dns_names=*/{"example.com"},
+          /*valid_emails=*/{},
+          /*invalid_emails=*/{},
+          /*flags=*/0,
+      },
+
+      // Input DNS names cannot have wildcards.
+      {
+          /*cert_subject=*/{},
+          /*cert_dns_names=*/{"www.example.com"},
+          /*cert_emails=*/{},
+          /*valid_dns_names=*/{},
+          /*invalid_dns_names=*/{"*.example.com"},
+          /*valid_emails=*/{},
+          /*invalid_emails=*/{},
+          /*flags=*/0,
+      },
+
+      // However, OpenSSL has some non-standard behavior that implements this
+      // with a different syntax.
+      // TODO(https://crbug.com/boringssl/463): Remove this.
+      {
+          /*cert_subject=*/{},
+          /*cert_dns_names=*/{"www.a.example", "*.b.test"},
+          /*cert_emails=*/{},
+          /*valid_dns_names=*/{".a.example", ".b.test", ".example", ".test"},
+          /*invalid_dns_names=*/{".www.a.example", ".www.b.test"},
+          /*valid_emails=*/{},
+          /*invalid_emails=*/{},
+          /*flags=*/0,
+      },
+
+      // Emails match case-sensitively before the '@' and case-insensitively
+      // after. They do not match DNS names.
+      {
+          /*cert_subject=*/{},
+          /*cert_dns_names=*/{},
+          /*cert_emails=*/{"test@a.example", "TEST@B.EXAMPLE"},
+          /*valid_dns_names=*/{},
+          /*invalid_dns_names=*/{"a.example", "b.example"},
+          /*valid_emails=*/
+          {"test@a.example", "test@A.EXAMPLE", "TEST@b.example",
+           "TEST@B.EXAMPLE"},
+          /*invalid_emails=*/
+          {"TEST@a.example", "test@B.EXAMPLE", "another-test@a.example",
+           "est@a.example"},
+          /*flags=*/0,
+      },
+
+      // Emails may also be found in the subject.
+      {
+          /*cert_subject=*/{{NID_pkcs9_emailAddress, "test@a.example"},
+                            {NID_pkcs9_emailAddress, "TEST@B.EXAMPLE"}},
+          /*cert_dns_names=*/{},
+          /*cert_emails=*/{},
+          /*valid_dns_names=*/{},
+          /*invalid_dns_names=*/{"a.example", "b.example"},
+          /*valid_emails=*/
+          {"test@a.example", "test@A.EXAMPLE", "TEST@b.example",
+           "TEST@B.EXAMPLE"},
+          /*invalid_emails=*/
+          {"TEST@a.example", "test@B.EXAMPLE", "another-test@a.example",
+           "est@a.example"},
+          /*flags=*/0,
+      },
+
+      // There are no email wildcard names.
+      {
+          /*cert_subject=*/{},
+          /*cert_dns_names=*/{},
+          /*cert_emails=*/{"test@*.a.example", "@b.example", "*@c.example"},
+          /*valid_dns_names=*/{},
+          /*invalid_dns_names=*/{},
+          /*valid_emails=*/{},
+          /*invalid_emails=*/
+          {"test@test.a.example", "test@b.example", "test@c.example"},
+          /*flags=*/0,
+      },
+
+      // Unrelated RDNs can be skipped when looking in the subject.
+      {
+          /*cert_subject=*/{{NID_organizationName, "Acme Corporation"},
+                            {NID_commonName, "a.example"},
+                            {NID_pkcs9_emailAddress, "test@b.example"},
+                            {NID_countryName, "US"}},
+          /*cert_dns_names=*/{},
+          /*cert_emails=*/{},
+          /*valid_dns_names=*/{"a.example"},
+          /*invalid_dns_names=*/{},
+          /*valid_emails=*/{"test@b.example"},
+          /*invalid_emails=*/{},
+          /*flags=*/0,
+      },
+  };
+
+  size_t i = 0;
+  for (const auto &t : kTests) {
+    SCOPED_TRACE(i++);
+
+    // Issue a test certificate.
+    bssl::UniquePtr<X509> cert =
+        MakeTestCert("Root", "Leaf", key.get(), /*is_ca=*/false);
+    ASSERT_TRUE(cert);
+    if (!t.cert_subject.empty()) {
+      bssl::UniquePtr<X509_NAME> subject(X509_NAME_new());
+      ASSERT_TRUE(subject);
+      for (const auto &entry : t.cert_subject) {
+        ASSERT_TRUE(X509_NAME_add_entry_by_NID(
+            subject.get(), entry.first, MBSTRING_ASC,
+            reinterpret_cast<const unsigned char *>(entry.second.data()),
+            entry.second.size(), /*loc=*/-1, /*set=*/0));
+      }
+      ASSERT_TRUE(X509_set_subject_name(cert.get(), subject.get()));
+    }
+    bssl::UniquePtr<GENERAL_NAMES> sans(sk_GENERAL_NAME_new_null());
+    ASSERT_TRUE(sans);
+    for (const auto &dns : t.cert_dns_names) {
+      bssl::UniquePtr<GENERAL_NAME> name(GENERAL_NAME_new());
+      ASSERT_TRUE(name);
+      name->type = GEN_DNS;
+      name->d.dNSName = ASN1_IA5STRING_new();
+      ASSERT_TRUE(name->d.dNSName);
+      ASSERT_TRUE(ASN1_STRING_set(name->d.dNSName, dns.data(), dns.size()));
+      ASSERT_TRUE(bssl::PushToStack(sans.get(), std::move(name)));
+    }
+    for (const auto &email : t.cert_emails) {
+      bssl::UniquePtr<GENERAL_NAME> name(GENERAL_NAME_new());
+      ASSERT_TRUE(name);
+      name->type = GEN_EMAIL;
+      name->d.rfc822Name = ASN1_IA5STRING_new();
+      ASSERT_TRUE(name->d.rfc822Name);
+      ASSERT_TRUE(
+          ASN1_STRING_set(name->d.rfc822Name, email.data(), email.size()));
+      ASSERT_TRUE(bssl::PushToStack(sans.get(), std::move(name)));
+    }
+    if (sk_GENERAL_NAME_num(sans.get()) != 0) {
+      ASSERT_TRUE(X509_add1_ext_i2d(cert.get(), NID_subject_alt_name,
+                                    sans.get(), /*crit=*/0, /*flags=*/0));
+    }
+    ASSERT_TRUE(X509_sign(cert.get(), key.get(), EVP_sha256()));
+
+    for (const auto &dns : t.valid_dns_names) {
+      SCOPED_TRACE(dns);
+      EXPECT_EQ(1, X509_check_host(cert.get(), dns.data(), dns.size(), t.flags,
+                                   /*peername=*/nullptr));
+      EXPECT_EQ(X509_V_OK,
+                Verify(cert.get(), {root.get()}, /*intermediates=*/{},
+                       /*crls=*/{}, /*flags=*/0, [&](X509_VERIFY_PARAM *param) {
+                         ASSERT_TRUE(X509_VERIFY_PARAM_set1_host(
+                             param, dns.data(), dns.size()));
+                         X509_VERIFY_PARAM_set_hostflags(param, t.flags);
+                       }));
+    }
+
+    for (const auto &dns : t.invalid_dns_names) {
+      SCOPED_TRACE(dns);
+      EXPECT_EQ(0, X509_check_host(cert.get(), dns.data(), dns.size(), t.flags,
+                                   /*peername=*/nullptr));
+      EXPECT_EQ(X509_V_ERR_HOSTNAME_MISMATCH,
+                Verify(cert.get(), {root.get()}, /*intermediates=*/{},
+                       /*crls=*/{}, /*flags=*/0, [&](X509_VERIFY_PARAM *param) {
+                         ASSERT_TRUE(X509_VERIFY_PARAM_set1_host(
+                             param, dns.data(), dns.size()));
+                         X509_VERIFY_PARAM_set_hostflags(param, t.flags);
+                       }));
+    }
+
+    for (const auto &email : t.valid_emails) {
+      SCOPED_TRACE(email);
+      EXPECT_EQ(
+          1, X509_check_email(cert.get(), email.data(), email.size(), t.flags));
+      EXPECT_EQ(X509_V_OK,
+                Verify(cert.get(), {root.get()}, /*intermediates=*/{},
+                       /*crls=*/{}, /*flags=*/0, [&](X509_VERIFY_PARAM *param) {
+                         ASSERT_TRUE(X509_VERIFY_PARAM_set1_email(
+                             param, email.data(), email.size()));
+                         X509_VERIFY_PARAM_set_hostflags(param, t.flags);
+                       }));
+    }
+
+    for (const auto &email : t.invalid_emails) {
+      SCOPED_TRACE(email);
+      EXPECT_EQ(
+          0, X509_check_email(cert.get(), email.data(), email.size(), t.flags));
+      EXPECT_EQ(X509_V_ERR_EMAIL_MISMATCH,
+                Verify(cert.get(), {root.get()}, /*intermediates=*/{},
+                       /*crls=*/{}, /*flags=*/0, [&](X509_VERIFY_PARAM *param) {
+                         ASSERT_TRUE(X509_VERIFY_PARAM_set1_email(
+                             param, email.data(), email.size()));
+                         X509_VERIFY_PARAM_set_hostflags(param, t.flags);
+                       }));
+    }
+  }
+}
diff --git a/crypto/x509v3/v3name_test.cc b/crypto/x509v3/v3name_test.cc
deleted file mode 100644
index a501115..0000000
--- a/crypto/x509v3/v3name_test.cc
+++ /dev/null
@@ -1,413 +0,0 @@
-/*
- * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
- * 1999.
- */
-/* ====================================================================
- * Copyright (c) 1999-2004 The OpenSSL Project.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- *    software must display the following acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- *    endorse or promote products derived from this software without
- *    prior written permission. For written permission, please contact
- *    licensing@OpenSSL.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- *    nor may "OpenSSL" appear in their names without prior written
- *    permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- *    acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com).  This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com). */
-
-#include <stdarg.h>
-#include <string.h>
-
-#include <gtest/gtest.h>
-
-#include <openssl/crypto.h>
-#include <openssl/mem.h>
-#include <openssl/x509.h>
-#include <openssl/x509v3.h>
-
-#include "../internal.h"
-#include "internal.h"
-
-
-static const char *const names[] = {
-    "a", "b", ".", "*", "@",
-    ".a", "a.", ".b", "b.", ".*", "*.", "*@", "@*", "a@", "@a", "b@", "..",
-    "-example.com", "example-.com",
-    "@@", "**", "*.com", "*com", "*.*.com", "*com", "com*", "*example.com",
-    "*@example.com", "test@*.example.com", "example.com", "www.example.com",
-    "test.www.example.com", "*.example.com", "*.www.example.com",
-    "test.*.example.com", "www.*.com",
-    ".www.example.com", "*www.example.com",
-    "example.net", "xn--rger-koa.example.com",
-    "*.xn--rger-koa.example.com", "www.xn--rger-koa.example.com",
-    "*.good--example.com", "www.good--example.com",
-    "*.xn--bar.com", "xn--foo.xn--bar.com",
-    "a.example.com", "b.example.com",
-    "postmaster@example.com", "Postmaster@example.com",
-    "postmaster@EXAMPLE.COM",
-    NULL
-};
-
-static const char *const exceptions[] = {
-    "set CN: host: [*.example.com] matches [a.example.com]",
-    "set CN: host: [*.example.com] matches [b.example.com]",
-    "set CN: host: [*.example.com] matches [www.example.com]",
-    "set CN: host: [*.example.com] matches [xn--rger-koa.example.com]",
-    "set CN: host: [*.www.example.com] matches [test.www.example.com]",
-    "set CN: host: [*.www.example.com] matches [.www.example.com]",
-    "set CN: host: [*www.example.com] matches [www.example.com]",
-    "set CN: host: [test.www.example.com] matches [.www.example.com]",
-    "set CN: host: [*.xn--rger-koa.example.com] matches [www.xn--rger-koa.example.com]",
-    "set CN: host: [*.xn--bar.com] matches [xn--foo.xn--bar.com]",
-    "set CN: host: [*.good--example.com] matches [www.good--example.com]",
-    "set CN: host-no-wildcards: [*.www.example.com] matches [.www.example.com]",
-    "set CN: host-no-wildcards: [test.www.example.com] matches [.www.example.com]",
-    "set emailAddress: email: [postmaster@example.com] does not match [Postmaster@example.com]",
-    "set emailAddress: email: [postmaster@EXAMPLE.COM] does not match [Postmaster@example.com]",
-    "set emailAddress: email: [Postmaster@example.com] does not match [postmaster@example.com]",
-    "set emailAddress: email: [Postmaster@example.com] does not match [postmaster@EXAMPLE.COM]",
-    "set dnsName: host: [*.example.com] matches [www.example.com]",
-    "set dnsName: host: [*.example.com] matches [a.example.com]",
-    "set dnsName: host: [*.example.com] matches [b.example.com]",
-    "set dnsName: host: [*.example.com] matches [xn--rger-koa.example.com]",
-    "set dnsName: host: [*.www.example.com] matches [test.www.example.com]",
-    "set dnsName: host-no-wildcards: [*.www.example.com] matches [.www.example.com]",
-    "set dnsName: host-no-wildcards: [test.www.example.com] matches [.www.example.com]",
-    "set dnsName: host: [*.www.example.com] matches [.www.example.com]",
-    "set dnsName: host: [*www.example.com] matches [www.example.com]",
-    "set dnsName: host: [test.www.example.com] matches [.www.example.com]",
-    "set dnsName: host: [*.xn--rger-koa.example.com] matches [www.xn--rger-koa.example.com]",
-    "set dnsName: host: [*.xn--bar.com] matches [xn--foo.xn--bar.com]",
-    "set dnsName: host: [*.good--example.com] matches [www.good--example.com]",
-    "set rfc822Name: email: [postmaster@example.com] does not match [Postmaster@example.com]",
-    "set rfc822Name: email: [Postmaster@example.com] does not match [postmaster@example.com]",
-    "set rfc822Name: email: [Postmaster@example.com] does not match [postmaster@EXAMPLE.COM]",
-    "set rfc822Name: email: [postmaster@EXAMPLE.COM] does not match [Postmaster@example.com]",
-    NULL
-};
-
-static int is_exception(const char *msg)
-{
-    const char *const *p;
-    for (p = exceptions; *p; ++p)
-        if (strcmp(msg, *p) == 0)
-            return 1;
-    return 0;
-}
-
-static int set_cn(X509 *crt, ...)
-{
-    int ret = 0;
-    X509_NAME *n = NULL;
-    va_list ap;
-    va_start(ap, crt);
-    n = X509_NAME_new();
-    if (n == NULL)
-        goto out;
-    while (1) {
-        int nid;
-        const char *name;
-        nid = va_arg(ap, int);
-        if (nid == 0)
-            break;
-        name = va_arg(ap, const char *);
-        if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_ASC,
-                                        (unsigned char *)name, -1, -1, 1))
-            goto out;
-    }
-    if (!X509_set_subject_name(crt, n))
-        goto out;
-    ret = 1;
- out:
-    X509_NAME_free(n);
-    va_end(ap);
-    return ret;
-}
-
-/*
- * int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc); X509_EXTENSION
- * *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex, int nid, int crit,
- * ASN1_OCTET_STRING *data); int X509_add_ext(X509 *x, X509_EXTENSION *ex,
- * int loc);
- */
-
-static int set_altname(X509 *crt, ...)
-{
-    int ret = 0;
-    GENERAL_NAMES *gens = NULL;
-    GENERAL_NAME *gen = NULL;
-    ASN1_IA5STRING *ia5 = NULL;
-    va_list ap;
-    va_start(ap, crt);
-    gens = sk_GENERAL_NAME_new_null();
-    if (gens == NULL)
-        goto out;
-    while (1) {
-        int type;
-        const char *name;
-        type = va_arg(ap, int);
-        if (type == 0)
-            break;
-        name = va_arg(ap, const char *);
-
-        gen = GENERAL_NAME_new();
-        if (gen == NULL)
-            goto out;
-        ia5 = ASN1_IA5STRING_new();
-        if (ia5 == NULL)
-            goto out;
-        if (!ASN1_STRING_set(ia5, name, -1))
-            goto out;
-        switch (type) {
-        case GEN_EMAIL:
-        case GEN_DNS:
-            GENERAL_NAME_set0_value(gen, type, ia5);
-            ia5 = NULL;
-            break;
-        default:
-            abort();
-        }
-        sk_GENERAL_NAME_push(gens, gen);
-        gen = NULL;
-    }
-    if (!X509_add1_ext_i2d(crt, NID_subject_alt_name, gens, 0, 0))
-        goto out;
-    ret = 1;
- out:
-    ASN1_IA5STRING_free(ia5);
-    GENERAL_NAME_free(gen);
-    GENERAL_NAMES_free(gens);
-    va_end(ap);
-    return ret;
-}
-
-static int set_cn1(X509 *crt, const char *name)
-{
-    return set_cn(crt, NID_commonName, name, 0);
-}
-
-static int set_cn_and_email(X509 *crt, const char *name)
-{
-    return set_cn(crt, NID_commonName, name,
-                  NID_pkcs9_emailAddress, "dummy@example.com", 0);
-}
-
-static int set_cn2(X509 *crt, const char *name)
-{
-    return set_cn(crt, NID_commonName, "dummy value",
-                  NID_commonName, name, 0);
-}
-
-static int set_cn3(X509 *crt, const char *name)
-{
-    return set_cn(crt, NID_commonName, name,
-                  NID_commonName, "dummy value", 0);
-}
-
-static int set_email1(X509 *crt, const char *name)
-{
-    return set_cn(crt, NID_pkcs9_emailAddress, name, 0);
-}
-
-static int set_email2(X509 *crt, const char *name)
-{
-    return set_cn(crt, NID_pkcs9_emailAddress, "dummy@example.com",
-                  NID_pkcs9_emailAddress, name, 0);
-}
-
-static int set_email3(X509 *crt, const char *name)
-{
-    return set_cn(crt, NID_pkcs9_emailAddress, name,
-                  NID_pkcs9_emailAddress, "dummy@example.com", 0);
-}
-
-static int set_email_and_cn(X509 *crt, const char *name)
-{
-    return set_cn(crt, NID_pkcs9_emailAddress, name,
-                  NID_commonName, "www.example.org", 0);
-}
-
-static int set_altname_dns(X509 *crt, const char *name)
-{
-    return set_altname(crt, GEN_DNS, name, 0);
-}
-
-static int set_altname_email(X509 *crt, const char *name)
-{
-    return set_altname(crt, GEN_EMAIL, name, 0);
-}
-
-struct set_name_fn {
-    int (*fn) (X509 *, const char *);
-    const char *name;
-    int host;
-    int email;
-};
-
-static const struct set_name_fn name_fns[] = {
-    {set_cn1, "set CN", 1, 0},
-    {set_cn2, "set CN", 1, 0},
-    {set_cn3, "set CN", 1, 0},
-    {set_cn_and_email, "set CN", 1, 0},
-    {set_email1, "set emailAddress", 0, 1},
-    {set_email2, "set emailAddress", 0, 1},
-    {set_email3, "set emailAddress", 0, 1},
-    {set_email_and_cn, "set emailAddress", 0, 1},
-    {set_altname_dns, "set dnsName", 1, 0},
-    {set_altname_email, "set rfc822Name", 0, 1},
-    {NULL, NULL, 0, 0},
-};
-
-static X509 *make_cert(void)
-{
-    X509 *ret = NULL;
-    X509 *crt = NULL;
-    X509_NAME *issuer = NULL;
-    crt = X509_new();
-    if (crt == NULL)
-        goto out;
-    if (!X509_set_version(crt, X509_VERSION_3))
-        goto out;
-    ret = crt;
-    crt = NULL;
- out:
-    X509_NAME_free(issuer);
-    return ret;
-}
-
-static int errors;
-
-static void check_message(const struct set_name_fn *fn, const char *op,
-                          const char *nameincert, int match, const char *name)
-{
-    char msg[1024];
-    if (match < 0)
-        return;
-    BIO_snprintf(msg, sizeof(msg), "%s: %s: [%s] %s [%s]",
-                 fn->name, op, nameincert,
-                 match ? "matches" : "does not match", name);
-    if (is_exception(msg))
-        return;
-    puts(msg);
-    ++errors;
-}
-
-static void run_cert(X509 *crt, const char *nameincert,
-                     const struct set_name_fn *fn)
-{
-    const char *const *pname = names;
-    while (*pname) {
-        int samename = OPENSSL_strcasecmp(nameincert, *pname) == 0;
-        size_t namelen = strlen(*pname);
-        char *name = (char *)malloc(namelen);
-        int match, ret;
-        OPENSSL_memcpy(name, *pname, namelen);
-
-        ret = X509_check_host(crt, name, namelen, 0, NULL);
-        match = -1;
-        if (ret < 0) {
-            fprintf(stderr, "internal error in X509_check_host\n");
-            ++errors;
-        } else if (fn->host) {
-            if (ret == 1 && !samename)
-                match = 1;
-            if (ret == 0 && samename)
-                match = 0;
-        } else if (ret == 1)
-            match = 1;
-        check_message(fn, "host", nameincert, match, *pname);
-
-        ret = X509_check_host(crt, name, namelen,
-                              X509_CHECK_FLAG_NO_WILDCARDS, NULL);
-        match = -1;
-        if (ret < 0) {
-            fprintf(stderr, "internal error in X509_check_host\n");
-            ++errors;
-        } else if (fn->host) {
-            if (ret == 1 && !samename)
-                match = 1;
-            if (ret == 0 && samename)
-                match = 0;
-        } else if (ret == 1)
-            match = 1;
-        check_message(fn, "host-no-wildcards", nameincert, match, *pname);
-
-        ret = X509_check_email(crt, name, namelen, 0);
-        match = -1;
-        if (fn->email) {
-            if (ret && !samename)
-                match = 1;
-            if (!ret && samename && strchr(nameincert, '@') != NULL)
-                match = 0;
-        } else if (ret)
-            match = 1;
-        check_message(fn, "email", nameincert, match, *pname);
-        ++pname;
-        free(name);
-    }
-}
-
-// TODO(davidben): Convert this test to GTest more thoroughly.
-TEST(X509V3Test, NameTest) {
-    const struct set_name_fn *pfn = name_fns;
-    while (pfn->name) {
-        const char *const *pname = names;
-        while (*pname) {
-            // The common name fallback requires the name look sufficiently
-            // DNS-like.
-            if (strcmp(pfn->name, "set CN") == 0 &&
-                !x509v3_looks_like_dns_name(
-                    reinterpret_cast<const unsigned char*>(*pname),
-                    strlen(*pname))) {
-                ++pname;
-                continue;
-            }
-            bssl::UniquePtr<X509> crt(make_cert());
-            ASSERT_TRUE(crt);
-            ASSERT_TRUE(pfn->fn(crt.get(), *pname));
-            run_cert(crt.get(), *pname, pfn);
-            ++pname;
-        }
-        ++pfn;
-    }
-    EXPECT_EQ(0, errors);
-}