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

Side by Side Diff: net/http/http_security_headers_unittest.cc

Issue 862133002: Update from https://crrev.com/312398 (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 11 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <algorithm> 5 #include <algorithm>
6 6
7 #include "base/base64.h" 7 #include "base/base64.h"
8 #include "base/sha1.h" 8 #include "base/sha1.h"
9 #include "base/strings/string_piece.h" 9 #include "base/strings/string_piece.h"
10 #include "crypto/sha2.h" 10 #include "crypto/sha2.h"
11 #include "net/base/net_log.h" 11 #include "net/base/net_log.h"
12 #include "net/base/test_completion_callback.h" 12 #include "net/base/test_completion_callback.h"
13 #include "net/http/http_security_headers.h" 13 #include "net/http/http_security_headers.h"
14 #include "net/http/http_util.h" 14 #include "net/http/http_util.h"
15 #include "net/http/transport_security_state.h" 15 #include "net/http/transport_security_state.h"
16 #include "net/ssl/ssl_info.h" 16 #include "net/ssl/ssl_info.h"
17 #include "testing/gtest/include/gtest/gtest.h" 17 #include "testing/gtest/include/gtest/gtest.h"
18 18
19 namespace net { 19 namespace net {
20 20
21 namespace { 21 namespace {
22 22
23 HashValue GetTestHashValue(uint8 label, HashValueTag tag) { 23 HashValue GetTestHashValue(uint8 label, HashValueTag tag) {
24 HashValue hash_value(tag); 24 HashValue hash_value(tag);
25 memset(hash_value.data(), label, hash_value.size()); 25 memset(hash_value.data(), label, hash_value.size());
26 return hash_value; 26 return hash_value;
27 } 27 }
28 28
29 std::string GetTestPin(uint8 label, HashValueTag tag) { 29 std::string GetTestPinImpl(uint8 label, HashValueTag tag, bool quoted) {
30 HashValue hash_value = GetTestHashValue(label, tag); 30 HashValue hash_value = GetTestHashValue(label, tag);
31 std::string base64; 31 std::string base64;
32 base::Base64Encode(base::StringPiece( 32 base::Base64Encode(base::StringPiece(
33 reinterpret_cast<char*>(hash_value.data()), hash_value.size()), &base64); 33 reinterpret_cast<char*>(hash_value.data()), hash_value.size()), &base64);
34 34
35 std::string ret;
35 switch (hash_value.tag) { 36 switch (hash_value.tag) {
36 case HASH_VALUE_SHA1: 37 case HASH_VALUE_SHA1:
37 return std::string("pin-sha1=\"") + base64 + "\""; 38 ret = "pin-sha1=";
39 break;
38 case HASH_VALUE_SHA256: 40 case HASH_VALUE_SHA256:
39 return std::string("pin-sha256=\"") + base64 + "\""; 41 ret = "pin-sha256=";
42 break;
40 default: 43 default:
41 NOTREACHED() << "Unknown HashValueTag " << hash_value.tag; 44 NOTREACHED() << "Unknown HashValueTag " << hash_value.tag;
42 return std::string("ERROR"); 45 return std::string("ERROR");
43 } 46 }
47 if (quoted)
48 ret += '\"';
49 ret += base64;
50 if (quoted)
51 ret += '\"';
52 return ret;
53 }
54
55 std::string GetTestPin(uint8 label, HashValueTag tag) {
56 return GetTestPinImpl(label, tag, true);
57 }
58
59 std::string GetTestPinUnquoted(uint8 label, HashValueTag tag) {
60 return GetTestPinImpl(label, tag, false);
44 } 61 }
45 62
46 }; 63 };
47 64
48 65
49 class HttpSecurityHeadersTest : public testing::Test { 66 class HttpSecurityHeadersTest : public testing::Test {
50 }; 67 };
51 68
52 69
53 TEST_F(HttpSecurityHeadersTest, BogusHeaders) { 70 TEST_F(HttpSecurityHeadersTest, BogusHeaders) {
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 HashValueVector hashes; 152 HashValueVector hashes;
136 HashValueVector chain_hashes; 153 HashValueVector chain_hashes;
137 154
138 // Set some fake "chain" hashes 155 // Set some fake "chain" hashes
139 chain_hashes.push_back(GetTestHashValue(1, tag)); 156 chain_hashes.push_back(GetTestHashValue(1, tag));
140 chain_hashes.push_back(GetTestHashValue(2, tag)); 157 chain_hashes.push_back(GetTestHashValue(2, tag));
141 chain_hashes.push_back(GetTestHashValue(3, tag)); 158 chain_hashes.push_back(GetTestHashValue(3, tag));
142 159
143 // The good pin must be in the chain, the backup pin must not be 160 // The good pin must be in the chain, the backup pin must not be
144 std::string good_pin = GetTestPin(2, tag); 161 std::string good_pin = GetTestPin(2, tag);
162 std::string good_pin_unquoted = GetTestPinUnquoted(2, tag);
145 std::string backup_pin = GetTestPin(4, tag); 163 std::string backup_pin = GetTestPin(4, tag);
146 164
147 EXPECT_FALSE(ParseHPKPHeader(std::string(), chain_hashes, &max_age, 165 EXPECT_FALSE(ParseHPKPHeader(std::string(), chain_hashes, &max_age,
148 &include_subdomains, &hashes)); 166 &include_subdomains, &hashes));
149 EXPECT_FALSE(ParseHPKPHeader(" ", chain_hashes, &max_age, 167 EXPECT_FALSE(ParseHPKPHeader(" ", chain_hashes, &max_age,
150 &include_subdomains, &hashes)); 168 &include_subdomains, &hashes));
151 EXPECT_FALSE(ParseHPKPHeader("abc", chain_hashes, &max_age, 169 EXPECT_FALSE(ParseHPKPHeader("abc", chain_hashes, &max_age,
152 &include_subdomains, &hashes)); 170 &include_subdomains, &hashes));
153 EXPECT_FALSE(ParseHPKPHeader(" abc", chain_hashes, &max_age, 171 EXPECT_FALSE(ParseHPKPHeader(" abc", chain_hashes, &max_age,
154 &include_subdomains, &hashes)); 172 &include_subdomains, &hashes));
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 &include_subdomains, &hashes)); 224 &include_subdomains, &hashes));
207 EXPECT_FALSE(ParseHPKPHeader("max-age=3488923;", chain_hashes, &max_age, 225 EXPECT_FALSE(ParseHPKPHeader("max-age=3488923;", chain_hashes, &max_age,
208 &include_subdomains, &hashes)); 226 &include_subdomains, &hashes));
209 EXPECT_FALSE(ParseHPKPHeader("max-age=3488923 e", chain_hashes, 227 EXPECT_FALSE(ParseHPKPHeader("max-age=3488923 e", chain_hashes,
210 &max_age, &include_subdomains, &hashes)); 228 &max_age, &include_subdomains, &hashes));
211 EXPECT_FALSE(ParseHPKPHeader("max-age=3488923 includesubdomain", 229 EXPECT_FALSE(ParseHPKPHeader("max-age=3488923 includesubdomain",
212 chain_hashes, &max_age, &include_subdomains, 230 chain_hashes, &max_age, &include_subdomains,
213 &hashes)); 231 &hashes));
214 EXPECT_FALSE(ParseHPKPHeader("max-age=34889.23", chain_hashes, &max_age, 232 EXPECT_FALSE(ParseHPKPHeader("max-age=34889.23", chain_hashes, &max_age,
215 &include_subdomains, &hashes)); 233 &include_subdomains, &hashes));
234 EXPECT_FALSE(
235 ParseHPKPHeader("max-age=243; " + good_pin_unquoted + ";" + backup_pin,
236 chain_hashes, &max_age, &include_subdomains, &hashes));
216 237
217 // Check the out args were not updated by checking the default 238 // Check the out args were not updated by checking the default
218 // values for its predictable fields. 239 // values for its predictable fields.
219 EXPECT_EQ(0, max_age.InSeconds()); 240 EXPECT_EQ(0, max_age.InSeconds());
220 EXPECT_EQ(hashes.size(), (size_t)0); 241 EXPECT_EQ(hashes.size(), (size_t)0);
221 } 242 }
222 243
223 TEST_F(HttpSecurityHeadersTest, ValidSTSHeaders) { 244 TEST_F(HttpSecurityHeadersTest, ValidSTSHeaders) {
224 base::TimeDelta max_age; 245 base::TimeDelta max_age;
225 base::TimeDelta expect_max_age; 246 base::TimeDelta expect_max_age;
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
384 HashValueVector hashes; 405 HashValueVector hashes;
385 HashValueVector chain_hashes; 406 HashValueVector chain_hashes;
386 407
387 // Set some fake "chain" hashes into chain_hashes 408 // Set some fake "chain" hashes into chain_hashes
388 chain_hashes.push_back(GetTestHashValue(1, tag)); 409 chain_hashes.push_back(GetTestHashValue(1, tag));
389 chain_hashes.push_back(GetTestHashValue(2, tag)); 410 chain_hashes.push_back(GetTestHashValue(2, tag));
390 chain_hashes.push_back(GetTestHashValue(3, tag)); 411 chain_hashes.push_back(GetTestHashValue(3, tag));
391 412
392 // The good pin must be in the chain, the backup pin must not be 413 // The good pin must be in the chain, the backup pin must not be
393 std::string good_pin = GetTestPin(2, tag); 414 std::string good_pin = GetTestPin(2, tag);
415 std::string good_pin2 = GetTestPin(3, tag);
394 std::string backup_pin = GetTestPin(4, tag); 416 std::string backup_pin = GetTestPin(4, tag);
395 417
396 EXPECT_TRUE(ParseHPKPHeader( 418 EXPECT_TRUE(ParseHPKPHeader(
397 "max-age=243; " + good_pin + ";" + backup_pin, 419 "max-age=243; " + good_pin + ";" + backup_pin,
398 chain_hashes, &max_age, &include_subdomains, &hashes)); 420 chain_hashes, &max_age, &include_subdomains, &hashes));
399 expect_max_age = base::TimeDelta::FromSeconds(243); 421 expect_max_age = base::TimeDelta::FromSeconds(243);
400 EXPECT_EQ(expect_max_age, max_age); 422 EXPECT_EQ(expect_max_age, max_age);
401 EXPECT_FALSE(include_subdomains); 423 EXPECT_FALSE(include_subdomains);
402 424
403 EXPECT_TRUE(ParseHPKPHeader( 425 EXPECT_TRUE(ParseHPKPHeader(
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
461 EXPECT_TRUE(include_subdomains); 483 EXPECT_TRUE(include_subdomains);
462 484
463 EXPECT_TRUE(ParseHPKPHeader( 485 EXPECT_TRUE(ParseHPKPHeader(
464 " max-age=999999999999999999999999999999999999999999999 ; " + 486 " max-age=999999999999999999999999999999999999999999999 ; " +
465 backup_pin + ";" + good_pin + "; ", 487 backup_pin + ";" + good_pin + "; ",
466 chain_hashes, &max_age, &include_subdomains, &hashes)); 488 chain_hashes, &max_age, &include_subdomains, &hashes));
467 expect_max_age = base::TimeDelta::FromSeconds(kMaxHSTSAgeSecs); 489 expect_max_age = base::TimeDelta::FromSeconds(kMaxHSTSAgeSecs);
468 EXPECT_EQ(expect_max_age, max_age); 490 EXPECT_EQ(expect_max_age, max_age);
469 EXPECT_FALSE(include_subdomains); 491 EXPECT_FALSE(include_subdomains);
470 492
471 // Test that parsing the same header twice doesn't duplicate the recorded 493 // Test that parsing a different header resets the hashes.
472 // hashes.
473 hashes.clear(); 494 hashes.clear();
474 EXPECT_TRUE(ParseHPKPHeader( 495 EXPECT_TRUE(ParseHPKPHeader(
475 " max-age=999; " + 496 " max-age=999; " +
476 backup_pin + ";" + good_pin + "; ", 497 backup_pin + ";" + good_pin + "; ",
477 chain_hashes, &max_age, &include_subdomains, &hashes)); 498 chain_hashes, &max_age, &include_subdomains, &hashes));
478 EXPECT_EQ(2u, hashes.size()); 499 EXPECT_EQ(2u, hashes.size());
479 EXPECT_TRUE(ParseHPKPHeader( 500 EXPECT_TRUE(ParseHPKPHeader(
480 " max-age=999; " + 501 " max-age=999; " + backup_pin + ";" + good_pin2 + "; ", chain_hashes,
481 backup_pin + ";" + good_pin + "; ", 502 &max_age, &include_subdomains, &hashes));
482 chain_hashes, &max_age, &include_subdomains, &hashes));
483 EXPECT_EQ(2u, hashes.size()); 503 EXPECT_EQ(2u, hashes.size());
484 } 504 }
485 505
486 TEST_F(HttpSecurityHeadersTest, BogusPinsHeadersSHA1) { 506 TEST_F(HttpSecurityHeadersTest, BogusPinsHeadersSHA1) {
487 TestBogusPinsHeaders(HASH_VALUE_SHA1); 507 TestBogusPinsHeaders(HASH_VALUE_SHA1);
488 } 508 }
489 509
490 TEST_F(HttpSecurityHeadersTest, BogusPinsHeadersSHA256) { 510 TEST_F(HttpSecurityHeadersTest, BogusPinsHeadersSHA256) {
491 TestBogusPinsHeaders(HASH_VALUE_SHA256); 511 TestBogusPinsHeaders(HASH_VALUE_SHA256);
492 } 512 }
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
708 EXPECT_TRUE(domain_state.ShouldUpgradeToSSL()); 728 EXPECT_TRUE(domain_state.ShouldUpgradeToSSL());
709 EXPECT_TRUE(state.ShouldUpgradeToSSL(domain)); 729 EXPECT_TRUE(state.ShouldUpgradeToSSL(domain));
710 // The dynamic pins, which do not match |saved_hashes|, should take 730 // The dynamic pins, which do not match |saved_hashes|, should take
711 // precedence over the static pins and cause the check to fail. 731 // precedence over the static pins and cause the check to fail.
712 EXPECT_FALSE(state.CheckPublicKeyPins(domain, 732 EXPECT_FALSE(state.CheckPublicKeyPins(domain,
713 is_issued_by_known_root, 733 is_issued_by_known_root,
714 saved_hashes, 734 saved_hashes,
715 &failure_log)); 735 &failure_log));
716 } 736 }
717 737
738 // Tests that seeing an invalid HPKP header leaves the existing one alone.
739 TEST_F(HttpSecurityHeadersTest, IgnoreInvalidHeaders) {
740 TransportSecurityState state;
741
742 HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA256);
743 std::string good_pin = GetTestPin(1, HASH_VALUE_SHA256);
744 std::string bad_pin = GetTestPin(2, HASH_VALUE_SHA256);
745 std::string backup_pin = GetTestPin(3, HASH_VALUE_SHA256);
746
747 SSLInfo ssl_info;
748 ssl_info.public_key_hashes.push_back(good_hash);
749
750 // Add a valid HPKP header.
751 EXPECT_TRUE(state.AddHPKPHeader(
752 "example.com", "max-age = 10000; " + good_pin + "; " + backup_pin,
753 ssl_info));
754
755 // Check the insertion was valid.
756 EXPECT_TRUE(state.HasPublicKeyPins("example.com"));
757 std::string failure_log;
758 bool is_issued_by_known_root = true;
759 EXPECT_TRUE(state.CheckPublicKeyPins("example.com", is_issued_by_known_root,
760 ssl_info.public_key_hashes,
761 &failure_log));
762
763 // Now assert an invalid one. This should fail.
764 EXPECT_FALSE(state.AddHPKPHeader(
765 "example.com", "max-age = 10000; " + bad_pin + "; " + backup_pin,
766 ssl_info));
767
768 // The old pins must still exist.
769 EXPECT_TRUE(state.HasPublicKeyPins("example.com"));
770 EXPECT_TRUE(state.CheckPublicKeyPins("example.com", is_issued_by_known_root,
771 ssl_info.public_key_hashes,
772 &failure_log));
773 }
774
718 }; // namespace net 775 }; // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698