| 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 <stdint.h> | 5 #include <stdint.h> |
| 6 #include <algorithm> | 6 #include <algorithm> |
| 7 | 7 |
| 8 #include "base/base64.h" | 8 #include "base/base64.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 692 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 703 dynamic_pkp_state.spki_hashes.end(), backup_hash); | 703 dynamic_pkp_state.spki_hashes.end(), backup_hash); |
| 704 EXPECT_NE(dynamic_pkp_state.spki_hashes.end(), hash); | 704 EXPECT_NE(dynamic_pkp_state.spki_hashes.end(), hash); |
| 705 | 705 |
| 706 // Expect the overall state to reflect the header, too. | 706 // Expect the overall state to reflect the header, too. |
| 707 EXPECT_TRUE(state.HasPublicKeyPins(domain)); | 707 EXPECT_TRUE(state.HasPublicKeyPins(domain)); |
| 708 HashValueVector hashes; | 708 HashValueVector hashes; |
| 709 hashes.push_back(good_hash); | 709 hashes.push_back(good_hash); |
| 710 std::string failure_log; | 710 std::string failure_log; |
| 711 const bool is_issued_by_known_root = true; | 711 const bool is_issued_by_known_root = true; |
| 712 HostPortPair domain_port(domain, 443); | 712 HostPortPair domain_port(domain, 443); |
| 713 EXPECT_TRUE(state.CheckPublicKeyPins( | 713 EXPECT_EQ(TransportSecurityState::PKPStatus::OK, |
| 714 domain_port, is_issued_by_known_root, hashes, nullptr, nullptr, | 714 state.CheckPublicKeyPins( |
| 715 TransportSecurityState::DISABLE_PIN_REPORTS, &failure_log)); | 715 domain_port, is_issued_by_known_root, hashes, nullptr, nullptr, |
| 716 TransportSecurityState::DISABLE_PIN_REPORTS, &failure_log)); |
| 716 | 717 |
| 717 TransportSecurityState::PKPState new_dynamic_pkp_state; | 718 TransportSecurityState::PKPState new_dynamic_pkp_state; |
| 718 EXPECT_TRUE(state.GetDynamicPKPState(domain, &new_dynamic_pkp_state)); | 719 EXPECT_TRUE(state.GetDynamicPKPState(domain, &new_dynamic_pkp_state)); |
| 719 EXPECT_EQ(2UL, new_dynamic_pkp_state.spki_hashes.size()); | 720 EXPECT_EQ(2UL, new_dynamic_pkp_state.spki_hashes.size()); |
| 720 EXPECT_EQ(report_uri, new_dynamic_pkp_state.report_uri); | 721 EXPECT_EQ(report_uri, new_dynamic_pkp_state.report_uri); |
| 721 | 722 |
| 722 hash = std::find(new_dynamic_pkp_state.spki_hashes.begin(), | 723 hash = std::find(new_dynamic_pkp_state.spki_hashes.begin(), |
| 723 new_dynamic_pkp_state.spki_hashes.end(), good_hash); | 724 new_dynamic_pkp_state.spki_hashes.end(), good_hash); |
| 724 EXPECT_NE(new_dynamic_pkp_state.spki_hashes.end(), hash); | 725 EXPECT_NE(new_dynamic_pkp_state.spki_hashes.end(), hash); |
| 725 | 726 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 788 EXPECT_TRUE(state.ShouldSSLErrorsBeFatal(domain)); | 789 EXPECT_TRUE(state.ShouldSSLErrorsBeFatal(domain)); |
| 789 std::string failure_log; | 790 std::string failure_log; |
| 790 | 791 |
| 791 // Damage the hashes to cause a pin validation failure. | 792 // Damage the hashes to cause a pin validation failure. |
| 792 new_static_pkp_state2.spki_hashes[0].data()[0] ^= 0x80; | 793 new_static_pkp_state2.spki_hashes[0].data()[0] ^= 0x80; |
| 793 new_static_pkp_state2.spki_hashes[1].data()[0] ^= 0x80; | 794 new_static_pkp_state2.spki_hashes[1].data()[0] ^= 0x80; |
| 794 new_static_pkp_state2.spki_hashes[2].data()[0] ^= 0x80; | 795 new_static_pkp_state2.spki_hashes[2].data()[0] ^= 0x80; |
| 795 | 796 |
| 796 const bool is_issued_by_known_root = true; | 797 const bool is_issued_by_known_root = true; |
| 797 HostPortPair domain_port(domain, 443); | 798 HostPortPair domain_port(domain, 443); |
| 798 EXPECT_FALSE(state.CheckPublicKeyPins( | 799 EXPECT_EQ(TransportSecurityState::PKPStatus::VIOLATED, |
| 799 domain_port, is_issued_by_known_root, new_static_pkp_state2.spki_hashes, | 800 state.CheckPublicKeyPins( |
| 800 nullptr, nullptr, TransportSecurityState::DISABLE_PIN_REPORTS, | 801 domain_port, is_issued_by_known_root, |
| 801 &failure_log)); | 802 new_static_pkp_state2.spki_hashes, nullptr, nullptr, |
| 803 TransportSecurityState::DISABLE_PIN_REPORTS, &failure_log)); |
| 802 EXPECT_NE(0UL, failure_log.length()); | 804 EXPECT_NE(0UL, failure_log.length()); |
| 803 } | 805 } |
| 804 | 806 |
| 805 // Tests that when a static HSTS and a static HPKP entry are present, adding a | 807 // Tests that when a static HSTS and a static HPKP entry are present, adding a |
| 806 // dynamic HSTS header does not clobber the static HPKP entry. Further, adding a | 808 // dynamic HSTS header does not clobber the static HPKP entry. Further, adding a |
| 807 // dynamic HPKP entry could not affect the HSTS entry for the site. | 809 // dynamic HPKP entry could not affect the HSTS entry for the site. |
| 808 TEST_F(HttpSecurityHeadersTest, NoClobberPins) { | 810 TEST_F(HttpSecurityHeadersTest, NoClobberPins) { |
| 809 TransportSecurityState state; | 811 TransportSecurityState state; |
| 810 TransportSecurityState::STSState sts_state; | 812 TransportSecurityState::STSState sts_state; |
| 811 TransportSecurityState::PKPState pkp_state; | 813 TransportSecurityState::PKPState pkp_state; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 824 EXPECT_TRUE(state.HasPublicKeyPins(domain)); | 826 EXPECT_TRUE(state.HasPublicKeyPins(domain)); |
| 825 | 827 |
| 826 // Add a dynamic HSTS header. CheckPublicKeyPins should still pass when given | 828 // Add a dynamic HSTS header. CheckPublicKeyPins should still pass when given |
| 827 // the original |saved_hashes|, indicating that the static PKP data is still | 829 // the original |saved_hashes|, indicating that the static PKP data is still |
| 828 // configured for the domain. | 830 // configured for the domain. |
| 829 EXPECT_TRUE(state.AddHSTSHeader(domain, "includesubdomains; max-age=10000")); | 831 EXPECT_TRUE(state.AddHSTSHeader(domain, "includesubdomains; max-age=10000")); |
| 830 EXPECT_TRUE(state.ShouldUpgradeToSSL(domain)); | 832 EXPECT_TRUE(state.ShouldUpgradeToSSL(domain)); |
| 831 std::string failure_log; | 833 std::string failure_log; |
| 832 const bool is_issued_by_known_root = true; | 834 const bool is_issued_by_known_root = true; |
| 833 HostPortPair domain_port(domain, 443); | 835 HostPortPair domain_port(domain, 443); |
| 834 EXPECT_TRUE(state.CheckPublicKeyPins( | 836 EXPECT_EQ( |
| 835 domain_port, is_issued_by_known_root, saved_hashes, nullptr, nullptr, | 837 TransportSecurityState::PKPStatus::OK, |
| 836 TransportSecurityState::DISABLE_PIN_REPORTS, &failure_log)); | 838 state.CheckPublicKeyPins( |
| 839 domain_port, is_issued_by_known_root, saved_hashes, nullptr, nullptr, |
| 840 TransportSecurityState::DISABLE_PIN_REPORTS, &failure_log)); |
| 837 | 841 |
| 838 // Add an HPKP header, which should only update the dynamic state. | 842 // Add an HPKP header, which should only update the dynamic state. |
| 839 HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA256); | 843 HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA256); |
| 840 std::string good_pin = GetTestPin(1, HASH_VALUE_SHA256); | 844 std::string good_pin = GetTestPin(1, HASH_VALUE_SHA256); |
| 841 std::string backup_pin = GetTestPin(2, HASH_VALUE_SHA256); | 845 std::string backup_pin = GetTestPin(2, HASH_VALUE_SHA256); |
| 842 std::string header = "max-age = 10000; " + good_pin + "; " + backup_pin; | 846 std::string header = "max-age = 10000; " + good_pin + "; " + backup_pin; |
| 843 | 847 |
| 844 // Construct a fake SSLInfo that will pass AddHPKPHeader's checks. | 848 // Construct a fake SSLInfo that will pass AddHPKPHeader's checks. |
| 845 SSLInfo ssl_info; | 849 SSLInfo ssl_info; |
| 846 ssl_info.public_key_hashes.push_back(good_hash); | 850 ssl_info.public_key_hashes.push_back(good_hash); |
| 847 ssl_info.public_key_hashes.push_back(saved_hashes[0]); | 851 ssl_info.public_key_hashes.push_back(saved_hashes[0]); |
| 848 EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info)); | 852 EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info)); |
| 849 | 853 |
| 850 EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info)); | 854 EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info)); |
| 851 // HSTS should still be configured for this domain. | 855 // HSTS should still be configured for this domain. |
| 852 EXPECT_TRUE(sts_state.ShouldUpgradeToSSL()); | 856 EXPECT_TRUE(sts_state.ShouldUpgradeToSSL()); |
| 853 EXPECT_TRUE(state.ShouldUpgradeToSSL(domain)); | 857 EXPECT_TRUE(state.ShouldUpgradeToSSL(domain)); |
| 854 // The dynamic pins, which do not match |saved_hashes|, should take | 858 // The dynamic pins, which do not match |saved_hashes|, should take |
| 855 // precedence over the static pins and cause the check to fail. | 859 // precedence over the static pins and cause the check to fail. |
| 856 EXPECT_FALSE(state.CheckPublicKeyPins( | 860 EXPECT_EQ( |
| 857 domain_port, is_issued_by_known_root, saved_hashes, nullptr, nullptr, | 861 TransportSecurityState::PKPStatus::VIOLATED, |
| 858 TransportSecurityState::DISABLE_PIN_REPORTS, &failure_log)); | 862 state.CheckPublicKeyPins( |
| 863 domain_port, is_issued_by_known_root, saved_hashes, nullptr, nullptr, |
| 864 TransportSecurityState::DISABLE_PIN_REPORTS, &failure_log)); |
| 859 } | 865 } |
| 860 | 866 |
| 861 // Tests that seeing an invalid HPKP header leaves the existing one alone. | 867 // Tests that seeing an invalid HPKP header leaves the existing one alone. |
| 862 TEST_F(HttpSecurityHeadersTest, IgnoreInvalidHeaders) { | 868 TEST_F(HttpSecurityHeadersTest, IgnoreInvalidHeaders) { |
| 863 TransportSecurityState state; | 869 TransportSecurityState state; |
| 864 | 870 |
| 865 HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA256); | 871 HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA256); |
| 866 std::string good_pin = GetTestPin(1, HASH_VALUE_SHA256); | 872 std::string good_pin = GetTestPin(1, HASH_VALUE_SHA256); |
| 867 std::string bad_pin = GetTestPin(2, HASH_VALUE_SHA256); | 873 std::string bad_pin = GetTestPin(2, HASH_VALUE_SHA256); |
| 868 std::string backup_pin = GetTestPin(3, HASH_VALUE_SHA256); | 874 std::string backup_pin = GetTestPin(3, HASH_VALUE_SHA256); |
| 869 | 875 |
| 870 SSLInfo ssl_info; | 876 SSLInfo ssl_info; |
| 871 ssl_info.public_key_hashes.push_back(good_hash); | 877 ssl_info.public_key_hashes.push_back(good_hash); |
| 872 | 878 |
| 873 // Add a valid HPKP header. | 879 // Add a valid HPKP header. |
| 874 EXPECT_TRUE(state.AddHPKPHeader( | 880 EXPECT_TRUE(state.AddHPKPHeader( |
| 875 "example.com", "max-age = 10000; " + good_pin + "; " + backup_pin, | 881 "example.com", "max-age = 10000; " + good_pin + "; " + backup_pin, |
| 876 ssl_info)); | 882 ssl_info)); |
| 877 | 883 |
| 878 // Check the insertion was valid. | 884 // Check the insertion was valid. |
| 879 EXPECT_TRUE(state.HasPublicKeyPins("example.com")); | 885 EXPECT_TRUE(state.HasPublicKeyPins("example.com")); |
| 880 std::string failure_log; | 886 std::string failure_log; |
| 881 bool is_issued_by_known_root = true; | 887 bool is_issued_by_known_root = true; |
| 882 HostPortPair domain_port("example.com", 443); | 888 HostPortPair domain_port("example.com", 443); |
| 883 EXPECT_TRUE(state.CheckPublicKeyPins( | 889 EXPECT_EQ(TransportSecurityState::PKPStatus::OK, |
| 884 domain_port, is_issued_by_known_root, ssl_info.public_key_hashes, nullptr, | 890 state.CheckPublicKeyPins( |
| 885 nullptr, TransportSecurityState::DISABLE_PIN_REPORTS, &failure_log)); | 891 domain_port, is_issued_by_known_root, |
| 892 ssl_info.public_key_hashes, nullptr, nullptr, |
| 893 TransportSecurityState::DISABLE_PIN_REPORTS, &failure_log)); |
| 886 | 894 |
| 887 // Now assert an invalid one. This should fail. | 895 // Now assert an invalid one. This should fail. |
| 888 EXPECT_FALSE(state.AddHPKPHeader( | 896 EXPECT_FALSE(state.AddHPKPHeader( |
| 889 "example.com", "max-age = 10000; " + bad_pin + "; " + backup_pin, | 897 "example.com", "max-age = 10000; " + bad_pin + "; " + backup_pin, |
| 890 ssl_info)); | 898 ssl_info)); |
| 891 | 899 |
| 892 // The old pins must still exist. | 900 // The old pins must still exist. |
| 893 EXPECT_TRUE(state.HasPublicKeyPins("example.com")); | 901 EXPECT_TRUE(state.HasPublicKeyPins("example.com")); |
| 894 EXPECT_TRUE(state.CheckPublicKeyPins( | 902 EXPECT_EQ(TransportSecurityState::PKPStatus::OK, |
| 895 domain_port, is_issued_by_known_root, ssl_info.public_key_hashes, nullptr, | 903 state.CheckPublicKeyPins( |
| 896 nullptr, TransportSecurityState::DISABLE_PIN_REPORTS, &failure_log)); | 904 domain_port, is_issued_by_known_root, |
| 905 ssl_info.public_key_hashes, nullptr, nullptr, |
| 906 TransportSecurityState::DISABLE_PIN_REPORTS, &failure_log)); |
| 897 } | 907 } |
| 898 | 908 |
| 899 }; // namespace net | 909 }; // namespace net |
| OLD | NEW |