| Index: net/tools/transport_security_state_generator/input_file_parsers_unittest.cc
|
| diff --git a/net/tools/transport_security_state_generator/input_file_parsers_unittest.cc b/net/tools/transport_security_state_generator/input_file_parsers_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..3badbf88d96251bee9d0f2d20776b3a9d8a61cef
|
| --- /dev/null
|
| +++ b/net/tools/transport_security_state_generator/input_file_parsers_unittest.cc
|
| @@ -0,0 +1,377 @@
|
| +// Copyright 2017 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 <string>
|
| +#include <vector>
|
| +
|
| +#include "net/tools/transport_security_state_generator/input_file_parsers.h"
|
| +#include "net/tools/transport_security_state_generator/pinsets.h"
|
| +#include "net/tools/transport_security_state_generator/transport_security_state_entry.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +namespace net {
|
| +
|
| +namespace transport_security_state {
|
| +
|
| +// Test that all values are correctly parsed from a valid JSON input.
|
| +TEST(InputFileParsersTest, ParseJSON) {
|
| + std::string valid =
|
| + "{"
|
| + " \"pinsets\": [{"
|
| + " \"name\": \"test\","
|
| + " \"static_spki_hashes\": [\"TestSPKI\"],"
|
| + " \"bad_static_spki_hashes\": [\"BadTestSPKI\"],"
|
| + " \"report_uri\": \"https://hpkp-log.example.com\""
|
| + " }],"
|
| + " \"entries\": ["
|
| + " {"
|
| + " \"name\": \"hsts.example.com\","
|
| + " \"mode\": \"force-https\", "
|
| + " \"include_subdomains\": true"
|
| + " }, {"
|
| + " \"name\": \"hpkp.example.com\","
|
| + " \"pins\": \"thepinset\","
|
| + " \"include_subdomains_for_pinning\": true"
|
| + " }, {"
|
| + " \"name\": \"expect-ct.example.com\","
|
| + " \"expect_ct\": true,"
|
| + " \"expect_ct_report_uri\": \"https://expect-ct-log.example.com\""
|
| + " }, {"
|
| + " \"name\": \"expect-staple.example.com\","
|
| + " \"expect_staple\": true,"
|
| + " \"expect_staple_report_uri\": "
|
| + "\"https://expect-staple-log.example.com\","
|
| + " \"include_subdomains_for_expect_staple\": true"
|
| + " }"
|
| + " ],"
|
| + " \"domain_ids\": ["
|
| + " \"NOT_PINNED\","
|
| + " \"EXAMPLE_COM\""
|
| + " ]"
|
| + "}";
|
| +
|
| + TransportSecurityStateEntries entries;
|
| + Pinsets pinsets;
|
| + DomainIDList domain_ids;
|
| + std::vector<std::string> errors;
|
| +
|
| + EXPECT_TRUE(ParseJSON(valid, &entries, &pinsets, &domain_ids, &errors));
|
| + EXPECT_EQ(0U, errors.size());
|
| +
|
| + ASSERT_EQ(1U, pinsets.size());
|
| + PinsetMap::const_iterator pinset = pinsets.pinsets().find("test");
|
| + ASSERT_NE(pinset, pinsets.pinsets().cend());
|
| + EXPECT_EQ("test", pinset->second->name());
|
| + EXPECT_EQ("https://hpkp-log.example.com", pinset->second->report_uri());
|
| +
|
| + ASSERT_EQ(1U, pinset->second->static_spki_hashes().size());
|
| + EXPECT_EQ("TestSPKI", pinset->second->static_spki_hashes()[0]);
|
| +
|
| + ASSERT_EQ(1U, pinset->second->bad_static_spki_hashes().size());
|
| + EXPECT_EQ("BadTestSPKI", pinset->second->bad_static_spki_hashes()[0]);
|
| +
|
| + ASSERT_EQ(4U, entries.size());
|
| + TransportSecurityStateEntry* entry = entries[0].get();
|
| + EXPECT_EQ("hsts.example.com", entry->hostname);
|
| + EXPECT_TRUE(entry->force_https);
|
| + EXPECT_FALSE(entry->hpkp_include_subdomains);
|
| + EXPECT_EQ("", entry->pinset);
|
| + EXPECT_FALSE(entry->expect_ct);
|
| + EXPECT_EQ("", entry->expect_ct_report_uri);
|
| + EXPECT_FALSE(entry->expect_staple);
|
| + EXPECT_FALSE(entry->expect_staple_include_subdomains);
|
| + EXPECT_EQ("", entry->expect_staple_report_uri);
|
| +
|
| + entry = entries[1].get();
|
| + EXPECT_EQ("hpkp.example.com", entry->hostname);
|
| + EXPECT_FALSE(entry->force_https);
|
| + EXPECT_TRUE(entry->hpkp_include_subdomains);
|
| + EXPECT_EQ("thepinset", entry->pinset);
|
| + EXPECT_FALSE(entry->expect_ct);
|
| + EXPECT_EQ("", entry->expect_ct_report_uri);
|
| + EXPECT_FALSE(entry->expect_staple);
|
| + EXPECT_FALSE(entry->expect_staple_include_subdomains);
|
| + EXPECT_EQ("", entry->expect_staple_report_uri);
|
| +
|
| + entry = entries[2].get();
|
| + EXPECT_EQ("expect-ct.example.com", entry->hostname);
|
| + EXPECT_FALSE(entry->force_https);
|
| + EXPECT_FALSE(entry->hpkp_include_subdomains);
|
| + EXPECT_EQ("", entry->pinset);
|
| + EXPECT_TRUE(entry->expect_ct);
|
| + EXPECT_EQ("https://expect-ct-log.example.com", entry->expect_ct_report_uri);
|
| + EXPECT_FALSE(entry->expect_staple);
|
| + EXPECT_FALSE(entry->expect_staple_include_subdomains);
|
| + EXPECT_EQ("", entry->expect_staple_report_uri);
|
| +
|
| + entry = entries[3].get();
|
| + EXPECT_EQ("expect-staple.example.com", entry->hostname);
|
| + EXPECT_FALSE(entry->force_https);
|
| + EXPECT_FALSE(entry->hpkp_include_subdomains);
|
| + EXPECT_EQ("", entry->pinset);
|
| + EXPECT_FALSE(entry->expect_ct);
|
| + EXPECT_EQ("", entry->expect_ct_report_uri);
|
| + EXPECT_TRUE(entry->expect_staple);
|
| + EXPECT_TRUE(entry->expect_staple_include_subdomains);
|
| + EXPECT_EQ("https://expect-staple-log.example.com",
|
| + entry->expect_staple_report_uri);
|
| +
|
| + ASSERT_EQ(2U, domain_ids.size());
|
| + EXPECT_EQ("NOT_PINNED", domain_ids[0]);
|
| + EXPECT_EQ("EXAMPLE_COM", domain_ids[1]);
|
| +}
|
| +
|
| +// Test that parsing valid JSON with missing keys fails.
|
| +TEST(InputFileParsersTest, ParseJSONInvalid) {
|
| + TransportSecurityStateEntries entries;
|
| + Pinsets pinsets;
|
| + DomainIDList domain_ids;
|
| + std::vector<std::string> errors;
|
| +
|
| + std::string no_pinsets =
|
| + "{"
|
| + " \"entries\": [],"
|
| + " \"domain_ids\": []"
|
| + "}";
|
| +
|
| + EXPECT_FALSE(ParseJSON(no_pinsets, &entries, &pinsets, &domain_ids, &errors));
|
| +
|
| + std::string no_entries =
|
| + "{"
|
| + " \"pinsets\": [],"
|
| + " \"domain_ids\": []"
|
| + "}";
|
| +
|
| + EXPECT_FALSE(ParseJSON(no_entries, &entries, &pinsets, &domain_ids, &errors));
|
| +
|
| + std::string no_domain_ids =
|
| + "{"
|
| + " \"pinsets\": [],"
|
| + " \"entries\": []"
|
| + "}\n";
|
| +
|
| + EXPECT_FALSE(
|
| + ParseJSON(no_domain_ids, &entries, &pinsets, &domain_ids, &errors));
|
| +}
|
| +
|
| +// Test that parsing valid JSON with invalid (HSTS) entries fails.
|
| +TEST(InputFileParsersTest, ParseJSONInvalidHSTS) {
|
| + TransportSecurityStateEntries entries;
|
| + Pinsets pinsets;
|
| + DomainIDList domain_ids;
|
| + std::vector<std::string> errors;
|
| +
|
| + std::string missing_hostname =
|
| + "{"
|
| + " \"pinsets\": [],"
|
| + " \"entries\": ["
|
| + " {"
|
| + " \"mode\": \"force-https\""
|
| + " }"
|
| + " ],"
|
| + " \"domain_ids\": []"
|
| + "}";
|
| +
|
| + EXPECT_FALSE(
|
| + ParseJSON(missing_hostname, &entries, &pinsets, &domain_ids, &errors));
|
| +}
|
| +
|
| +// Test that parsing valid JSON invalid (HPKP) entries fails.
|
| +TEST(InputFileParsersTest, ParseJSONInvalidHPKP) {
|
| + TransportSecurityStateEntries entries;
|
| + Pinsets pinsets;
|
| + DomainIDList domain_ids;
|
| + std::vector<std::string> errors;
|
| +
|
| + std::string missing_hostname =
|
| + "{"
|
| + " \"pinsets\": [{"
|
| + " \"static_spki_hashes\": [\"TestSPKI\"],"
|
| + " \"bad_static_spki_hashes\": [\"BadTestSPKI\"],"
|
| + " \"report_uri\": \"https://hpkp-log.example.com\""
|
| + " }],"
|
| + " \"entries\": [],"
|
| + " \"domain_ids\": []"
|
| + "}";
|
| +
|
| + EXPECT_FALSE(
|
| + ParseJSON(missing_hostname, &entries, &pinsets, &domain_ids, &errors));
|
| +}
|
| +
|
| +// Test that non-standard JSON comments don't affect parsing.
|
| +TEST(InputFileParsersTest, ParseJSONComments) {
|
| + std::string valid =
|
| + "// This line should be ignored.\n"
|
| + "{\n"
|
| + "// This line should be ignored.\n"
|
| + " \"pinsets\": [],\n"
|
| + " \"entries\": [\n"
|
| + " {\n"
|
| + "// This line should be ignored.\n"
|
| + " \"name\": \"hsts.example.com\",\n"
|
| + " \"mode\": \"force-https\"\n"
|
| + "// This line should be ignored.\n"
|
| + " }\n"
|
| + " ],\n"
|
| + "// This line should be ignored.\n"
|
| + " \"domain_ids\": [\n"
|
| + " \"NOT_PINNED\"\n"
|
| + " ]\n"
|
| + "// This line should be ignored.\n"
|
| + "}\n";
|
| +
|
| + TransportSecurityStateEntries entries;
|
| + Pinsets pinsets;
|
| + DomainIDList domain_ids;
|
| + std::vector<std::string> errors;
|
| +
|
| + EXPECT_TRUE(ParseJSON(valid, &entries, &pinsets, &domain_ids, &errors));
|
| + EXPECT_EQ(0U, errors.size());
|
| +
|
| + EXPECT_EQ(0U, pinsets.size());
|
| +
|
| + ASSERT_EQ(1U, entries.size());
|
| + EXPECT_EQ("hsts.example.com", entries[0]->hostname);
|
| + EXPECT_TRUE(entries[0]->force_https);
|
| +
|
| + ASSERT_EQ(1U, domain_ids.size());
|
| + EXPECT_EQ("NOT_PINNED", domain_ids[0]);
|
| +}
|
| +
|
| +// Test parsing of all 3 SPKI formats.
|
| +TEST(InputFileParsersTest, ParseCertificatesFile) {
|
| + std::string valid =
|
| + "# This line should ignored. The rest should result in 3 pins.\n"
|
| + "TestPublicKey1\n"
|
| + "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\n"
|
| + "\n"
|
| + "TestPublicKey2\n"
|
| + "-----BEGIN PUBLIC KEY-----\n"
|
| + "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAujzwcb5bJuC/A/Y9izGl\n"
|
| + "LlA3fnKGbeyn53BdVznJN4fQwU82WKVYdqt8d/1ZDRdYyhGrTgXJeCURe9VSJyX1\n"
|
| + "X2a5EApSFsopP8Yjy0Rl6dNOLO84KCW9dPmfHC3uP0ac4hnHT5dUr05YvhJmHCkf\n"
|
| + "as6v/aEgpPLDhRF6UruSUh+gIpUg/F3+vlD99HLfbloukoDtQyxW+86s9sO7RQ00\n"
|
| + "pd79VOoa/v09FvoS7MFgnBBOtvBQLOXjEH7/qBsnrXFtHBeOtxSLar/FL3OhVXuh\n"
|
| + "dUTRyc1Mg0ECtz8zHZugW+LleIm5Bf5Yr0bN1O/HfDPCkDaCldcm6xohEHn9pBaW\n"
|
| + "+wIDAQAB\n"
|
| + "-----END PUBLIC KEY-----\n"
|
| + "\n"
|
| + "# The 'Chromium' prefix is required here.\n"
|
| + "ChromiumTestCertificate3\n"
|
| + "-----BEGIN CERTIFICATE-----\n"
|
| + "MIIDeTCCAmGgAwIBAgIJAMRHXuiAgufAMA0GCSqGSIb3DQEBCwUAMFMxETAPBgNV\n"
|
| + "BAMMCENocm9taXVtMR4wHAYDVQQKDBVUaGUgQ2hyb21pdW0gUHJvamVjdHMxETAP\n"
|
| + "BgNVBAsMCFNlY3VyaXR5MQswCQYDVQQGEwJVUzAeFw0xNzAyMDExOTAyMzFaFw0x\n"
|
| + "ODAyMDExOTAyMzFaMFMxETAPBgNVBAMMCENocm9taXVtMR4wHAYDVQQKDBVUaGUg\n"
|
| + "Q2hyb21pdW0gUHJvamVjdHMxETAPBgNVBAsMCFNlY3VyaXR5MQswCQYDVQQGEwJV\n"
|
| + "UzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALtggpf5vNVsmQrJKTQe\n"
|
| + "ynTeOzVOyROGDugGtR+Cri8WlNg1UAlIyYIS8txZ4oCknsT8gs3TFfu0wxmWNxx5\n"
|
| + "4oLGy2BQOHH00dgBAsKgqX//mY4mH5AZ85UFYni1hj9aszIJMIBWtgbNGVkppW65\n"
|
| + "8maF1KVdHmxXMvtKxn/9UsusH/A0ng5UJDYBPISQMv0XqIlv0wdVTIVWIcQhOjWz\n"
|
| + "MGwFDSjxS1WgEnPgd4Qi7MYaDbUTsXGtWba83vZJ8CQzjLumSJJCnz2aquGmraX0\n"
|
| + "J0joUjB4fuYL8xrbDqnFmADvozMMVkZ4843w8ikvJkM8nWoIXexVvirfXDoqtdUo\n"
|
| + "YOcCAwEAAaNQME4wHQYDVR0OBBYEFGJ6O/oLtzpb4OWvrEFxieYb1JbsMB8GA1Ud\n"
|
| + "IwQYMBaAFGJ6O/oLtzpb4OWvrEFxieYb1JbsMAwGA1UdEwQFMAMBAf8wDQYJKoZI\n"
|
| + "hvcNAQELBQADggEBAFpt9jlBT6OsfKFAJZnmExbW8JlsqXOJAaR+nD1XOnp6o+DM\n"
|
| + "NIguj9+wJOW34OM+2Om0n+KMYbDER0p4g3gxoaDblu7otgnC0OTOnx3DPUYab0jr\n"
|
| + "uT6O4C3/nfWW5sl3Ni3Y99dmdcqKcmYkHsr7uADLPWsjb+sfUrQQfHHnPwzyUz/A\n"
|
| + "w4rSJ0wxnLOmjk5F5YHMLkNpPrzFA1mFyGIau7THsRIr3B632MLNcOlNR21nOc7i\n"
|
| + "eB4u+OzpcZXuiQg3bqrNp6Xb70OIW1rfNEiCpps4UZyRnZ/nrzByxeHH5zPWWZk9\n"
|
| + "nZtxI+65PFOekOjBpbnRC8v1CfOmUSVKIqWaPys=\n"
|
| + "-----END CERTIFICATE-----";
|
| +
|
| + Pinsets pinsets;
|
| + std::vector<std::string> errors;
|
| + EXPECT_TRUE(ParseCertificatesFile(valid, &pinsets, &errors));
|
| + ASSERT_EQ(3U, pinsets.spki_size());
|
| + EXPECT_EQ(0U, errors.size());
|
| +
|
| + const SPKIHashMap& hashes = pinsets.spki_hashes();
|
| + ASSERT_NE(hashes.cend(), hashes.find("TestPublicKey1"));
|
| + ASSERT_NE(hashes.cend(), hashes.find("TestPublicKey2"));
|
| + ASSERT_NE(hashes.cend(), hashes.find("ChromiumTestCertificate3"));
|
| +}
|
| +
|
| +TEST(InputFileParsersTest, ParseCertificatesFileInvalid) {
|
| + Pinsets pinsets;
|
| + std::vector<std::string> errors;
|
| +
|
| + std::string invalid =
|
| + "TestName\n"
|
| + "unexpected";
|
| + EXPECT_FALSE(ParseCertificatesFile(invalid, &pinsets, &errors));
|
| +}
|
| +
|
| +TEST(InputFileParsersTest, ParseCertificatesFileInvalidName) {
|
| + Pinsets pinsets;
|
| + std::vector<std::string> errors;
|
| +
|
| + std::string invalid_name1 =
|
| + "startsWithSmallLetter\n"
|
| + "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\n";
|
| + EXPECT_FALSE(ParseCertificatesFile(invalid_name1, &pinsets, &errors));
|
| +
|
| + std::string invalid_name2 =
|
| + "Invalid-Characters-In-Name\n"
|
| + "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\n";
|
| + EXPECT_FALSE(ParseCertificatesFile(invalid_name2, &pinsets, &errors));
|
| +
|
| + std::string invalid_name3 =
|
| + "1InvalidName\n"
|
| + "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\n";
|
| + EXPECT_FALSE(ParseCertificatesFile(invalid_name3, &pinsets, &errors));
|
| +
|
| + std::string invalid_name4 =
|
| + "Invalid Name\n"
|
| + "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\n";
|
| + EXPECT_FALSE(ParseCertificatesFile(invalid_name4, &pinsets, &errors));
|
| +}
|
| +
|
| +TEST(InputFileParsersTest, ParseCertificatesFileInvalidCertificateName) {
|
| + Pinsets pinsets;
|
| + std::vector<std::string> errors;
|
| + std::string certificate =
|
| + "-----BEGIN CERTIFICATE-----\n"
|
| + "MIIDIzCCAgugAwIBAgIJALs84KlxWh4GMA0GCSqGSIb3DQEBCwUAMCgxGTAXBgNV\n"
|
| + "BAoMEENocm9taXVtIENsYXNzIDMxCzAJBgNVBAsMAkcxMB4XDTE3MDIwMTE5NTUw\n"
|
| + "NVoXDTE4MDIwMTE5NTUwNVowKDEZMBcGA1UECgwQQ2hyb21pdW0gQ2xhc3MgMzEL\n"
|
| + "MAkGA1UECwwCRzEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkolrR\n"
|
| + "7gCPm22Cc9psS2Jh1mksVneee5ntEezZ2gEU20y9Z9URBReo8SFvaZcgKkAkca1v\n"
|
| + "552YIG+FBO/u8njxzlHXvuVJ5x2geciqqR4TRhA4jO1ndrNW6nlJfOoYueWbdym3\n"
|
| + "8zwugoULoCtyLyzdiMI5g8iVBQHDh8+K3TZIHar3HS49TjX5u5nv4igO4RfDcFUa\n"
|
| + "h8g+6x5nWoFF8oa3FG0YTN+q6iI1i2JHmj/q03fVPv3WLPGJ3JADau9gO1Lw1/qf\n"
|
| + "R/N3l4MVtjDFFGYzclfqW2UmL6zRirEV0GF2gwSBAGVX3WWhpOcM8rFIWYkZCsI5\n"
|
| + "iUdtwFNBfcKS9sNpAgMBAAGjUDBOMB0GA1UdDgQWBBTm4VJfibducqwb9h4XELn3\n"
|
| + "p6zLVzAfBgNVHSMEGDAWgBTm4VJfibducqwb9h4XELn3p6zLVzAMBgNVHRMEBTAD\n"
|
| + "AQH/MA0GCSqGSIb3DQEBCwUAA4IBAQApTm40RfsZG20IIgWJ62pZ2end/lvaneTh\n"
|
| + "MZSgFnoTRjKkd/5dh22YyKPw9PnpIuiyi85L36COreqZUvbxqRQnpL1oSCRlLBJQ\n"
|
| + "2LcGlF0j0Opa+SY2VWup4XjnYF8CvwMl4obNpSuywTFmkXCRxzN23tn8whNHvWHM\n"
|
| + "BQ7abw8X1KY02uPbHucrpou6KXkKkhyhfML8OD8IRkSM56K6YyedqV97cmEdW0Ie\n"
|
| + "LlpFJQVX13bmojtSNI1zaiCiEenn5xLa/dAlyFT18Mq6y8plioBinVWFYd0qcRoA\n"
|
| + "E2j3m+jTVIv3CZ+ivGxggZQ8ZYN8FJ/iTW3pXGojogHh0NRJJ8dM\n"
|
| + "-----END CERTIFICATE-----";
|
| +
|
| + std::string missing_prefix = "Class3_G1_Test\n" + certificate;
|
| + EXPECT_FALSE(ParseCertificatesFile(missing_prefix, &pinsets, &errors));
|
| + EXPECT_EQ(2U, errors.size());
|
| + errors.clear();
|
| +
|
| + std::string missing_class = "Chromium_G1_Test\n" + certificate;
|
| + EXPECT_FALSE(ParseCertificatesFile(missing_class, &pinsets, &errors));
|
| + EXPECT_EQ(2U, errors.size());
|
| + errors.clear();
|
| +
|
| + std::string missing_number = "Chromium_Class3_Test\n" + certificate;
|
| + EXPECT_FALSE(ParseCertificatesFile(missing_number, &pinsets, &errors));
|
| + EXPECT_EQ(2U, errors.size());
|
| + errors.clear();
|
| +
|
| + std::string valid = "Chromium_Class3_G1_Test\n" + certificate;
|
| + EXPECT_TRUE(ParseCertificatesFile(valid, &pinsets, &errors));
|
| + EXPECT_EQ(0U, errors.size());
|
| +}
|
| +
|
| +} // namespace transport_security_state
|
| +
|
| +} // namespace net
|
|
|