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

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: Rebase and refactor. (Not done yet.) Created 6 years, 8 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 436 matching lines...) Expand 10 before | Expand all | Expand 10 after
447 TEST_F(HttpSecurityHeadersTest, ValidPKPHeadersSHA256) { 447 TEST_F(HttpSecurityHeadersTest, ValidPKPHeadersSHA256) {
448 TestValidPKPHeaders(HASH_VALUE_SHA256); 448 TestValidPKPHeaders(HASH_VALUE_SHA256);
449 } 449 }
450 450
451 TEST_F(HttpSecurityHeadersTest, UpdateDynamicPKPOnly) { 451 TEST_F(HttpSecurityHeadersTest, UpdateDynamicPKPOnly) {
452 TransportSecurityState state; 452 TransportSecurityState state;
453 TransportSecurityState::DomainState domain_state; 453 TransportSecurityState::DomainState domain_state;
454 454
455 // docs.google.com has preloaded pins. 455 // docs.google.com has preloaded pins.
456 std::string domain = "docs.google.com"; 456 std::string domain = "docs.google.com";
457 EXPECT_TRUE(state.GetDomainState(domain, true, &domain_state)); 457 EXPECT_TRUE(state.GetStaticDomainState(domain, true, &domain_state));
458 EXPECT_GT(domain_state.static_spki_hashes.size(), 1UL); 458 EXPECT_GT(domain_state.pkp.spki_hashes.size(), 1UL);
459 HashValueVector saved_hashes = domain_state.static_spki_hashes; 459 HashValueVector saved_hashes = domain_state.pkp.spki_hashes;
460 460
461 // Add a header, which should only update the dynamic state. 461 // Add a header, which should only update the dynamic state.
462 HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA1); 462 HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA1);
463 HashValue backup_hash = GetTestHashValue(2, HASH_VALUE_SHA1); 463 HashValue backup_hash = GetTestHashValue(2, HASH_VALUE_SHA1);
464 std::string good_pin = GetTestPin(1, HASH_VALUE_SHA1); 464 std::string good_pin = GetTestPin(1, HASH_VALUE_SHA1);
465 std::string backup_pin = GetTestPin(2, HASH_VALUE_SHA1); 465 std::string backup_pin = GetTestPin(2, HASH_VALUE_SHA1);
466 std::string header = "max-age = 10000; " + good_pin + "; " + backup_pin; 466 std::string header = "max-age = 10000; " + good_pin + "; " + backup_pin;
467 467
468 // Construct a fake SSLInfo that will pass AddHPKPHeader's checks. 468 // Construct a fake SSLInfo that will pass AddHPKPHeader's checks.
469 SSLInfo ssl_info; 469 SSLInfo ssl_info;
470 ssl_info.public_key_hashes.push_back(good_hash); 470 ssl_info.public_key_hashes.push_back(good_hash);
471 ssl_info.public_key_hashes.push_back(saved_hashes[0]); 471 ssl_info.public_key_hashes.push_back(saved_hashes[0]);
472 EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info)); 472 EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info));
473 473
474 // Expect the preloaded state to remain unchanged. 474 // Expect the preloaded state to remain unchanged.
475 std::string canonicalized_host = TransportSecurityState::CanonicalizeHost(
476 domain);
477 TransportSecurityState::DomainState static_domain_state; 475 TransportSecurityState::DomainState static_domain_state;
478 EXPECT_TRUE(state.GetStaticDomainState(canonicalized_host, 476 EXPECT_TRUE(state.GetStaticDomainState(domain, true, &static_domain_state));
479 true,
480 &static_domain_state));
481 for (size_t i = 0; i < saved_hashes.size(); ++i) { 477 for (size_t i = 0; i < saved_hashes.size(); ++i) {
482 EXPECT_TRUE(HashValuesEqual( 478 EXPECT_TRUE(HashValuesEqual(
483 saved_hashes[i])(static_domain_state.static_spki_hashes[i])); 479 saved_hashes[i])(static_domain_state.pkp.spki_hashes[i]));
484 } 480 }
485 481
486 // Expect the dynamic state to reflect the header. 482 // Expect the dynamic state to reflect the header.
487 TransportSecurityState::DomainState dynamic_domain_state; 483 TransportSecurityState::DomainState dynamic_domain_state;
488 EXPECT_TRUE(state.GetDynamicDomainState(domain, &dynamic_domain_state)); 484 EXPECT_TRUE(state.GetDynamicDomainState(domain, &dynamic_domain_state));
489 EXPECT_EQ(2UL, dynamic_domain_state.dynamic_spki_hashes.size()); 485 EXPECT_EQ(2UL, dynamic_domain_state.pkp.spki_hashes.size());
490 486
491 HashValueVector::const_iterator hash = std::find_if( 487 HashValueVector::const_iterator hash = std::find_if(
492 dynamic_domain_state.dynamic_spki_hashes.begin(), 488 dynamic_domain_state.pkp.spki_hashes.begin(),
493 dynamic_domain_state.dynamic_spki_hashes.end(), 489 dynamic_domain_state.pkp.spki_hashes.end(),
494 HashValuesEqual(good_hash)); 490 HashValuesEqual(good_hash));
495 EXPECT_NE(dynamic_domain_state.dynamic_spki_hashes.end(), hash); 491 EXPECT_NE(dynamic_domain_state.pkp.spki_hashes.end(), hash);
496 492
497 hash = std::find_if( 493 hash = std::find_if(
498 dynamic_domain_state.dynamic_spki_hashes.begin(), 494 dynamic_domain_state.pkp.spki_hashes.begin(),
499 dynamic_domain_state.dynamic_spki_hashes.end(), 495 dynamic_domain_state.pkp.spki_hashes.end(),
500 HashValuesEqual(backup_hash)); 496 HashValuesEqual(backup_hash));
501 EXPECT_NE(dynamic_domain_state.dynamic_spki_hashes.end(), hash); 497 EXPECT_NE(dynamic_domain_state.pkp.spki_hashes.end(), hash);
502 498
503 // Expect the overall state to reflect the header, too. 499 // Expect the overall state to reflect the header, too.
500 EXPECT_TRUE(state.HasPublicKeyPins(domain, true /* sni enabled */ ));
501 HashValueVector hashes;
502 hashes.push_back(good_hash);
503 EXPECT_TRUE(state.CheckPublicKeyPins(domain, true /* sni_enabled */, hashes));
504
505 /* TODO(palmer): check both dynamic and static state, or add
506 * TSS::GetPublicKeyPins?
Ryan Sleevi 2014/04/08 20:29:11 indent issue? Still trying to grok why this was d
504 EXPECT_TRUE(state.GetDomainState(domain, true, &domain_state)); 507 EXPECT_TRUE(state.GetDomainState(domain, true, &domain_state));
505 EXPECT_EQ(2UL, domain_state.dynamic_spki_hashes.size()); 508 EXPECT_EQ(2UL, domain_state.dynamic_pkp.spki_hashes.size());
506 509
507 hash = std::find_if(domain_state.dynamic_spki_hashes.begin(), 510 hash = std::find_if(domain_state.pkp.spki_hashes.begin(),
508 domain_state.dynamic_spki_hashes.end(), 511 domain_state.pkp.spki_hashes.end(),
509 HashValuesEqual(good_hash)); 512 HashValuesEqual(good_hash));
510 EXPECT_NE(domain_state.dynamic_spki_hashes.end(), hash); 513 EXPECT_NE(domain_state.pkp.spki_hashes.end(), hash);
511 514
512 hash = std::find_if( 515 hash = std::find_if(
513 domain_state.dynamic_spki_hashes.begin(), 516 domain_state.pkp.spki_hashes.begin(),
514 domain_state.dynamic_spki_hashes.end(), 517 domain_state.pkp.spki_hashes.end(),
515 HashValuesEqual(backup_hash)); 518 HashValuesEqual(backup_hash));
516 EXPECT_NE(domain_state.dynamic_spki_hashes.end(), hash); 519 EXPECT_NE(domain_state.pkp.spki_hashes.end(), hash);
520 */
521 }
522
523 TEST_F(HttpSecurityHeadersTest, NoClobberPins) {
524 TransportSecurityState state;
525 TransportSecurityState::DomainState domain_state;
526
527 // accounts.google.com has preloaded pins.
528 std::string domain = "accounts.google.com";
529
530 // Retrieve the DomainState as it is by default, including its known good
531 // pins.
532 const bool sni_enabled = true;
533 EXPECT_TRUE(state.GetStaticDomainState(domain, sni_enabled, &domain_state));
534 HashValueVector saved_hashes = domain_state.pkp.spki_hashes;
535 EXPECT_TRUE(domain_state.ShouldUpgradeToSSL());
536 EXPECT_TRUE(domain_state.HasPublicKeyPins());
537 EXPECT_TRUE(state.ShouldUpgradeToSSL(domain, sni_enabled));
538 EXPECT_TRUE(state.HasPublicKeyPins(domain, sni_enabled));
539
540 // Add a dynamic HSTS header. CheckPublicKeyPins should still pass when given
541 // the original |saved_hashes|, indicating that the static PKP data is still
542 // configured for the domain.
543 EXPECT_TRUE(state.AddHSTSHeader(domain, "includesubdomains; max-age=10000"));
544 EXPECT_TRUE(state.ShouldUpgradeToSSL(domain, sni_enabled));
545 EXPECT_TRUE(state.CheckPublicKeyPins(domain, sni_enabled, saved_hashes));
546
547 // Add an HPKP header, which should only update the dynamic state.
548 HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA1);
549 std::string good_pin = GetTestPin(1, HASH_VALUE_SHA1);
550 std::string backup_pin = GetTestPin(2, HASH_VALUE_SHA1);
551 std::string header = "max-age = 10000; " + good_pin + "; " + backup_pin;
552
553 // Construct a fake SSLInfo that will pass AddHPKPHeader's checks.
554 SSLInfo ssl_info;
555 ssl_info.public_key_hashes.push_back(good_hash);
556 ssl_info.public_key_hashes.push_back(saved_hashes[0]);
557 EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info));
558
559 EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info));
560 // HSTS should still be configured for this domain.
561 EXPECT_TRUE(domain_state.ShouldUpgradeToSSL());
562 EXPECT_TRUE(state.ShouldUpgradeToSSL(domain, sni_enabled));
563 // Check that a good pin is still valid.
564 EXPECT_TRUE(state.CheckPublicKeyPins(domain, sni_enabled, saved_hashes));
517 } 565 }
518 566
519 }; // namespace net 567 }; // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698