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

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: use test_helpers.h 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..c025f5bfab33a7eb6fd4a83ab22ebe9776ee6eba
--- /dev/null
+++ b/net/cert/internal/name_constraints_unittest.cc
@@ -0,0 +1,1095 @@
+// 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 "net/der/parser.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace {
+
+der::Input SequenceValueFromString(const std::string* s) {
eroman 2015/08/26 19:56:44 This is the same function used in verify_name_matc
mattm 2015/08/29 01:37:19 Done.
+ der::Parser parser(InputFromString(s));
+ der::Input data;
+ if (!parser.ReadTag(der::kSequence, &data)) {
+ EXPECT_TRUE(false);
+ return der::Input();
+ }
+ if (parser.HasMore()) {
+ EXPECT_TRUE(false);
+ return der::Input();
+ }
+ return data;
+}
+
+::testing::AssertionResult LoadTestData(const std::string& token,
+ const std::string& basename,
+ std::string* result) {
+ std::string path = "net/data/name_constraints_unittest/name_constraints/" +
+ basename + ".pem";
+
+ const PemBlockMapping mappings[] = {
+ {token.c_str(), result},
eroman 2015/08/26 19:56:44 This reads funny. Can you either change the |toke|
mattm 2015/08/29 01:37:19 Done.
+ };
+
+ 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);
+}
+
+const int kOtherNameFlag = 1 << 0;
+const int kRfc822NameFlag = 1 << 1;
+const int kDnsNameFlag = 1 << 2;
+const int kX400AddressFlag = 1 << 3;
+const int kDirectoryNameFlag = 1 << 4;
+const int kEdiPartyNameFlag = 1 << 5;
+const int kUniformResourceIdentifierFlag = 1 << 6;
+const int kIpAddressFlag = 1 << 7;
+const int kRegisteredIdFlag = 1 << 8;
+const int kAllFlags = (1 << 9) - 1;
+::testing::AssertionResult CheckNotPresent(
eroman 2015/08/26 19:56:44 nit: newline
mattm 2015/08/29 01:37:19 Done.
+ const NameConstraints& name_constraints,
+ int flag) {
+ if (flag & kOtherNameFlag && !name_constraints.IsPermittedOtherName())
+ return ::testing::AssertionFailure() << "contained otherNames";
+ if (flag & kRfc822NameFlag && !name_constraints.IsPermittedRFC822Name())
+ return ::testing::AssertionFailure() << "contained rfc822Names";
+ if (flag & kDnsNameFlag) {
+ if (!name_constraints.IsPermittedDNSName("a") ||
+ !name_constraints.IsPermittedDNSName("b"))
+ return ::testing::AssertionFailure() << "contained dNSNames";
+ }
+ if (flag & kX400AddressFlag && !name_constraints.IsPermittedX400Address())
+ return ::testing::AssertionFailure() << "contained x400Addresses";
+ if (flag & kDirectoryNameFlag) {
+ std::string name_us;
+ ::testing::AssertionResult r(::testing::AssertionFailure());
+ if (!(r = LoadTestName("name-us", &name_us)))
+ return r;
+ std::string name_jp;
+ if (!(r = LoadTestName("name-jp", &name_jp)))
+ return r;
+ std::string name_de;
+ if (!(r = LoadTestName("name-de", &name_de)))
+ return r;
+ std::string name_ca;
+ if (!(r = LoadTestName("name-ca", &name_ca)))
+ return r;
+ if (!name_constraints.IsPermittedDirectoryName(
+ SequenceValueFromString(&name_us)) ||
+ !name_constraints.IsPermittedDirectoryName(
+ SequenceValueFromString(&name_jp)) ||
+ !name_constraints.IsPermittedDirectoryName(
+ SequenceValueFromString(&name_de)) ||
+ !name_constraints.IsPermittedDirectoryName(
+ SequenceValueFromString(&name_ca))) {
+ return ::testing::AssertionFailure() << "contained directoryNames";
+ }
+ }
+ if (flag & kEdiPartyNameFlag && !name_constraints.IsPermittedEdiPartyName())
+ return ::testing::AssertionFailure() << "contained ediPartyNames";
+ if (flag & kUniformResourceIdentifierFlag &&
+ !name_constraints.IsPermittedURI()) {
+ return ::testing::AssertionFailure()
+ << "contained uniformResourceIdentifiers";
+ }
+ if (flag & kIpAddressFlag) {
+ const uint8_t ip4a[] = {192, 168, 0, 1};
+ const uint8_t ip4b[] = {255, 255, 255, 255};
+ // clang-format off
+ const uint8_t ip6a[] = {1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16};
+ const uint8_t ip6b[] = {255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255};
+ // clang-format on
+ if (!name_constraints.IsPermittedIP(
+ IPAddressNumber(ip4a, ip4a + arraysize(ip4a))) ||
+ !name_constraints.IsPermittedIP(
+ IPAddressNumber(ip4b, ip4b + arraysize(ip4b))) ||
+ !name_constraints.IsPermittedIP(
+ IPAddressNumber(ip6a, ip6a + arraysize(ip6a))) ||
+ !name_constraints.IsPermittedIP(
+ IPAddressNumber(ip6b, ip6b + arraysize(ip6b)))) {
+ return ::testing::AssertionFailure() << "contained iPAddresses";
+ }
+ }
+ if (flag & kRegisteredIdFlag && !name_constraints.IsPermittedRegisteredId())
+ return ::testing::AssertionFailure() << "contained registeredIDs";
+
+ return ::testing::AssertionSuccess();
+}
+
+} // 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", &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_TRUE(CheckNotPresent(name_constraints, kAllFlags & ~kDnsNameFlag));
+
+ std::string san;
+ ASSERT_TRUE(LoadTestSubjectAltName("san-permitted", &san));
+ EXPECT_TRUE(name_constraints.IsPermittedCert(der::Input(),
+ InputFromString(&san), true));
+
+ ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-dnsname", &san));
+ EXPECT_FALSE(name_constraints.IsPermittedCert(der::Input(),
+ InputFromString(&san), true));
+
+ ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-directoryname", &san));
+ EXPECT_TRUE(name_constraints.IsPermittedCert(der::Input(),
+ InputFromString(&san), true));
+
+ ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-ipaddress", &san));
+ EXPECT_TRUE(name_constraints.IsPermittedCert(der::Input(),
+ InputFromString(&san), true));
+}
+
+TEST_P(ParseNameConstraints, DNSNames_ExcludeOnly) {
eroman 2015/08/26 19:56:44 Underscores in Gtest names are discouraged/banned:
mattm 2015/08/29 01:37:19 Done.
+ std::string a;
+ ASSERT_TRUE(LoadTestNameConstraint("dnsname-excluded", &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, DNSNames_ExcludeAll) {
+ std::string a;
+ ASSERT_TRUE(LoadTestNameConstraint("dnsname-excludeall", &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", &constraints_der));
eroman 2015/08/26 19:56:44 nit: I find it more readable to include the ".pem"
mattm 2015/08/29 01:37:19 Done.
+
+ std::string name_us;
+ ASSERT_TRUE(LoadTestName("name-us", &name_us));
+ std::string name_us_ca;
+ ASSERT_TRUE(LoadTestName("name-us-california", &name_us_ca));
+ std::string name_us_ca_mountain_view;
+ ASSERT_TRUE(LoadTestName("name-us-california-mountain_view",
+ &name_us_ca_mountain_view));
+ std::string name_us_az;
+ ASSERT_TRUE(LoadTestName("name-us-arizona", &name_us_az));
+ std::string name_jp;
+ ASSERT_TRUE(LoadTestName("name-jp", &name_jp));
+ std::string name_jp_tokyo;
+ ASSERT_TRUE(LoadTestName("name-jp-tokyo", &name_jp_tokyo));
+ std::string name_de;
+ ASSERT_TRUE(LoadTestName("name-de", &name_de));
+ std::string name_ca;
+ ASSERT_TRUE(LoadTestName("name-ca", &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_TRUE(
+ CheckNotPresent(name_constraints, kAllFlags & ~kDirectoryNameFlag));
+
+ // 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", &san));
+ EXPECT_TRUE(name_constraints.IsPermittedCert(der::Input(),
+ InputFromString(&san), true));
+
+ ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-dnsname", &san));
+ EXPECT_TRUE(name_constraints.IsPermittedCert(der::Input(),
+ InputFromString(&san), true));
+
+ ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-directoryname", &san));
+ EXPECT_FALSE(name_constraints.IsPermittedCert(der::Input(),
+ InputFromString(&san), true));
+
+ ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-ipaddress", &san));
+ EXPECT_TRUE(name_constraints.IsPermittedCert(der::Input(),
+ InputFromString(&san), true));
+}
+
+TEST_P(ParseNameConstraints, DirectoryNames_ExcludeOnly) {
+ std::string constraints_der;
+ ASSERT_TRUE(
+ LoadTestNameConstraint("directoryname-excluded", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ std::string name_empty;
+ ASSERT_TRUE(LoadTestName("name-empty", &name_empty));
+ std::string name_us;
+ ASSERT_TRUE(LoadTestName("name-us", &name_us));
+ std::string name_us_ca;
+ ASSERT_TRUE(LoadTestName("name-us-california", &name_us_ca));
+ std::string name_us_ca_mountain_view;
+ ASSERT_TRUE(LoadTestName("name-us-california-mountain_view",
+ &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, DirectoryNames_ExcludeAll) {
+ std::string constraints_der;
+ ASSERT_TRUE(
+ LoadTestNameConstraint("directoryname-excluded", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ std::string name_empty;
+ ASSERT_TRUE(LoadTestName("name-empty", &name_empty));
+ std::string name_us;
+ ASSERT_TRUE(LoadTestName("name-us", &name_us));
+ std::string name_us_ca;
+ ASSERT_TRUE(LoadTestName("name-us-california", &name_us_ca));
+ std::string name_us_ca_mountain_view;
+ ASSERT_TRUE(LoadTestName("name-us-california-mountain_view",
+ &name_us_ca_mountain_view));
+ std::string name_jp;
+ ASSERT_TRUE(LoadTestName("name-jp", &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", &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_TRUE(CheckNotPresent(name_constraints, kAllFlags & ~kIpAddressFlag));
+
+ std::string san;
+ ASSERT_TRUE(LoadTestSubjectAltName("san-permitted", &san));
+ EXPECT_TRUE(name_constraints.IsPermittedCert(der::Input(),
+ InputFromString(&san), true));
+
+ ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-dnsname", &san));
+ EXPECT_TRUE(name_constraints.IsPermittedCert(der::Input(),
+ InputFromString(&san), true));
+
+ ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-directoryname", &san));
+ EXPECT_TRUE(name_constraints.IsPermittedCert(der::Input(),
+ InputFromString(&san), true));
+
+ ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-ipaddress", &san));
+ EXPECT_FALSE(name_constraints.IsPermittedCert(der::Input(),
+ InputFromString(&san), true));
+}
+
+TEST_P(ParseNameConstraints, IPAdresses_ExcludeOnly) {
+ std::string a;
+ ASSERT_TRUE(LoadTestNameConstraint("ipaddress-excluded", &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, IPAdresses_ExcludeAll) {
+ std::string a;
+ ASSERT_TRUE(LoadTestNameConstraint("ipaddress-excludeall", &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", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ if (is_critical()) {
+ EXPECT_FALSE(name_constraints.IsPermittedOtherName());
+ EXPECT_TRUE(CheckNotPresent(name_constraints, kAllFlags & ~kOtherNameFlag));
+ } else {
+ EXPECT_TRUE(CheckNotPresent(name_constraints, kAllFlags));
+ }
+}
+
+TEST_P(ParseNameConstraints, otherNamesInExcluded) {
+ std::string constraints_der;
+ ASSERT_TRUE(LoadTestNameConstraint("othername-excluded", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ if (is_critical()) {
+ EXPECT_FALSE(name_constraints.IsPermittedOtherName());
+ EXPECT_TRUE(CheckNotPresent(name_constraints, kAllFlags & ~kOtherNameFlag));
+ } else {
+ EXPECT_TRUE(CheckNotPresent(name_constraints, kAllFlags));
+ }
+}
+
+TEST_P(ParseNameConstraints, Rfc822NamesInPermitted) {
+ std::string constraints_der;
+ ASSERT_TRUE(LoadTestNameConstraint("rfc822name-permitted", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ if (is_critical()) {
+ EXPECT_FALSE(name_constraints.IsPermittedRFC822Name());
+ EXPECT_TRUE(
+ CheckNotPresent(name_constraints, kAllFlags & ~kRfc822NameFlag));
+ } else {
+ EXPECT_TRUE(CheckNotPresent(name_constraints, kAllFlags));
+ }
+}
+
+TEST_P(ParseNameConstraints, Rfc822NamesInExcluded) {
+ std::string constraints_der;
+ ASSERT_TRUE(LoadTestNameConstraint("rfc822name-excluded", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ if (is_critical()) {
+ EXPECT_FALSE(name_constraints.IsPermittedRFC822Name());
+ EXPECT_TRUE(
+ CheckNotPresent(name_constraints, kAllFlags & ~kRfc822NameFlag));
+ } else {
+ EXPECT_TRUE(CheckNotPresent(name_constraints, kAllFlags));
+ }
+}
+
+TEST_P(ParseNameConstraints, x400AddresssInPermitted) {
+ std::string constraints_der;
+ ASSERT_TRUE(
+ LoadTestNameConstraint("x400address-permitted", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ if (is_critical()) {
+ EXPECT_FALSE(name_constraints.IsPermittedX400Address());
+ EXPECT_TRUE(
+ CheckNotPresent(name_constraints, kAllFlags & ~kX400AddressFlag));
+ } else {
+ EXPECT_TRUE(CheckNotPresent(name_constraints, kAllFlags));
+ }
+}
+
+TEST_P(ParseNameConstraints, x400AddresssInExcluded) {
+ std::string constraints_der;
+ ASSERT_TRUE(LoadTestNameConstraint("x400address-excluded", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ if (is_critical()) {
+ EXPECT_FALSE(name_constraints.IsPermittedX400Address());
+ EXPECT_TRUE(
+ CheckNotPresent(name_constraints, kAllFlags & ~kX400AddressFlag));
+ } else {
+ EXPECT_TRUE(CheckNotPresent(name_constraints, kAllFlags));
+ }
+}
+
+TEST_P(ParseNameConstraints, ediPartyNamesInPermitted) {
+ std::string constraints_der;
+ ASSERT_TRUE(
+ LoadTestNameConstraint("edipartyname-permitted", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ if (is_critical()) {
+ EXPECT_FALSE(name_constraints.IsPermittedEdiPartyName());
+ EXPECT_TRUE(
+ CheckNotPresent(name_constraints, kAllFlags & ~kEdiPartyNameFlag));
+ } else {
+ EXPECT_TRUE(CheckNotPresent(name_constraints, kAllFlags));
+ }
+}
+
+TEST_P(ParseNameConstraints, ediPartyNamesInExcluded) {
+ std::string constraints_der;
+ ASSERT_TRUE(
+ LoadTestNameConstraint("edipartyname-excluded", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ if (is_critical()) {
+ EXPECT_FALSE(name_constraints.IsPermittedEdiPartyName());
+ EXPECT_TRUE(
+ CheckNotPresent(name_constraints, kAllFlags & ~kEdiPartyNameFlag));
+ } else {
+ EXPECT_TRUE(CheckNotPresent(name_constraints, kAllFlags));
+ }
+}
+
+TEST_P(ParseNameConstraints, registeredIDsInPermitted) {
+ std::string constraints_der;
+ ASSERT_TRUE(
+ LoadTestNameConstraint("registeredid-permitted", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ if (is_critical()) {
+ EXPECT_FALSE(name_constraints.IsPermittedRegisteredId());
+ EXPECT_TRUE(
+ CheckNotPresent(name_constraints, kAllFlags & ~kRegisteredIdFlag));
+ } else {
+ EXPECT_TRUE(CheckNotPresent(name_constraints, kAllFlags));
+ }
+}
+
+TEST_P(ParseNameConstraints, registeredIDsInExcluded) {
+ std::string constraints_der;
+ ASSERT_TRUE(
+ LoadTestNameConstraint("registeredid-excluded", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ if (is_critical()) {
+ EXPECT_FALSE(name_constraints.IsPermittedRegisteredId());
+ EXPECT_TRUE(
+ CheckNotPresent(name_constraints, kAllFlags & ~kRegisteredIdFlag));
+ } else {
+ EXPECT_TRUE(CheckNotPresent(name_constraints, kAllFlags));
+ }
+}
+
+TEST_P(ParseNameConstraints,
+ failsOnGeneralSubtreeWithMinimumZeroEncodedUnnecessarily) {
+ std::string constraints_der;
+ ASSERT_TRUE(LoadTestNameConstraint("dnsname-with_min_0", &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", &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", &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", &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", &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", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_FALSE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+}
+
+TEST_P(ParseNameConstraints, IsPermittedCert_SubjectEmailAddress_ok) {
+ std::string constraints_der;
+ ASSERT_TRUE(LoadTestNameConstraint("directoryname", &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", &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, IsPermittedCert_SubjectEmailAddress_notok) {
+ std::string constraints_der;
+ ASSERT_TRUE(LoadTestNameConstraint("rfc822name-permitted", &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", &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, IsPermittedCert_SubjectDnsNames) {
+ std::string constraints_der;
+ ASSERT_TRUE(LoadTestNameConstraint("dnsname", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ ASSERT_TRUE(LoadTestNameConstraint("directoryname", &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", &name_us_az));
+ std::string name_us_az_foocom;
+ ASSERT_TRUE(LoadTestName("name-us-arizona-foo.com", &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",
+ &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",
+ &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, IsPermittedCert_SubjectIpAddresses) {
+ std::string constraints_der;
+ ASSERT_TRUE(LoadTestNameConstraint("ipaddress", &constraints_der));
+ NameConstraints name_constraints;
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ ASSERT_TRUE(LoadTestNameConstraint("directoryname", &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", &constraints_der));
+ EXPECT_TRUE(
+ name_constraints.Parse(InputFromString(&constraints_der), is_critical()));
+
+ std::string name_us_az;
+ ASSERT_TRUE(LoadTestName("name-us-arizona", &name_us_az));
+ std::string name_us_az_1_1_1_1;
+ ASSERT_TRUE(LoadTestName("name-us-arizona-1.1.1.1", &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", &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", &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", &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, IsPermittedCert_Subject_commonName_encodings) {
+ std::string constraints_der;
+ ASSERT_TRUE(LoadTestNameConstraint("ipaddress", &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",
+ &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",
+ &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 */));
+}
+
+} // namespace net

Powered by Google App Engine
This is Rietveld 408576698