OLD | NEW |
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" |
(...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
494 TEST_F(HttpSecurityHeadersTest, ValidPKPHeadersSHA1) { | 494 TEST_F(HttpSecurityHeadersTest, ValidPKPHeadersSHA1) { |
495 TestValidPKPHeaders(HASH_VALUE_SHA1); | 495 TestValidPKPHeaders(HASH_VALUE_SHA1); |
496 } | 496 } |
497 | 497 |
498 TEST_F(HttpSecurityHeadersTest, ValidPKPHeadersSHA256) { | 498 TEST_F(HttpSecurityHeadersTest, ValidPKPHeadersSHA256) { |
499 TestValidPKPHeaders(HASH_VALUE_SHA256); | 499 TestValidPKPHeaders(HASH_VALUE_SHA256); |
500 } | 500 } |
501 | 501 |
502 TEST_F(HttpSecurityHeadersTest, UpdateDynamicPKPOnly) { | 502 TEST_F(HttpSecurityHeadersTest, UpdateDynamicPKPOnly) { |
503 TransportSecurityState state; | 503 TransportSecurityState state; |
504 TransportSecurityState::DomainState domain_state; | 504 TransportSecurityState::DomainState static_domain_state; |
505 | 505 |
506 // docs.google.com has preloaded pins. | 506 // docs.google.com has preloaded pins. |
| 507 const bool sni_enabled = true; |
507 std::string domain = "docs.google.com"; | 508 std::string domain = "docs.google.com"; |
508 EXPECT_TRUE(state.GetDomainState(domain, true, &domain_state)); | 509 EXPECT_TRUE( |
509 EXPECT_GT(domain_state.static_spki_hashes.size(), 1UL); | 510 state.GetStaticDomainState(domain, sni_enabled, &static_domain_state)); |
510 HashValueVector saved_hashes = domain_state.static_spki_hashes; | 511 EXPECT_GT(static_domain_state.pkp.spki_hashes.size(), 1UL); |
| 512 HashValueVector saved_hashes = static_domain_state.pkp.spki_hashes; |
511 | 513 |
512 // Add a header, which should only update the dynamic state. | 514 // Add a header, which should only update the dynamic state. |
513 HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA1); | 515 HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA1); |
514 HashValue backup_hash = GetTestHashValue(2, HASH_VALUE_SHA1); | 516 HashValue backup_hash = GetTestHashValue(2, HASH_VALUE_SHA1); |
515 std::string good_pin = GetTestPin(1, HASH_VALUE_SHA1); | 517 std::string good_pin = GetTestPin(1, HASH_VALUE_SHA1); |
516 std::string backup_pin = GetTestPin(2, HASH_VALUE_SHA1); | 518 std::string backup_pin = GetTestPin(2, HASH_VALUE_SHA1); |
517 std::string header = "max-age = 10000; " + good_pin + "; " + backup_pin; | 519 std::string header = "max-age = 10000; " + good_pin + "; " + backup_pin; |
518 | 520 |
519 // Construct a fake SSLInfo that will pass AddHPKPHeader's checks. | 521 // Construct a fake SSLInfo that will pass AddHPKPHeader's checks. |
520 SSLInfo ssl_info; | 522 SSLInfo ssl_info; |
521 ssl_info.public_key_hashes.push_back(good_hash); | 523 ssl_info.public_key_hashes.push_back(good_hash); |
522 ssl_info.public_key_hashes.push_back(saved_hashes[0]); | 524 ssl_info.public_key_hashes.push_back(saved_hashes[0]); |
523 EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info)); | 525 EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info)); |
524 | 526 |
525 // Expect the preloaded state to remain unchanged. | 527 // Expect the static state to remain unchanged. |
526 std::string canonicalized_host = TransportSecurityState::CanonicalizeHost( | 528 TransportSecurityState::DomainState new_static_domain_state; |
527 domain); | 529 EXPECT_TRUE(state.GetStaticDomainState( |
528 TransportSecurityState::DomainState static_domain_state; | 530 domain, sni_enabled, &new_static_domain_state)); |
529 EXPECT_TRUE(state.GetStaticDomainState(canonicalized_host, | |
530 true, | |
531 &static_domain_state)); | |
532 for (size_t i = 0; i < saved_hashes.size(); ++i) { | 531 for (size_t i = 0; i < saved_hashes.size(); ++i) { |
533 EXPECT_TRUE(HashValuesEqual( | 532 EXPECT_TRUE(HashValuesEqual(saved_hashes[i])( |
534 saved_hashes[i])(static_domain_state.static_spki_hashes[i])); | 533 new_static_domain_state.pkp.spki_hashes[i])); |
535 } | 534 } |
536 | 535 |
537 // Expect the dynamic state to reflect the header. | 536 // Expect the dynamic state to reflect the header. |
538 TransportSecurityState::DomainState dynamic_domain_state; | 537 TransportSecurityState::DomainState dynamic_domain_state; |
539 EXPECT_TRUE(state.GetDynamicDomainState(domain, &dynamic_domain_state)); | 538 EXPECT_TRUE(state.GetDynamicDomainState(domain, &dynamic_domain_state)); |
540 EXPECT_EQ(2UL, dynamic_domain_state.dynamic_spki_hashes.size()); | 539 EXPECT_EQ(2UL, dynamic_domain_state.pkp.spki_hashes.size()); |
541 | 540 |
542 HashValueVector::const_iterator hash = std::find_if( | 541 HashValueVector::const_iterator hash = |
543 dynamic_domain_state.dynamic_spki_hashes.begin(), | 542 std::find_if(dynamic_domain_state.pkp.spki_hashes.begin(), |
544 dynamic_domain_state.dynamic_spki_hashes.end(), | 543 dynamic_domain_state.pkp.spki_hashes.end(), |
545 HashValuesEqual(good_hash)); | 544 HashValuesEqual(good_hash)); |
546 EXPECT_NE(dynamic_domain_state.dynamic_spki_hashes.end(), hash); | 545 EXPECT_NE(dynamic_domain_state.pkp.spki_hashes.end(), hash); |
547 | 546 |
548 hash = std::find_if( | 547 hash = std::find_if(dynamic_domain_state.pkp.spki_hashes.begin(), |
549 dynamic_domain_state.dynamic_spki_hashes.begin(), | 548 dynamic_domain_state.pkp.spki_hashes.end(), |
550 dynamic_domain_state.dynamic_spki_hashes.end(), | 549 HashValuesEqual(backup_hash)); |
551 HashValuesEqual(backup_hash)); | 550 EXPECT_NE(dynamic_domain_state.pkp.spki_hashes.end(), hash); |
552 EXPECT_NE(dynamic_domain_state.dynamic_spki_hashes.end(), hash); | |
553 | 551 |
554 // Expect the overall state to reflect the header, too. | 552 // Expect the overall state to reflect the header, too. |
555 EXPECT_TRUE(state.GetDomainState(domain, true, &domain_state)); | 553 EXPECT_TRUE(state.HasPublicKeyPins(domain, sni_enabled)); |
556 EXPECT_EQ(2UL, domain_state.dynamic_spki_hashes.size()); | 554 HashValueVector hashes; |
| 555 hashes.push_back(good_hash); |
| 556 std::string failure_log; |
| 557 EXPECT_TRUE( |
| 558 state.CheckPublicKeyPins(domain, sni_enabled, hashes, &failure_log)); |
557 | 559 |
558 hash = std::find_if(domain_state.dynamic_spki_hashes.begin(), | 560 TransportSecurityState::DomainState new_dynamic_domain_state; |
559 domain_state.dynamic_spki_hashes.end(), | 561 EXPECT_TRUE(state.GetDynamicDomainState(domain, &new_dynamic_domain_state)); |
| 562 EXPECT_EQ(2UL, new_dynamic_domain_state.pkp.spki_hashes.size()); |
| 563 |
| 564 hash = std::find_if(new_dynamic_domain_state.pkp.spki_hashes.begin(), |
| 565 new_dynamic_domain_state.pkp.spki_hashes.end(), |
560 HashValuesEqual(good_hash)); | 566 HashValuesEqual(good_hash)); |
561 EXPECT_NE(domain_state.dynamic_spki_hashes.end(), hash); | 567 EXPECT_NE(new_dynamic_domain_state.pkp.spki_hashes.end(), hash); |
562 | 568 |
563 hash = std::find_if( | 569 hash = std::find_if(new_dynamic_domain_state.pkp.spki_hashes.begin(), |
564 domain_state.dynamic_spki_hashes.begin(), | 570 new_dynamic_domain_state.pkp.spki_hashes.end(), |
565 domain_state.dynamic_spki_hashes.end(), | 571 HashValuesEqual(backup_hash)); |
566 HashValuesEqual(backup_hash)); | 572 EXPECT_NE(new_dynamic_domain_state.pkp.spki_hashes.end(), hash); |
567 EXPECT_NE(domain_state.dynamic_spki_hashes.end(), hash); | 573 } |
| 574 |
| 575 // Tests that when a static HSTS and a static HPKP entry are present, adding a |
| 576 // dynamic HSTS header does not clobber the static HPKP entry. Further, adding a |
| 577 // dynamic HPKP entry could not affect the HSTS entry for the site. |
| 578 TEST_F(HttpSecurityHeadersTest, NoClobberPins) { |
| 579 TransportSecurityState state; |
| 580 TransportSecurityState::DomainState domain_state; |
| 581 |
| 582 // accounts.google.com has preloaded pins. |
| 583 std::string domain = "accounts.google.com"; |
| 584 |
| 585 // Retrieve the DomainState as it is by default, including its known good |
| 586 // pins. |
| 587 const bool sni_enabled = true; |
| 588 EXPECT_TRUE(state.GetStaticDomainState(domain, sni_enabled, &domain_state)); |
| 589 HashValueVector saved_hashes = domain_state.pkp.spki_hashes; |
| 590 EXPECT_TRUE(domain_state.ShouldUpgradeToSSL()); |
| 591 EXPECT_TRUE(domain_state.HasPublicKeyPins()); |
| 592 EXPECT_TRUE(state.ShouldUpgradeToSSL(domain, sni_enabled)); |
| 593 EXPECT_TRUE(state.HasPublicKeyPins(domain, sni_enabled)); |
| 594 |
| 595 // Add a dynamic HSTS header. CheckPublicKeyPins should still pass when given |
| 596 // the original |saved_hashes|, indicating that the static PKP data is still |
| 597 // configured for the domain. |
| 598 EXPECT_TRUE(state.AddHSTSHeader(domain, "includesubdomains; max-age=10000")); |
| 599 EXPECT_TRUE(state.ShouldUpgradeToSSL(domain, sni_enabled)); |
| 600 std::string failure_log; |
| 601 EXPECT_TRUE(state.CheckPublicKeyPins( |
| 602 domain, sni_enabled, saved_hashes, &failure_log)); |
| 603 |
| 604 // Add an HPKP header, which should only update the dynamic state. |
| 605 HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA1); |
| 606 std::string good_pin = GetTestPin(1, HASH_VALUE_SHA1); |
| 607 std::string backup_pin = GetTestPin(2, HASH_VALUE_SHA1); |
| 608 std::string header = "max-age = 10000; " + good_pin + "; " + backup_pin; |
| 609 |
| 610 // Construct a fake SSLInfo that will pass AddHPKPHeader's checks. |
| 611 SSLInfo ssl_info; |
| 612 ssl_info.public_key_hashes.push_back(good_hash); |
| 613 ssl_info.public_key_hashes.push_back(saved_hashes[0]); |
| 614 EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info)); |
| 615 |
| 616 EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info)); |
| 617 // HSTS should still be configured for this domain. |
| 618 EXPECT_TRUE(domain_state.ShouldUpgradeToSSL()); |
| 619 EXPECT_TRUE(state.ShouldUpgradeToSSL(domain, sni_enabled)); |
| 620 // The dynamic pins, which do not match |saved_hashes|, should take |
| 621 // precedence over the static pins and cause the check to fail. |
| 622 EXPECT_FALSE(state.CheckPublicKeyPins( |
| 623 domain, sni_enabled, saved_hashes, &failure_log)); |
568 } | 624 } |
569 | 625 |
570 }; // namespace net | 626 }; // namespace net |
OLD | NEW |