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

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

Issue 103803012: Make HSTS headers not clobber preloaded pins. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Respond to comments and fix compilation errors. Created 6 years, 7 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 | Annotate | Revision Log
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"
(...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698