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 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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.GetDomainState(domain, true, &domain_state)); |
458 EXPECT_GT(domain_state.static_spki_hashes.size(), 1UL); | 458 EXPECT_GT(domain_state.static_pkp.spki_hashes.size(), 1UL); |
459 HashValueVector saved_hashes = domain_state.static_spki_hashes; | 459 HashValueVector saved_hashes = domain_state.static_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( | 475 std::string canonicalized_host = TransportSecurityState::CanonicalizeHost( |
476 domain); | 476 domain); |
477 TransportSecurityState::DomainState static_domain_state; | 477 TransportSecurityState::DomainState static_domain_state; |
478 EXPECT_TRUE(state.GetStaticDomainState(canonicalized_host, | 478 EXPECT_TRUE(state.GetStaticDomainState(canonicalized_host, |
479 true, | 479 true, |
480 &static_domain_state)); | 480 &static_domain_state)); |
481 for (size_t i = 0; i < saved_hashes.size(); ++i) { | 481 for (size_t i = 0; i < saved_hashes.size(); ++i) { |
482 EXPECT_TRUE(HashValuesEqual( | 482 EXPECT_TRUE(HashValuesEqual( |
483 saved_hashes[i])(static_domain_state.static_spki_hashes[i])); | 483 saved_hashes[i])(static_domain_state.static_pkp.spki_hashes[i])); |
484 } | 484 } |
485 | 485 |
486 // Expect the dynamic state to reflect the header. | 486 // Expect the dynamic state to reflect the header. |
487 TransportSecurityState::DomainState dynamic_domain_state; | 487 TransportSecurityState::DomainState dynamic_domain_state; |
488 EXPECT_TRUE(state.GetDynamicDomainState(domain, &dynamic_domain_state)); | 488 EXPECT_TRUE(state.GetDynamicDomainState(domain, &dynamic_domain_state)); |
489 EXPECT_EQ(2UL, dynamic_domain_state.dynamic_spki_hashes.size()); | 489 EXPECT_EQ(2UL, dynamic_domain_state.dynamic_pkp.spki_hashes.size()); |
490 | 490 |
491 HashValueVector::const_iterator hash = std::find_if( | 491 HashValueVector::const_iterator hash = std::find_if( |
492 dynamic_domain_state.dynamic_spki_hashes.begin(), | 492 dynamic_domain_state.dynamic_pkp.spki_hashes.begin(), |
493 dynamic_domain_state.dynamic_spki_hashes.end(), | 493 dynamic_domain_state.dynamic_pkp.spki_hashes.end(), |
494 HashValuesEqual(good_hash)); | 494 HashValuesEqual(good_hash)); |
495 EXPECT_NE(dynamic_domain_state.dynamic_spki_hashes.end(), hash); | 495 EXPECT_NE(dynamic_domain_state.dynamic_pkp.spki_hashes.end(), hash); |
496 | 496 |
497 hash = std::find_if( | 497 hash = std::find_if( |
498 dynamic_domain_state.dynamic_spki_hashes.begin(), | 498 dynamic_domain_state.dynamic_pkp.spki_hashes.begin(), |
499 dynamic_domain_state.dynamic_spki_hashes.end(), | 499 dynamic_domain_state.dynamic_pkp.spki_hashes.end(), |
500 HashValuesEqual(backup_hash)); | 500 HashValuesEqual(backup_hash)); |
501 EXPECT_NE(dynamic_domain_state.dynamic_spki_hashes.end(), hash); | 501 EXPECT_NE(dynamic_domain_state.dynamic_pkp.spki_hashes.end(), hash); |
502 | 502 |
503 // Expect the overall state to reflect the header, too. | 503 // Expect the overall state to reflect the header, too. |
504 EXPECT_TRUE(state.GetDomainState(domain, true, &domain_state)); | 504 EXPECT_TRUE(state.GetDomainState(domain, true, &domain_state)); |
505 EXPECT_EQ(2UL, domain_state.dynamic_spki_hashes.size()); | 505 EXPECT_EQ(2UL, domain_state.dynamic_pkp.spki_hashes.size()); |
506 | 506 |
507 hash = std::find_if(domain_state.dynamic_spki_hashes.begin(), | 507 hash = std::find_if(domain_state.dynamic_pkp.spki_hashes.begin(), |
508 domain_state.dynamic_spki_hashes.end(), | 508 domain_state.dynamic_pkp.spki_hashes.end(), |
509 HashValuesEqual(good_hash)); | 509 HashValuesEqual(good_hash)); |
510 EXPECT_NE(domain_state.dynamic_spki_hashes.end(), hash); | 510 EXPECT_NE(domain_state.dynamic_pkp.spki_hashes.end(), hash); |
511 | 511 |
512 hash = std::find_if( | 512 hash = std::find_if( |
513 domain_state.dynamic_spki_hashes.begin(), | 513 domain_state.dynamic_pkp.spki_hashes.begin(), |
514 domain_state.dynamic_spki_hashes.end(), | 514 domain_state.dynamic_pkp.spki_hashes.end(), |
515 HashValuesEqual(backup_hash)); | 515 HashValuesEqual(backup_hash)); |
516 EXPECT_NE(domain_state.dynamic_spki_hashes.end(), hash); | 516 EXPECT_NE(domain_state.dynamic_pkp.spki_hashes.end(), hash); |
| 517 } |
| 518 |
| 519 TEST_F(HttpSecurityHeadersTest, NoClobberPins) { |
| 520 TransportSecurityState state; |
| 521 TransportSecurityState::DomainState domain_state; |
| 522 |
| 523 std::string domain("accounts.google.com"); |
| 524 |
| 525 // Retrieve the DomainState as it is by default, including its known good |
| 526 // pins. Assert sanity. |
| 527 EXPECT_TRUE(state.GetDomainState(domain, true, &domain_state)); |
| 528 HashValueVector saved_hashes = domain_state.static_pkp.spki_hashes; |
| 529 EXPECT_TRUE(domain_state.ShouldUpgradeToSSL()); |
| 530 EXPECT_TRUE(domain_state.HasPublicKeyPins()); |
| 531 |
| 532 // Add a dynamic header. Due to bug crbug.com/29386, this will mask the |
| 533 // static pins. However, we temporarily work around that in |
| 534 // CheckPublicKeyPins (invoked below). CheckPublicKeyPins should still |
| 535 // pass when given the original |saved_hashes|. |
| 536 EXPECT_TRUE(state.AddHSTSHeader(domain, "includesubdomains; max-age=10000")); |
| 537 EXPECT_TRUE(domain_state.ShouldUpgradeToSSL()); |
| 538 EXPECT_TRUE(state.GetDomainState(domain, true, &domain_state)); |
| 539 EXPECT_TRUE(domain_state.CheckPublicKeyPins(saved_hashes)); |
| 540 |
| 541 // Add a header, which should only update the dynamic state. |
| 542 HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA1); |
| 543 std::string good_pin = GetTestPin(1, HASH_VALUE_SHA1); |
| 544 std::string backup_pin = GetTestPin(2, HASH_VALUE_SHA1); |
| 545 std::string header = "max-age = 10000; " + good_pin + "; " + backup_pin; |
| 546 |
| 547 // Construct a fake SSLInfo that will pass AddHPKPHeader's checks. |
| 548 SSLInfo ssl_info; |
| 549 ssl_info.public_key_hashes.push_back(good_hash); |
| 550 ssl_info.public_key_hashes.push_back(saved_hashes[0]); |
| 551 EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info)); |
| 552 |
| 553 EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info)); |
| 554 EXPECT_TRUE(domain_state.ShouldUpgradeToSSL()); |
| 555 EXPECT_TRUE(state.GetDomainState(domain, true, &domain_state)); |
| 556 EXPECT_TRUE(domain_state.CheckPublicKeyPins(saved_hashes)); |
517 } | 557 } |
518 | 558 |
519 }; // namespace net | 559 }; // namespace net |
OLD | NEW |