| Index: net/http/http_security_headers_unittest.cc
|
| diff --git a/net/http/http_security_headers_unittest.cc b/net/http/http_security_headers_unittest.cc
|
| index d09f6fd308d49ab6dc5c207f6b8d91b72aad52ad..234c5f076ece48c8bc597cb5f3cf9868ec5334dc 100644
|
| --- a/net/http/http_security_headers_unittest.cc
|
| +++ b/net/http/http_security_headers_unittest.cc
|
| @@ -26,21 +26,38 @@ HashValue GetTestHashValue(uint8 label, HashValueTag tag) {
|
| return hash_value;
|
| }
|
|
|
| -std::string GetTestPin(uint8 label, HashValueTag tag) {
|
| +std::string GetTestPinImpl(uint8 label, HashValueTag tag, bool quoted) {
|
| HashValue hash_value = GetTestHashValue(label, tag);
|
| std::string base64;
|
| base::Base64Encode(base::StringPiece(
|
| reinterpret_cast<char*>(hash_value.data()), hash_value.size()), &base64);
|
|
|
| + std::string ret;
|
| switch (hash_value.tag) {
|
| case HASH_VALUE_SHA1:
|
| - return std::string("pin-sha1=\"") + base64 + "\"";
|
| + ret = "pin-sha1=";
|
| + break;
|
| case HASH_VALUE_SHA256:
|
| - return std::string("pin-sha256=\"") + base64 + "\"";
|
| + ret = "pin-sha256=";
|
| + break;
|
| default:
|
| NOTREACHED() << "Unknown HashValueTag " << hash_value.tag;
|
| return std::string("ERROR");
|
| }
|
| + if (quoted)
|
| + ret += '\"';
|
| + ret += base64;
|
| + if (quoted)
|
| + ret += '\"';
|
| + return ret;
|
| +}
|
| +
|
| +std::string GetTestPin(uint8 label, HashValueTag tag) {
|
| + return GetTestPinImpl(label, tag, true);
|
| +}
|
| +
|
| +std::string GetTestPinUnquoted(uint8 label, HashValueTag tag) {
|
| + return GetTestPinImpl(label, tag, false);
|
| }
|
|
|
| };
|
| @@ -142,6 +159,7 @@ static void TestBogusPinsHeaders(HashValueTag tag) {
|
|
|
| // The good pin must be in the chain, the backup pin must not be
|
| std::string good_pin = GetTestPin(2, tag);
|
| + std::string good_pin_unquoted = GetTestPinUnquoted(2, tag);
|
| std::string backup_pin = GetTestPin(4, tag);
|
|
|
| EXPECT_FALSE(ParseHPKPHeader(std::string(), chain_hashes, &max_age,
|
| @@ -213,6 +231,9 @@ static void TestBogusPinsHeaders(HashValueTag tag) {
|
| &hashes));
|
| EXPECT_FALSE(ParseHPKPHeader("max-age=34889.23", chain_hashes, &max_age,
|
| &include_subdomains, &hashes));
|
| + EXPECT_FALSE(
|
| + ParseHPKPHeader("max-age=243; " + good_pin_unquoted + ";" + backup_pin,
|
| + chain_hashes, &max_age, &include_subdomains, &hashes));
|
|
|
| // Check the out args were not updated by checking the default
|
| // values for its predictable fields.
|
| @@ -391,6 +412,7 @@ static void TestValidPKPHeaders(HashValueTag tag) {
|
|
|
| // The good pin must be in the chain, the backup pin must not be
|
| std::string good_pin = GetTestPin(2, tag);
|
| + std::string good_pin2 = GetTestPin(3, tag);
|
| std::string backup_pin = GetTestPin(4, tag);
|
|
|
| EXPECT_TRUE(ParseHPKPHeader(
|
| @@ -468,8 +490,7 @@ static void TestValidPKPHeaders(HashValueTag tag) {
|
| EXPECT_EQ(expect_max_age, max_age);
|
| EXPECT_FALSE(include_subdomains);
|
|
|
| - // Test that parsing the same header twice doesn't duplicate the recorded
|
| - // hashes.
|
| + // Test that parsing a different header resets the hashes.
|
| hashes.clear();
|
| EXPECT_TRUE(ParseHPKPHeader(
|
| " max-age=999; " +
|
| @@ -477,9 +498,8 @@ static void TestValidPKPHeaders(HashValueTag tag) {
|
| chain_hashes, &max_age, &include_subdomains, &hashes));
|
| EXPECT_EQ(2u, hashes.size());
|
| EXPECT_TRUE(ParseHPKPHeader(
|
| - " max-age=999; " +
|
| - backup_pin + ";" + good_pin + "; ",
|
| - chain_hashes, &max_age, &include_subdomains, &hashes));
|
| + " max-age=999; " + backup_pin + ";" + good_pin2 + "; ", chain_hashes,
|
| + &max_age, &include_subdomains, &hashes));
|
| EXPECT_EQ(2u, hashes.size());
|
| }
|
|
|
| @@ -715,4 +735,41 @@ TEST_F(HttpSecurityHeadersTest, NoClobberPins) {
|
| &failure_log));
|
| }
|
|
|
| +// Tests that seeing an invalid HPKP header leaves the existing one alone.
|
| +TEST_F(HttpSecurityHeadersTest, IgnoreInvalidHeaders) {
|
| + TransportSecurityState state;
|
| +
|
| + HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA256);
|
| + std::string good_pin = GetTestPin(1, HASH_VALUE_SHA256);
|
| + std::string bad_pin = GetTestPin(2, HASH_VALUE_SHA256);
|
| + std::string backup_pin = GetTestPin(3, HASH_VALUE_SHA256);
|
| +
|
| + SSLInfo ssl_info;
|
| + ssl_info.public_key_hashes.push_back(good_hash);
|
| +
|
| + // Add a valid HPKP header.
|
| + EXPECT_TRUE(state.AddHPKPHeader(
|
| + "example.com", "max-age = 10000; " + good_pin + "; " + backup_pin,
|
| + ssl_info));
|
| +
|
| + // Check the insertion was valid.
|
| + EXPECT_TRUE(state.HasPublicKeyPins("example.com"));
|
| + std::string failure_log;
|
| + bool is_issued_by_known_root = true;
|
| + EXPECT_TRUE(state.CheckPublicKeyPins("example.com", is_issued_by_known_root,
|
| + ssl_info.public_key_hashes,
|
| + &failure_log));
|
| +
|
| + // Now assert an invalid one. This should fail.
|
| + EXPECT_FALSE(state.AddHPKPHeader(
|
| + "example.com", "max-age = 10000; " + bad_pin + "; " + backup_pin,
|
| + ssl_info));
|
| +
|
| + // The old pins must still exist.
|
| + EXPECT_TRUE(state.HasPublicKeyPins("example.com"));
|
| + EXPECT_TRUE(state.CheckPublicKeyPins("example.com", is_issued_by_known_root,
|
| + ssl_info.public_key_hashes,
|
| + &failure_log));
|
| +}
|
| +
|
| }; // namespace net
|
|
|