Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(168)

Unified Diff: net/cert/internal/name_constraints_unittest.cc

Issue 1214933009: Class for parsing and evaluating RFC 5280 NameConstraints. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@compare_DN2
Patch Set: review changes for comment #6 Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/cert/internal/name_constraints_unittest.cc
diff --git a/net/cert/internal/name_constraints_unittest.cc b/net/cert/internal/name_constraints_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..a0b4909c26fc0d7add9183dceeb2552edbacfd53
--- /dev/null
+++ b/net/cert/internal/name_constraints_unittest.cc
@@ -0,0 +1,1127 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/cert/internal/name_constraints.h"
+
+#include "net/cert/internal/test_helpers.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace {
+
+::testing::AssertionResult LoadTestData(const char* token,
+ const std::string& basename,
+ std::string* result) {
+ std::string path = "net/data/name_constraints_unittest/" + basename;
+
+ const PemBlockMapping mappings[] = {
+ {token, result},
+ };
+
+ return ReadTestDataFromPemFile(path, mappings);
+}
+
+::testing::AssertionResult LoadTestName(const std::string& basename,
+ std::string* result) {
+ return LoadTestData("NAME", basename, result);
+}
+
+::testing::AssertionResult LoadTestNameConstraint(const std::string& basename,
+ std::string* result) {
+ return LoadTestData("NAME CONSTRAINTS", basename, result);
+}
+
+::testing::AssertionResult LoadTestSubjectAltName(const std::string& basename,
+ std::string* result) {
+ return LoadTestData("SUBJECT ALTERNATIVE NAME", basename, result);
+}
+
+} // namespace
+
+class ParseNameConstraints
+ : public ::testing::TestWithParam<::testing::tuple<bool>> {
+ public:
+ bool is_critical() const { return ::testing::get<0>(GetParam()); }
+};
+
+// Run the tests with the name constraints marked critical and non-critical. For
+// supported name types, the results should be the same for both.
+INSTANTIATE_TEST_CASE_P(InstantiationName,
+ ParseNameConstraints,
+ ::testing::Values(true, false));
+
+TEST_P(ParseNameConstraints, DNSNames) {
+ std::string a;
+ ASSERT_TRUE(LoadTestNameConstraint("dnsname.pem", &a));
+
+ NameConstraints name_constraints;
+ EXPECT_TRUE(name_constraints.Parse(InputFromString(&a), is_critical()));
+
+ EXPECT_TRUE(name_constraints.IsPermittedDNSName("permitted.example.com"));
+ EXPECT_TRUE(name_constraints.IsPermittedDNSName("permitted.example.com."));
+ EXPECT_TRUE(name_constraints.IsPermittedDNSName("a.permitted.example.com"));
+ EXPECT_FALSE(name_constraints.IsPermittedDNSName("apermitted.example.com"));
+ EXPECT_FALSE(name_constraints.IsPermittedDNSName("apermitted.example.com."));
+ EXPECT_TRUE(name_constraints.IsPermittedDNSName("alsopermitted.example.com"));
+ EXPECT_FALSE(
+ name_constraints.IsPermittedDNSName("excluded.permitted.example.com"));
+ EXPECT_FALSE(
+ name_constraints.IsPermittedDNSName("a.excluded.permitted.example.com"));
+ EXPECT_FALSE(name_constraints.IsPermittedDNSName(
+ "stillnotpermitted.excluded.permitted.example.com"));
+ EXPECT_FALSE(name_constraints.IsPermittedDNSName(
+ "a.stillnotpermitted.excluded.permitted.example.com"));
+ EXPECT_FALSE(
+ name_constraints.IsPermittedDNSName("extraneousexclusion.example.com"));
+ EXPECT_FALSE(
+ name_constraints.IsPermittedDNSName("a.extraneousexclusion.example.com"));
+ EXPECT_FALSE(name_constraints.IsPermittedDNSName("other.example.com"));
+ EXPECT_FALSE(name_constraints.IsPermittedDNSName("other.com"));
+
+ // Wildcard names:
+ // Pattern could match excluded.permitted.example.com, thus should not be
+ // allowed.
+ EXPECT_FALSE(name_constraints.IsPermittedDNSName("*.permitted.example.com"));
+ // Entirely within excluded name, obviously not allowed.
+ EXPECT_FALSE(
+ name_constraints.IsPermittedDNSName("*.excluded.permitted.example.com"));
+ // Within permitted.example.com and cannot match any exclusion, thus these are
+ // allowed.
+ EXPECT_TRUE(
+ name_constraints.IsPermittedDNSName("*.foo.permitted.example.com"));
+ EXPECT_TRUE(
+ name_constraints.IsPermittedDNSName("*.alsopermitted.example.com"));
+ // Matches permitted.example2.com, but also matches other .example2.com names
+ // which are not in either permitted or excluded, so not allowed.
+ EXPECT_FALSE(name_constraints.IsPermittedDNSName("*.example2.com"));
+ // Partial wildcards are not supported, so these name are permitted even if
+ // it seems like they shouldn't be. It's fine, since certificate verification
+ // won't treat them as wildcard names either.
+ EXPECT_TRUE(
+ name_constraints.IsPermittedDNSName("*xcluded.permitted.example.com"));
+ EXPECT_TRUE(
+ name_constraints.IsPermittedDNSName("exclude*.permitted.example.com"));
+ EXPECT_TRUE(
+ name_constraints.IsPermittedDNSName("excl*ded.permitted.example.com"));
+ // Garbage wildcard data.
+ EXPECT_FALSE(name_constraints.IsPermittedDNSName("*."));
+ EXPECT_FALSE(name_constraints.IsPermittedDNSName("*.*"));
+ EXPECT_FALSE(name_constraints.IsPermittedDNSName(".*"));
+ EXPECT_FALSE(name_constraints.IsPermittedDNSName("*"));
+ // Matches SAN with trailing dot.
+ EXPECT_TRUE(name_constraints.IsPermittedDNSName("permitted.example3.com"));
+ EXPECT_TRUE(name_constraints.IsPermittedDNSName("permitted.example3.com."));
+ EXPECT_TRUE(name_constraints.IsPermittedDNSName("a.permitted.example3.com"));
+ EXPECT_TRUE(name_constraints.IsPermittedDNSName("a.permitted.example3.com."));
+
+ EXPECT_EQ(GENERAL_NAME_DNS_NAME, name_constraints.ConstrainedNameTypes());
+
+ std::string san;
+ ASSERT_TRUE(LoadTestSubjectAltName("san-permitted.pem", &san));
+ EXPECT_TRUE(name_constraints.IsPermittedCert(der::Input(),
+ InputFromString(&san), true));
+
+ ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-dnsname.pem", &san));
+ EXPECT_FALSE(name_constraints.IsPermittedCert(der::Input(),
+ InputFromString(&san), true));
+
+ ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-directoryname.pem", &san));
+ EXPECT_TRUE(name_constraints.IsPermittedCert(der::Input(),
+ InputFromString(&san), true));
+
+ ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-ipaddress.pem", &san));
+ EXPECT_TRUE(name_constraints.IsPermittedCert(der::Input(),
+ InputFromString(&san), true));
+}
+
+TEST_P(ParseNameConstraints, DNSNamesExcludeOnly) {
+ std::string a;
+ ASSERT_TRUE(LoadTestNameConstraint("dnsname-excluded.pem", &a));
+
+ NameConstraints name_constraints;
+ EXPECT_TRUE(name_constraints.Parse(InputFromString(&a), is_critical()));
+
+ // Only "excluded.permitted.example.com" is excluded, but since no dNSNames
+ // are permitted, everything is excluded.
+ EXPECT_FALSE(name_constraints.IsPermittedDNSName(""));
+ EXPECT_FALSE(name_constraints.IsPermittedDNSName("foo.com"));
+ EXPECT_FALSE(name_constraints.IsPermittedDNSName("permitted.example.com"));
+ EXPECT_FALSE(
+ name_constraints.IsPermittedDNSName("excluded.permitted.example.com"));
+ EXPECT_FALSE(
+ name_constraints.IsPermittedDNSName("a.excluded.permitted.example.com"));
+}
+
+TEST_P(ParseNameConstraints, DNSNamesExcludeAll) {
+ std::string a;
+ ASSERT_TRUE(LoadTestNameConstraint("dnsname-excludeall.pem", &a));
+
+ NameConstraints name_constraints;
+ EXPECT_TRUE(name_constraints.Parse(InputFromString(&a), is_critical()));
+
+ // "permitted.example.com" is in the permitted section, but since "" is
+ // excluded, nothing is permitted.
+ EXPECT_FALSE(name_constraints.IsPermittedDNSName(""));
+ EXPECT_FALSE(name_constraints.IsPermittedDNSName("foo.com"));
+ EXPECT_FALSE(name_constraints.IsPermittedDNSName("permitted.example.com"));
+ EXPECT_FALSE(
+ name_constraints.IsPermittedDNSName("foo.permitted.example.com"));
+}
+
+TEST_P(ParseNameConstraints, DirectoryNames) {
+ std::string constraints_der;
+ ASSERT_TRUE(LoadTestNameConstraint("directoryname.pem", &constraints_der));
+
+ std::string name_us;
+ ASSERT_TRUE(LoadTestName("name-us.pem", &name_us));
+ std::string name_us_ca;
+ ASSERT_TRUE(LoadTestName("name-us-california.pem", &name_us_ca));
+ std::string name_us_ca_mountain_view;
+ ASSERT_TRUE(LoadTestName("name-us-california-mountain_view.pem",
+ &name_us_ca_mountain_view));
+ std::string name_us_az;
+ ASSERT_TRUE(LoadTestName("name-us-arizona.pem", &name_us_az));
+ std::string name_jp;
+ ASSERT_TRUE(LoadTestName("name-jp.pem", &name_jp));
+ std::string name_jp_tokyo;
+ ASSERT_TRUE(LoadTestName("name-jp-tokyo.pem", &name_jp_tokyo));
+ std::string name_de;
+ ASSERT_TRUE(LoadTestName("name-de.pem", &name_de));
+ std::string name_ca;
+ ASSERT_TRUE(LoadTestName("name-ca.pem", &name_ca));
+
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ // Not in any permitted subtree.
+ EXPECT_FALSE(name_constraints.IsPermittedDirectoryName(
+ SequenceValueFromString(&name_ca)));
+ // Within the permitted C=US subtree.
+ EXPECT_TRUE(name_constraints.IsPermittedDirectoryName(
+ SequenceValueFromString(&name_us)));
+ // Within the permitted C=US subtree.
+ EXPECT_TRUE(name_constraints.IsPermittedDirectoryName(
+ SequenceValueFromString(&name_us_az)));
+ // Within the permitted C=US subtree, however the excluded C=US,ST=California
+ // subtree takes priority.
+ EXPECT_FALSE(name_constraints.IsPermittedDirectoryName(
+ SequenceValueFromString(&name_us_ca)));
+ // Within the permitted C=US subtree as well as the permitted
+ // C=US,ST=California,L=Mountain View subtree, however the excluded
+ // C=US,ST=California subtree still takes priority.
+ EXPECT_FALSE(name_constraints.IsPermittedDirectoryName(
+ SequenceValueFromString(&name_us_ca_mountain_view)));
+ // Not in any permitted subtree, and also inside the extraneous excluded C=DE
+ // subtree.
+ EXPECT_FALSE(name_constraints.IsPermittedDirectoryName(
+ SequenceValueFromString(&name_de)));
+ // Not in any permitted subtree.
+ EXPECT_FALSE(name_constraints.IsPermittedDirectoryName(
+ SequenceValueFromString(&name_jp)));
+ // Within the permitted C=JP,ST=Tokyo subtree.
+ EXPECT_TRUE(name_constraints.IsPermittedDirectoryName(
+ SequenceValueFromString(&name_jp_tokyo)));
+
+ EXPECT_EQ(GENERAL_NAME_DIRECTORY_NAME,
+ name_constraints.ConstrainedNameTypes());
+
+ // Within the permitted C=US subtree.
+ EXPECT_TRUE(
+ name_constraints.IsPermittedCert(SequenceValueFromString(&name_us),
+ der::Input(), false /* is_leaf_cert */));
+ EXPECT_TRUE(
+ name_constraints.IsPermittedCert(SequenceValueFromString(&name_us),
+ der::Input(), true /* is_leaf_cert */));
+ // Within the permitted C=US subtree, however the excluded C=US,ST=California
+ // subtree takes priority.
+ EXPECT_FALSE(
+ name_constraints.IsPermittedCert(SequenceValueFromString(&name_us_ca),
+ der::Input(), false /* is_leaf_cert */));
+ EXPECT_FALSE(
+ name_constraints.IsPermittedCert(SequenceValueFromString(&name_us_ca),
+ der::Input(), true /* is_leaf_cert */));
+
+ std::string san;
+ ASSERT_TRUE(LoadTestSubjectAltName("san-permitted.pem", &san));
+ EXPECT_TRUE(name_constraints.IsPermittedCert(der::Input(),
+ InputFromString(&san), true));
+
+ ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-dnsname.pem", &san));
+ EXPECT_TRUE(name_constraints.IsPermittedCert(der::Input(),
+ InputFromString(&san), true));
+
+ ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-directoryname.pem", &san));
+ EXPECT_FALSE(name_constraints.IsPermittedCert(der::Input(),
+ InputFromString(&san), true));
+
+ ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-ipaddress.pem", &san));
+ EXPECT_TRUE(name_constraints.IsPermittedCert(der::Input(),
+ InputFromString(&san), true));
+}
+
+TEST_P(ParseNameConstraints, DirectoryNamesExcludeOnly) {
+ std::string constraints_der;
+ ASSERT_TRUE(
+ LoadTestNameConstraint("directoryname-excluded.pem", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ std::string name_empty;
+ ASSERT_TRUE(LoadTestName("name-empty.pem", &name_empty));
+ std::string name_us;
+ ASSERT_TRUE(LoadTestName("name-us.pem", &name_us));
+ std::string name_us_ca;
+ ASSERT_TRUE(LoadTestName("name-us-california.pem", &name_us_ca));
+ std::string name_us_ca_mountain_view;
+ ASSERT_TRUE(LoadTestName("name-us-california-mountain_view.pem",
+ &name_us_ca_mountain_view));
+
+ // Only "C=US,ST=California" is excluded, but since no directoryNames are
+ // permitted, everything is excluded.
+ EXPECT_FALSE(name_constraints.IsPermittedDirectoryName(
+ SequenceValueFromString(&name_empty)));
+ EXPECT_FALSE(name_constraints.IsPermittedDirectoryName(
+ SequenceValueFromString(&name_us)));
+ EXPECT_FALSE(name_constraints.IsPermittedDirectoryName(
+ SequenceValueFromString(&name_us_ca)));
+ EXPECT_FALSE(name_constraints.IsPermittedDirectoryName(
+ SequenceValueFromString(&name_us_ca_mountain_view)));
+}
+
+TEST_P(ParseNameConstraints, DirectoryNamesExcludeAll) {
+ std::string constraints_der;
+ ASSERT_TRUE(
+ LoadTestNameConstraint("directoryname-excluded.pem", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ std::string name_empty;
+ ASSERT_TRUE(LoadTestName("name-empty.pem", &name_empty));
+ std::string name_us;
+ ASSERT_TRUE(LoadTestName("name-us.pem", &name_us));
+ std::string name_us_ca;
+ ASSERT_TRUE(LoadTestName("name-us-california.pem", &name_us_ca));
+ std::string name_us_ca_mountain_view;
+ ASSERT_TRUE(LoadTestName("name-us-california-mountain_view.pem",
+ &name_us_ca_mountain_view));
+ std::string name_jp;
+ ASSERT_TRUE(LoadTestName("name-jp.pem", &name_jp));
+
+ // "C=US" is in the permitted section, but since an empty
+ // directoryName is excluded, nothing is permitted.
+ EXPECT_FALSE(name_constraints.IsPermittedDirectoryName(
+ SequenceValueFromString(&name_empty)));
+ EXPECT_FALSE(name_constraints.IsPermittedDirectoryName(
+ SequenceValueFromString(&name_us)));
+ EXPECT_FALSE(name_constraints.IsPermittedDirectoryName(
+ SequenceValueFromString(&name_us_ca)));
+ EXPECT_FALSE(name_constraints.IsPermittedDirectoryName(
+ SequenceValueFromString(&name_jp)));
+}
+
+TEST_P(ParseNameConstraints, IPAdresses) {
+ std::string a;
+ ASSERT_TRUE(LoadTestNameConstraint("ipaddress.pem", &a));
+
+ NameConstraints name_constraints;
+ EXPECT_TRUE(name_constraints.Parse(InputFromString(&a), is_critical()));
+
+ // IPv4 tests:
+ {
+ // Not in any permitted range.
+ const uint8_t ip4[] = {192, 169, 0, 1};
+ EXPECT_FALSE(name_constraints.IsPermittedIP(
+ IPAddressNumber(ip4, ip4 + arraysize(ip4))));
+ }
+ {
+ // Within the permitted 192.168.0.0/255.255.0.0 range.
+ const uint8_t ip4[] = {192, 168, 0, 1};
+ EXPECT_TRUE(name_constraints.IsPermittedIP(
+ IPAddressNumber(ip4, ip4 + arraysize(ip4))));
+ }
+ {
+ // Within the permitted 192.168.0.0/255.255.0.0 range, however the
+ // excluded 192.168.5.0/255.255.255.0 takes priority.
+ const uint8_t ip4[] = {192, 168, 5, 1};
+ EXPECT_FALSE(name_constraints.IsPermittedIP(
+ IPAddressNumber(ip4, ip4 + arraysize(ip4))));
+ }
+ {
+ // Within the permitted 192.168.0.0/255.255.0.0 range as well as the
+ // permitted 192.168.5.32/255.255.255.96 range, however the excluded
+ // 192.168.5.0/255.255.255.0 still takes priority.
+ const uint8_t ip4[] = {192, 168, 5, 33};
+ EXPECT_FALSE(name_constraints.IsPermittedIP(
+ IPAddressNumber(ip4, ip4 + arraysize(ip4))));
+ }
+ {
+ // Not in any permitted range. (Just outside the 192.167.5.32/255.255.255.96
+ // range.)
+ const uint8_t ip4[] = {192, 167, 5, 31};
+ EXPECT_FALSE(name_constraints.IsPermittedIP(
+ IPAddressNumber(ip4, ip4 + arraysize(ip4))));
+ }
+ {
+ // Within the permitted 192.167.5.32/255.255.255.96 range.
+ const uint8_t ip4[] = {192, 167, 5, 32};
+ EXPECT_TRUE(name_constraints.IsPermittedIP(
+ IPAddressNumber(ip4, ip4 + arraysize(ip4))));
+ }
+ {
+ // Within the permitted 192.167.5.32/255.255.255.96 range.
+ const uint8_t ip4[] = {192, 167, 5, 63};
+ EXPECT_TRUE(name_constraints.IsPermittedIP(
+ IPAddressNumber(ip4, ip4 + arraysize(ip4))));
+ }
+ {
+ // Not in any permitted range. (Just outside the 192.167.5.32/255.255.255.96
+ // range.)
+ const uint8_t ip4[] = {192, 167, 5, 64};
+ EXPECT_FALSE(name_constraints.IsPermittedIP(
+ IPAddressNumber(ip4, ip4 + arraysize(ip4))));
+ }
+ {
+ // Not in any permitted range, and also inside the extraneous excluded
+ // 192.166.5.32/255.255.255.96 range.
+ const uint8_t ip4[] = {192, 166, 5, 32};
+ EXPECT_FALSE(name_constraints.IsPermittedIP(
+ IPAddressNumber(ip4, ip4 + arraysize(ip4))));
+ }
+
+ // IPv6 tests:
+ {
+ // Not in any permitted range.
+ const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 0, 0, 0, 1};
+ EXPECT_FALSE(name_constraints.IsPermittedIP(
+ IPAddressNumber(ip6, ip6 + arraysize(ip6))));
+ }
+ {
+ // Within the permitted
+ // 102:304:506:708:90a:b0c::/ffff:ffff:ffff:ffff:ffff:ffff:: range.
+ const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 0, 0, 1};
+ EXPECT_TRUE(name_constraints.IsPermittedIP(
+ IPAddressNumber(ip6, ip6 + arraysize(ip6))));
+ }
+ {
+ // Within the permitted
+ // 102:304:506:708:90a:b0c::/ffff:ffff:ffff:ffff:ffff:ffff:: range, however
+ // the excluded
+ // 102:304:506:708:90a:b0c:500:0/ffff:ffff:ffff:ffff:ffff:ffff:ff00:0 takes
+ // priority.
+ const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 5, 0, 0, 1};
+ EXPECT_FALSE(name_constraints.IsPermittedIP(
+ IPAddressNumber(ip6, ip6 + arraysize(ip6))));
+ }
+ {
+ // Within the permitted
+ // 102:304:506:708:90a:b0c::/ffff:ffff:ffff:ffff:ffff:ffff:: range as well
+ // as the permitted
+ // 102:304:506:708:90a:b0c:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0,
+ // however the excluded
+ // 102:304:506:708:90a:b0c:500:0/ffff:ffff:ffff:ffff:ffff:ffff:ff00:0 takes
+ // priority.
+ const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 5, 33, 0, 1};
+ EXPECT_FALSE(name_constraints.IsPermittedIP(
+ IPAddressNumber(ip6, ip6 + arraysize(ip6))));
+ }
+ {
+ // Not in any permitted range. (Just outside the
+ // 102:304:506:708:90a:b0b:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0
+ // range.)
+ const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 11, 5, 31, 255, 255};
+ EXPECT_FALSE(name_constraints.IsPermittedIP(
+ IPAddressNumber(ip6, ip6 + arraysize(ip6))));
+ }
+ {
+ // Within the permitted
+ // 102:304:506:708:90a:b0b:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0 range.
+ const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, 5, 32, 0, 0};
+ EXPECT_TRUE(name_constraints.IsPermittedIP(
+ IPAddressNumber(ip6, ip6 + arraysize(ip6))));
+ }
+ {
+ // Within the permitted
+ // 102:304:506:708:90a:b0b:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0 range.
+ const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 11, 5, 63, 255, 255};
+ EXPECT_TRUE(name_constraints.IsPermittedIP(
+ IPAddressNumber(ip6, ip6 + arraysize(ip6))));
+ }
+ {
+ // Not in any permitted range. (Just outside the
+ // 102:304:506:708:90a:b0b:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0
+ // range.)
+ const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, 5, 64, 0, 0};
+ EXPECT_FALSE(name_constraints.IsPermittedIP(
+ IPAddressNumber(ip6, ip6 + arraysize(ip6))));
+ }
+ {
+ // Not in any permitted range, and also inside the extraneous excluded
+ // 102:304:506:708:90a:b0a:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0 range.
+ const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 10, 5, 33, 0, 1};
+ EXPECT_FALSE(name_constraints.IsPermittedIP(
+ IPAddressNumber(ip6, ip6 + arraysize(ip6))));
+ }
+
+ EXPECT_EQ(GENERAL_NAME_IP_ADDRESS, name_constraints.ConstrainedNameTypes());
+
+ std::string san;
+ ASSERT_TRUE(LoadTestSubjectAltName("san-permitted.pem", &san));
+ EXPECT_TRUE(name_constraints.IsPermittedCert(der::Input(),
+ InputFromString(&san), true));
+
+ ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-dnsname.pem", &san));
+ EXPECT_TRUE(name_constraints.IsPermittedCert(der::Input(),
+ InputFromString(&san), true));
+
+ ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-directoryname.pem", &san));
+ EXPECT_TRUE(name_constraints.IsPermittedCert(der::Input(),
+ InputFromString(&san), true));
+
+ ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-ipaddress.pem", &san));
+ EXPECT_FALSE(name_constraints.IsPermittedCert(der::Input(),
+ InputFromString(&san), true));
+}
+
+TEST_P(ParseNameConstraints, IPAdressesExcludeOnly) {
+ std::string a;
+ ASSERT_TRUE(LoadTestNameConstraint("ipaddress-excluded.pem", &a));
+
+ NameConstraints name_constraints;
+ EXPECT_TRUE(name_constraints.Parse(InputFromString(&a), is_critical()));
+
+ // Only 192.168.5.0/255.255.255.0 is excluded, but since no iPAddresses
+ // are permitted, everything is excluded.
+ {
+ const uint8_t ip4[] = {192, 168, 0, 1};
+ EXPECT_FALSE(name_constraints.IsPermittedIP(
+ IPAddressNumber(ip4, ip4 + arraysize(ip4))));
+ }
+ {
+ const uint8_t ip4[] = {192, 168, 5, 1};
+ EXPECT_FALSE(name_constraints.IsPermittedIP(
+ IPAddressNumber(ip4, ip4 + arraysize(ip4))));
+ }
+ {
+ const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 0, 0, 0, 1};
+ EXPECT_FALSE(name_constraints.IsPermittedIP(
+ IPAddressNumber(ip6, ip6 + arraysize(ip6))));
+ }
+}
+
+TEST_P(ParseNameConstraints, IPAdressesExcludeAll) {
+ std::string a;
+ ASSERT_TRUE(LoadTestNameConstraint("ipaddress-excludeall.pem", &a));
+
+ NameConstraints name_constraints;
+ EXPECT_TRUE(name_constraints.Parse(InputFromString(&a), is_critical()));
+
+ // 192.168.0.0/255.255.0.0 and
+ // 102:304:506:708:90a:b0c::/ffff:ffff:ffff:ffff:ffff:ffff:: are permitted,
+ // but since 0.0.0.0/0 and ::/0 are excluded nothing is permitted.
+ {
+ const uint8_t ip4[] = {192, 168, 0, 1};
+ EXPECT_FALSE(name_constraints.IsPermittedIP(
+ IPAddressNumber(ip4, ip4 + arraysize(ip4))));
+ }
+ {
+ const uint8_t ip4[] = {1, 1, 1, 1};
+ EXPECT_FALSE(name_constraints.IsPermittedIP(
+ IPAddressNumber(ip4, ip4 + arraysize(ip4))));
+ }
+ {
+ const uint8_t ip6[] = {2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
+ EXPECT_FALSE(name_constraints.IsPermittedIP(
+ IPAddressNumber(ip6, ip6 + arraysize(ip6))));
+ }
+ {
+ const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 0, 0, 0, 1};
+ EXPECT_FALSE(name_constraints.IsPermittedIP(
+ IPAddressNumber(ip6, ip6 + arraysize(ip6))));
+ }
+}
+
+TEST_P(ParseNameConstraints, OtherNamesInPermitted) {
+ std::string constraints_der;
+ ASSERT_TRUE(
+ LoadTestNameConstraint("othername-permitted.pem", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ if (is_critical()) {
+ EXPECT_EQ(GENERAL_NAME_OTHER_NAME, name_constraints.ConstrainedNameTypes());
+ } else {
+ EXPECT_EQ(0, name_constraints.ConstrainedNameTypes());
+ }
+
+ std::string san;
+ ASSERT_TRUE(LoadTestSubjectAltName("san-othername.pem", &san));
+ EXPECT_EQ(!is_critical(),
+ name_constraints.IsPermittedCert(
+ der::Input(), InputFromString(&san), false /* is_leaf_cert */));
+}
+
+TEST_P(ParseNameConstraints, OtherNamesInExcluded) {
+ std::string constraints_der;
+ ASSERT_TRUE(
+ LoadTestNameConstraint("othername-excluded.pem", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ if (is_critical()) {
+ EXPECT_EQ(GENERAL_NAME_OTHER_NAME, name_constraints.ConstrainedNameTypes());
+ } else {
+ EXPECT_EQ(0, name_constraints.ConstrainedNameTypes());
+ }
+
+ std::string san;
+ ASSERT_TRUE(LoadTestSubjectAltName("san-othername.pem", &san));
+ EXPECT_EQ(!is_critical(),
+ name_constraints.IsPermittedCert(
+ der::Input(), InputFromString(&san), false /* is_leaf_cert */));
+}
+
+TEST_P(ParseNameConstraints, Rfc822NamesInPermitted) {
+ std::string constraints_der;
+ ASSERT_TRUE(
+ LoadTestNameConstraint("rfc822name-permitted.pem", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ if (is_critical()) {
+ EXPECT_EQ(GENERAL_NAME_RFC822_NAME,
+ name_constraints.ConstrainedNameTypes());
+ } else {
+ EXPECT_EQ(0, name_constraints.ConstrainedNameTypes());
+ }
+
+ std::string san;
+ ASSERT_TRUE(LoadTestSubjectAltName("san-rfc822name.pem", &san));
+ EXPECT_EQ(!is_critical(),
+ name_constraints.IsPermittedCert(
+ der::Input(), InputFromString(&san), false /* is_leaf_cert */));
+}
+
+TEST_P(ParseNameConstraints, Rfc822NamesInExcluded) {
+ std::string constraints_der;
+ ASSERT_TRUE(
+ LoadTestNameConstraint("rfc822name-excluded.pem", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ if (is_critical()) {
+ EXPECT_EQ(GENERAL_NAME_RFC822_NAME,
+ name_constraints.ConstrainedNameTypes());
+ } else {
+ EXPECT_EQ(0, name_constraints.ConstrainedNameTypes());
+ }
+
+ std::string san;
+ ASSERT_TRUE(LoadTestSubjectAltName("san-rfc822name.pem", &san));
+ EXPECT_EQ(!is_critical(),
+ name_constraints.IsPermittedCert(
+ der::Input(), InputFromString(&san), false /* is_leaf_cert */));
+}
+
+TEST_P(ParseNameConstraints, X400AddresssInPermitted) {
+ std::string constraints_der;
+ ASSERT_TRUE(
+ LoadTestNameConstraint("x400address-permitted.pem", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ if (is_critical()) {
+ EXPECT_EQ(GENERAL_NAME_X400_ADDRESS,
+ name_constraints.ConstrainedNameTypes());
+ } else {
+ EXPECT_EQ(0, name_constraints.ConstrainedNameTypes());
+ }
+
+ std::string san;
+ ASSERT_TRUE(LoadTestSubjectAltName("san-x400address.pem", &san));
+ EXPECT_EQ(!is_critical(),
+ name_constraints.IsPermittedCert(
+ der::Input(), InputFromString(&san), false /* is_leaf_cert */));
+}
+
+TEST_P(ParseNameConstraints, X400AddresssInExcluded) {
+ std::string constraints_der;
+ ASSERT_TRUE(
+ LoadTestNameConstraint("x400address-excluded.pem", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ if (is_critical()) {
+ EXPECT_EQ(GENERAL_NAME_X400_ADDRESS,
+ name_constraints.ConstrainedNameTypes());
+ } else {
+ EXPECT_EQ(0, name_constraints.ConstrainedNameTypes());
+ }
+
+ std::string san;
+ ASSERT_TRUE(LoadTestSubjectAltName("san-x400address.pem", &san));
+ EXPECT_EQ(!is_critical(),
+ name_constraints.IsPermittedCert(
+ der::Input(), InputFromString(&san), false /* is_leaf_cert */));
+}
+
+TEST_P(ParseNameConstraints, EdiPartyNamesInPermitted) {
+ std::string constraints_der;
+ ASSERT_TRUE(
+ LoadTestNameConstraint("edipartyname-permitted.pem", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ if (is_critical()) {
+ EXPECT_EQ(GENERAL_NAME_EDI_PARTY_NAME,
+ name_constraints.ConstrainedNameTypes());
+ } else {
+ EXPECT_EQ(0, name_constraints.ConstrainedNameTypes());
+ }
+
+ std::string san;
+ ASSERT_TRUE(LoadTestSubjectAltName("san-edipartyname.pem", &san));
+ EXPECT_EQ(!is_critical(),
+ name_constraints.IsPermittedCert(
+ der::Input(), InputFromString(&san), false /* is_leaf_cert */));
+}
+
+TEST_P(ParseNameConstraints, EdiPartyNamesInExcluded) {
+ std::string constraints_der;
+ ASSERT_TRUE(
+ LoadTestNameConstraint("edipartyname-excluded.pem", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ if (is_critical()) {
+ EXPECT_EQ(GENERAL_NAME_EDI_PARTY_NAME,
+ name_constraints.ConstrainedNameTypes());
+ } else {
+ EXPECT_EQ(0, name_constraints.ConstrainedNameTypes());
+ }
+
+ std::string san;
+ ASSERT_TRUE(LoadTestSubjectAltName("san-edipartyname.pem", &san));
+ EXPECT_EQ(!is_critical(),
+ name_constraints.IsPermittedCert(
+ der::Input(), InputFromString(&san), false /* is_leaf_cert */));
+}
+
+TEST_P(ParseNameConstraints, URIsInPermitted) {
+ std::string constraints_der;
+ ASSERT_TRUE(LoadTestNameConstraint("uri-permitted.pem", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ if (is_critical()) {
+ EXPECT_EQ(GENERAL_NAME_UNIFORM_RESOURCE_IDENTIFIER,
+ name_constraints.ConstrainedNameTypes());
+ } else {
+ EXPECT_EQ(0, name_constraints.ConstrainedNameTypes());
+ }
+
+ std::string san;
+ ASSERT_TRUE(LoadTestSubjectAltName("san-uri.pem", &san));
+ EXPECT_EQ(!is_critical(),
+ name_constraints.IsPermittedCert(
+ der::Input(), InputFromString(&san), false /* is_leaf_cert */));
+}
+
+TEST_P(ParseNameConstraints, URIsInExcluded) {
+ std::string constraints_der;
+ ASSERT_TRUE(LoadTestNameConstraint("uri-excluded.pem", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ if (is_critical()) {
+ EXPECT_EQ(GENERAL_NAME_UNIFORM_RESOURCE_IDENTIFIER,
+ name_constraints.ConstrainedNameTypes());
+ } else {
+ EXPECT_EQ(0, name_constraints.ConstrainedNameTypes());
+ }
+
+ std::string san;
+ ASSERT_TRUE(LoadTestSubjectAltName("san-uri.pem", &san));
+ EXPECT_EQ(!is_critical(),
+ name_constraints.IsPermittedCert(
+ der::Input(), InputFromString(&san), false /* is_leaf_cert */));
+}
+
+TEST_P(ParseNameConstraints, RegisteredIDsInPermitted) {
+ std::string constraints_der;
+ ASSERT_TRUE(
+ LoadTestNameConstraint("registeredid-permitted.pem", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ if (is_critical()) {
+ EXPECT_EQ(GENERAL_NAME_REGISTERED_ID,
+ name_constraints.ConstrainedNameTypes());
+ } else {
+ EXPECT_EQ(0, name_constraints.ConstrainedNameTypes());
+ }
+
+ std::string san;
+ ASSERT_TRUE(LoadTestSubjectAltName("san-registeredid.pem", &san));
+ EXPECT_EQ(!is_critical(),
+ name_constraints.IsPermittedCert(
+ der::Input(), InputFromString(&san), false /* is_leaf_cert */));
+}
+
+TEST_P(ParseNameConstraints, RegisteredIDsInExcluded) {
+ std::string constraints_der;
+ ASSERT_TRUE(
+ LoadTestNameConstraint("registeredid-excluded.pem", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ if (is_critical()) {
+ EXPECT_EQ(GENERAL_NAME_REGISTERED_ID,
+ name_constraints.ConstrainedNameTypes());
+ } else {
+ EXPECT_EQ(0, name_constraints.ConstrainedNameTypes());
+ }
+
+ std::string san;
+ ASSERT_TRUE(LoadTestSubjectAltName("san-registeredid.pem", &san));
+ EXPECT_EQ(!is_critical(),
+ name_constraints.IsPermittedCert(
+ der::Input(), InputFromString(&san), false /* is_leaf_cert */));
+}
+
+TEST_P(ParseNameConstraints,
+ failsOnGeneralSubtreeWithMinimumZeroEncodedUnnecessarily) {
+ std::string constraints_der;
+ ASSERT_TRUE(
+ LoadTestNameConstraint("dnsname-with_min_0.pem", &constraints_der));
+ NameConstraints name_constraints;
+ // The value should not be in the DER encoding if it is the default. But this
+ // could be changed to allowed if there are buggy encoders out there that
+ // include it anyway.
+ EXPECT_FALSE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+}
+
+TEST_P(ParseNameConstraints, FailsOnGeneralSubtreeWithMinimum) {
+ std::string constraints_der;
+ ASSERT_TRUE(
+ LoadTestNameConstraint("dnsname-with_min_1.pem", &constraints_der));
+ NameConstraints name_constraints;
+ // Could handle this more gracefully (see TODO in ParseGeneralSubtrees).
+ EXPECT_FALSE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+}
+
+TEST_P(ParseNameConstraints,
+ failsOnGeneralSubtreeWithMinimumZeroEncodedUnnecessarilyAndMaximum) {
+ std::string constraints_der;
+ ASSERT_TRUE(LoadTestNameConstraint("dnsname-with_min_0_and_max.pem",
+ &constraints_der));
+ NameConstraints name_constraints;
+ // Could handle this more gracefully (see TODO in ParseGeneralSubtrees).
+ EXPECT_FALSE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+}
+
+TEST_P(ParseNameConstraints, FailsOnGeneralSubtreeWithMinimumAndMaximum) {
+ std::string constraints_der;
+ ASSERT_TRUE(LoadTestNameConstraint("dnsname-with_min_1_and_max.pem",
+ &constraints_der));
+ NameConstraints name_constraints;
+ // Could handle this more gracefully (see TODO in ParseGeneralSubtrees).
+ EXPECT_FALSE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+}
+
+TEST_P(ParseNameConstraints, FailsOnGeneralSubtreeWithMaximum) {
+ std::string constraints_der;
+ ASSERT_TRUE(LoadTestNameConstraint("dnsname-with_max.pem", &constraints_der));
+ NameConstraints name_constraints;
+ // Could handle this more gracefully (see TODO in ParseGeneralSubtrees).
+ EXPECT_FALSE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+}
+
+TEST_P(ParseNameConstraints, FailsOnEmptyExtensionValue) {
+ std::string constraints_der = "";
+ NameConstraints name_constraints;
+ EXPECT_FALSE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+}
+
+TEST_P(ParseNameConstraints, FailsOnEmptyPermittedAndExcluded) {
+ std::string constraints_der;
+ ASSERT_TRUE(
+ LoadTestNameConstraint("invalid-no_subtrees.pem", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_FALSE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+}
+
+TEST_P(ParseNameConstraints, IsPermittedCertSubjectEmailAddressIsOk) {
+ std::string constraints_der;
+ ASSERT_TRUE(LoadTestNameConstraint("directoryname.pem", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ std::string name_us_arizona_email;
+ ASSERT_TRUE(
+ LoadTestName("name-us-arizona-email.pem", &name_us_arizona_email));
+
+ // Name constraints don't contain rfc822Name, so emailAddress in subject is
+ // allowed regardless.
+ EXPECT_TRUE(name_constraints.IsPermittedCert(
+ SequenceValueFromString(&name_us_arizona_email), der::Input(),
+ true /* is_leaf_cert */));
+ EXPECT_TRUE(name_constraints.IsPermittedCert(
+ SequenceValueFromString(&name_us_arizona_email), der::Input(),
+ false /* is_leaf_cert */));
+}
+
+TEST_P(ParseNameConstraints, IsPermittedCertSubjectEmailAddressIsNotOk) {
+ std::string constraints_der;
+ ASSERT_TRUE(
+ LoadTestNameConstraint("rfc822name-permitted.pem", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ std::string name_us_arizona_email;
+ ASSERT_TRUE(
+ LoadTestName("name-us-arizona-email.pem", &name_us_arizona_email));
+
+ // Name constraints contain rfc822Name, so emailAddress in subject is not
+ // allowed if the constraints were critical.
+ EXPECT_EQ(!is_critical(), name_constraints.IsPermittedCert(
+ SequenceValueFromString(&name_us_arizona_email),
+ der::Input(), true /* is_leaf_cert */));
+ EXPECT_EQ(!is_critical(), name_constraints.IsPermittedCert(
+ SequenceValueFromString(&name_us_arizona_email),
+ der::Input(), false /* is_leaf_cert */));
+}
+
+TEST_P(ParseNameConstraints, IsPermittedCertSubjectDnsNames) {
+ std::string constraints_der;
+ ASSERT_TRUE(LoadTestNameConstraint("dnsname.pem", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ ASSERT_TRUE(LoadTestNameConstraint("directoryname.pem", &constraints_der));
+ // This is a bit of a hack, but Parse can be called multiple times to load
+ // different constraints into the same object (doesn't do a proper merge, but
+ // good enough for this test).
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ std::string name_us_az;
+ ASSERT_TRUE(LoadTestName("name-us-arizona.pem", &name_us_az));
+ std::string name_us_az_foocom;
+ ASSERT_TRUE(LoadTestName("name-us-arizona-foo.com.pem", &name_us_az_foocom));
+
+ // foo.com is not within the permitted dNSName constraints:
+ EXPECT_FALSE(name_constraints.IsPermittedCert(
+ SequenceValueFromString(&name_us_az_foocom), der::Input(),
+ true /* is_leaf_cert */));
+ // commonName check is only done for leaf certs, so this is allowed:
+ EXPECT_TRUE(name_constraints.IsPermittedCert(
+ SequenceValueFromString(&name_us_az_foocom), der::Input(),
+ false /* is_leaf_cert */));
+
+ std::string name_us_az_permitted;
+ ASSERT_TRUE(LoadTestName("name-us-arizona-permitted.example.com.pem",
+ &name_us_az_permitted));
+ // permitted.example.com is within the permitted dNSName constraints and the
+ // permitted C=US directoryName constraint:
+ EXPECT_TRUE(name_constraints.IsPermittedCert(
+ SequenceValueFromString(&name_us_az_permitted), der::Input(),
+ true /* is_leaf_cert */));
+ EXPECT_TRUE(name_constraints.IsPermittedCert(
+ SequenceValueFromString(&name_us_az_permitted), der::Input(),
+ false /* is_leaf_cert */));
+
+ std::string name_us_ca_permitted;
+ ASSERT_TRUE(LoadTestName("name-us-california-permitted.example.com.pem",
+ &name_us_ca_permitted));
+ // permitted.example.com is within the permitted dNSName constraints but the
+ // subject is within the excluded C=US,ST=California directoryName, so not
+ // allowed anyway:
+ EXPECT_FALSE(name_constraints.IsPermittedCert(
+ SequenceValueFromString(&name_us_ca_permitted), der::Input(),
+ true /* is_leaf_cert */));
+ EXPECT_FALSE(name_constraints.IsPermittedCert(
+ SequenceValueFromString(&name_us_ca_permitted), der::Input(),
+ false /* is_leaf_cert */));
+
+ // As a leaf cert with no SubjectAltName, the subject is expected to have a
+ // host in commonName, this subject has no commonName field, so fails:
+ EXPECT_FALSE(
+ name_constraints.IsPermittedCert(SequenceValueFromString(&name_us_az),
+ der::Input(), true /* is_leaf_cert */));
+ // Within the permitted C=US subtree, not a leaf cert, so does not need
+ // a host in commonName.
+ EXPECT_TRUE(
+ name_constraints.IsPermittedCert(SequenceValueFromString(&name_us_az),
+ der::Input(), false /* is_leaf_cert */));
+}
+
+TEST_P(ParseNameConstraints, IsPermittedCertSubjectIpAddresses) {
+ std::string constraints_der;
+ ASSERT_TRUE(LoadTestNameConstraint("ipaddress.pem", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ ASSERT_TRUE(LoadTestNameConstraint("directoryname.pem", &constraints_der));
+ // This is a bit of a hack, but Parse can be called multiple times to load
+ // different constraints into the same object (doesn't do a proper merge, but
+ // good enough for this test).
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+ ASSERT_TRUE(LoadTestNameConstraint("dnsname.pem", &constraints_der));
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ std::string name_us_az;
+ ASSERT_TRUE(LoadTestName("name-us-arizona.pem", &name_us_az));
+ std::string name_us_az_1_1_1_1;
+ ASSERT_TRUE(LoadTestName("name-us-arizona-1.1.1.1.pem", &name_us_az_1_1_1_1));
+
+ // 1.1.1.1 is not within the permitted iPAddress constraints:
+ EXPECT_FALSE(name_constraints.IsPermittedCert(
+ SequenceValueFromString(&name_us_az_1_1_1_1), der::Input(),
+ true /* is_leaf_cert */));
+ // commonName check is only done for leaf certs, so this is allowed:
+ EXPECT_TRUE(name_constraints.IsPermittedCert(
+ SequenceValueFromString(&name_us_az_1_1_1_1), der::Input(),
+ false /* is_leaf_cert */));
+
+ std::string name_us_az_192_168_1_1;
+ ASSERT_TRUE(
+ LoadTestName("name-us-arizona-192.168.1.1.pem", &name_us_az_192_168_1_1));
+ // 192.168.1.1 is within the permitted iPAddress constraints and the
+ // permitted C=US directoryName constraint:
+ EXPECT_TRUE(name_constraints.IsPermittedCert(
+ SequenceValueFromString(&name_us_az_192_168_1_1), der::Input(),
+ true /* is_leaf_cert */));
+ EXPECT_TRUE(name_constraints.IsPermittedCert(
+ SequenceValueFromString(&name_us_az_192_168_1_1), der::Input(),
+ false /* is_leaf_cert */));
+
+ std::string name_us_ca_192_168_1_1;
+ ASSERT_TRUE(LoadTestName("name-us-california-192.168.1.1.pem",
+ &name_us_ca_192_168_1_1));
+ // 192.168.1.1 is within the permitted iPAddress constraints but the
+ // subject is within the excluded C=US,ST=California directoryName, so not
+ // allowed anyway:
+ EXPECT_FALSE(name_constraints.IsPermittedCert(
+ SequenceValueFromString(&name_us_ca_192_168_1_1), der::Input(),
+ true /* is_leaf_cert */));
+ EXPECT_FALSE(name_constraints.IsPermittedCert(
+ SequenceValueFromString(&name_us_ca_192_168_1_1), der::Input(),
+ false /* is_leaf_cert */));
+
+ std::string name_us_az_ipv6;
+ ASSERT_TRUE(LoadTestName("name-us-arizona-ipv6.pem", &name_us_az_ipv6));
+ // 102:304:506:708:90a:b0c::1 is within the permitted iPAddress constraints
+ // and the permitted C=US directoryName constraint, but Chrome only handles
+ // IPv4 addresses in commonName so the address will be checked against dNSName
+ // constraints instead, which will not match any permitted names.
+ EXPECT_FALSE(name_constraints.IsPermittedCert(
+ SequenceValueFromString(&name_us_az_ipv6), der::Input(),
+ true /* is_leaf_cert */));
+ EXPECT_TRUE(name_constraints.IsPermittedCert(
+ SequenceValueFromString(&name_us_az_ipv6), der::Input(),
+ false /* is_leaf_cert */));
+
+ // As a leaf cert with no SubjectAltName, the subject is expected to have a
+ // host in commonName, this subject has no commonName field, so fails:
+ EXPECT_FALSE(
+ name_constraints.IsPermittedCert(SequenceValueFromString(&name_us_az),
+ der::Input(), true /* is_leaf_cert */));
+ // Within the permitted C=US subtree, not a leaf cert, so does not need
+ // a host in commonName.
+ EXPECT_TRUE(
+ name_constraints.IsPermittedCert(SequenceValueFromString(&name_us_az),
+ der::Input(), false /* is_leaf_cert */));
+}
+
+TEST_P(ParseNameConstraints, IsPermittedCertSubjectCommonNameEncodings) {
+ std::string constraints_der;
+ ASSERT_TRUE(LoadTestNameConstraint("ipaddress.pem", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ // CommonName encoded as BMPString: should work since we convert to UTF8
+ // before parsing.
+ std::string name_us_az_192_168_1_1_bmp;
+ ASSERT_TRUE(LoadTestName("name-us-arizona-192.168.1.1-bmp.pem",
+ &name_us_az_192_168_1_1_bmp));
+ EXPECT_TRUE(name_constraints.IsPermittedCert(
+ SequenceValueFromString(&name_us_az_192_168_1_1_bmp), der::Input(),
+ true /* is_leaf_cert */));
+ EXPECT_TRUE(name_constraints.IsPermittedCert(
+ SequenceValueFromString(&name_us_az_192_168_1_1_bmp), der::Input(),
+ false /* is_leaf_cert */));
+
+ // CommonName encoded as TeletexString: should not work, TeletexString is not
+ // supported.
+ std::string name_us_az_192_168_1_1_t61;
+ ASSERT_TRUE(LoadTestName("name-us-arizona-192.168.1.1-t61.pem",
+ &name_us_az_192_168_1_1_t61));
+ EXPECT_FALSE(name_constraints.IsPermittedCert(
+ SequenceValueFromString(&name_us_az_192_168_1_1_t61), der::Input(),
+ true /* is_leaf_cert */));
+ // If it's not a leaf cert, commonName is not checked, so this is allowed.
+ EXPECT_TRUE(name_constraints.IsPermittedCert(
+ SequenceValueFromString(&name_us_az_192_168_1_1_t61), der::Input(),
+ false /* is_leaf_cert */));
+}
+
+TEST_P(ParseNameConstraints, IsPermittedCertFailsOnEmptySubjectAltName) {
+ std::string constraints_der;
+ ASSERT_TRUE(LoadTestNameConstraint("dnsname.pem", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ std::string name_us_az;
+ ASSERT_TRUE(LoadTestName("name-us-arizona.pem", &name_us_az));
+
+ // No constraints on directoryName type, so name_us_az should be allowed when
+ // subjectAltName is not present.
+ EXPECT_TRUE(
+ name_constraints.IsPermittedCert(SequenceValueFromString(&name_us_az),
+ der::Input(), false /* is_leaf_cert */));
+
+ std::string san;
+ ASSERT_TRUE(LoadTestSubjectAltName("san-invalid-empty.pem", &san));
+ // Should fail if subjectAltName is present but empty.
+ EXPECT_FALSE(name_constraints.IsPermittedCert(
+ SequenceValueFromString(&name_us_az), InputFromString(&san),
+ false /* is_leaf_cert */));
+ EXPECT_FALSE(name_constraints.IsPermittedCert(
+ SequenceValueFromString(&name_us_az), InputFromString(&san),
+ true /* is_leaf_cert */));
+}
+
+} // namespace net

Powered by Google App Engine
This is Rietveld 408576698