| 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/sha1.h" | 9 #include "base/sha1.h" |
| 10 #include "base/strings/string_piece.h" | 10 #include "base/strings/string_piece.h" |
| 11 #include "crypto/sha2.h" | 11 #include "crypto/sha2.h" |
| 12 #include "net/base/host_port_pair.h" |
| 12 #include "net/base/test_completion_callback.h" | 13 #include "net/base/test_completion_callback.h" |
| 13 #include "net/http/http_security_headers.h" | 14 #include "net/http/http_security_headers.h" |
| 14 #include "net/http/http_util.h" | 15 #include "net/http/http_util.h" |
| 15 #include "net/http/transport_security_state.h" | 16 #include "net/http/transport_security_state.h" |
| 16 #include "net/log/net_log.h" | 17 #include "net/log/net_log.h" |
| 17 #include "net/ssl/ssl_info.h" | 18 #include "net/ssl/ssl_info.h" |
| 18 #include "testing/gtest/include/gtest/gtest.h" | 19 #include "testing/gtest/include/gtest/gtest.h" |
| 19 | 20 |
| 20 namespace net { | 21 namespace net { |
| 21 | 22 |
| (...skipping 649 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 671 dynamic_pkp_state.spki_hashes.end(), | 672 dynamic_pkp_state.spki_hashes.end(), |
| 672 HashValuesEqual(backup_hash)); | 673 HashValuesEqual(backup_hash)); |
| 673 EXPECT_NE(dynamic_pkp_state.spki_hashes.end(), hash); | 674 EXPECT_NE(dynamic_pkp_state.spki_hashes.end(), hash); |
| 674 | 675 |
| 675 // Expect the overall state to reflect the header, too. | 676 // Expect the overall state to reflect the header, too. |
| 676 EXPECT_TRUE(state.HasPublicKeyPins(domain)); | 677 EXPECT_TRUE(state.HasPublicKeyPins(domain)); |
| 677 HashValueVector hashes; | 678 HashValueVector hashes; |
| 678 hashes.push_back(good_hash); | 679 hashes.push_back(good_hash); |
| 679 std::string failure_log; | 680 std::string failure_log; |
| 680 const bool is_issued_by_known_root = true; | 681 const bool is_issued_by_known_root = true; |
| 682 HostPortPair domain_port(domain, 443); |
| 681 EXPECT_TRUE(state.CheckPublicKeyPins( | 683 EXPECT_TRUE(state.CheckPublicKeyPins( |
| 682 domain, is_issued_by_known_root, hashes, &failure_log)); | 684 domain_port, is_issued_by_known_root, hashes, nullptr, nullptr, |
| 685 TransportSecurityState::DISABLE_PIN_REPORTS, &failure_log)); |
| 683 | 686 |
| 684 TransportSecurityState::PKPState new_dynamic_pkp_state; | 687 TransportSecurityState::PKPState new_dynamic_pkp_state; |
| 685 EXPECT_TRUE(state.GetDynamicPKPState(domain, &new_dynamic_pkp_state)); | 688 EXPECT_TRUE(state.GetDynamicPKPState(domain, &new_dynamic_pkp_state)); |
| 686 EXPECT_EQ(2UL, new_dynamic_pkp_state.spki_hashes.size()); | 689 EXPECT_EQ(2UL, new_dynamic_pkp_state.spki_hashes.size()); |
| 687 EXPECT_EQ(report_uri, new_dynamic_pkp_state.report_uri); | 690 EXPECT_EQ(report_uri, new_dynamic_pkp_state.report_uri); |
| 688 | 691 |
| 689 hash = std::find_if(new_dynamic_pkp_state.spki_hashes.begin(), | 692 hash = std::find_if(new_dynamic_pkp_state.spki_hashes.begin(), |
| 690 new_dynamic_pkp_state.spki_hashes.end(), | 693 new_dynamic_pkp_state.spki_hashes.end(), |
| 691 HashValuesEqual(good_hash)); | 694 HashValuesEqual(good_hash)); |
| 692 EXPECT_NE(new_dynamic_pkp_state.spki_hashes.end(), hash); | 695 EXPECT_NE(new_dynamic_pkp_state.spki_hashes.end(), hash); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 764 EXPECT_TRUE(state.HasPublicKeyPins(domain)); | 767 EXPECT_TRUE(state.HasPublicKeyPins(domain)); |
| 765 EXPECT_TRUE(state.ShouldSSLErrorsBeFatal(domain)); | 768 EXPECT_TRUE(state.ShouldSSLErrorsBeFatal(domain)); |
| 766 std::string failure_log; | 769 std::string failure_log; |
| 767 | 770 |
| 768 // Damage the hashes to cause a pin validation failure. | 771 // Damage the hashes to cause a pin validation failure. |
| 769 new_static_pkp_state2.spki_hashes[0].data()[0] ^= 0x80; | 772 new_static_pkp_state2.spki_hashes[0].data()[0] ^= 0x80; |
| 770 new_static_pkp_state2.spki_hashes[1].data()[0] ^= 0x80; | 773 new_static_pkp_state2.spki_hashes[1].data()[0] ^= 0x80; |
| 771 new_static_pkp_state2.spki_hashes[2].data()[0] ^= 0x80; | 774 new_static_pkp_state2.spki_hashes[2].data()[0] ^= 0x80; |
| 772 | 775 |
| 773 const bool is_issued_by_known_root = true; | 776 const bool is_issued_by_known_root = true; |
| 774 EXPECT_FALSE(state.CheckPublicKeyPins(domain, is_issued_by_known_root, | 777 HostPortPair domain_port(domain, 443); |
| 775 new_static_pkp_state2.spki_hashes, | 778 EXPECT_FALSE(state.CheckPublicKeyPins( |
| 776 &failure_log)); | 779 domain_port, is_issued_by_known_root, new_static_pkp_state2.spki_hashes, |
| 780 nullptr, nullptr, TransportSecurityState::DISABLE_PIN_REPORTS, |
| 781 &failure_log)); |
| 777 EXPECT_NE(0UL, failure_log.length()); | 782 EXPECT_NE(0UL, failure_log.length()); |
| 778 } | 783 } |
| 779 | 784 |
| 780 // Tests that when a static HSTS and a static HPKP entry are present, adding a | 785 // Tests that when a static HSTS and a static HPKP entry are present, adding a |
| 781 // dynamic HSTS header does not clobber the static HPKP entry. Further, adding a | 786 // dynamic HSTS header does not clobber the static HPKP entry. Further, adding a |
| 782 // dynamic HPKP entry could not affect the HSTS entry for the site. | 787 // dynamic HPKP entry could not affect the HSTS entry for the site. |
| 783 TEST_F(HttpSecurityHeadersTest, NoClobberPins) { | 788 TEST_F(HttpSecurityHeadersTest, NoClobberPins) { |
| 784 TransportSecurityState state; | 789 TransportSecurityState state; |
| 785 TransportSecurityState::STSState sts_state; | 790 TransportSecurityState::STSState sts_state; |
| 786 TransportSecurityState::PKPState pkp_state; | 791 TransportSecurityState::PKPState pkp_state; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 798 EXPECT_TRUE(state.ShouldUpgradeToSSL(domain)); | 803 EXPECT_TRUE(state.ShouldUpgradeToSSL(domain)); |
| 799 EXPECT_TRUE(state.HasPublicKeyPins(domain)); | 804 EXPECT_TRUE(state.HasPublicKeyPins(domain)); |
| 800 | 805 |
| 801 // Add a dynamic HSTS header. CheckPublicKeyPins should still pass when given | 806 // Add a dynamic HSTS header. CheckPublicKeyPins should still pass when given |
| 802 // the original |saved_hashes|, indicating that the static PKP data is still | 807 // the original |saved_hashes|, indicating that the static PKP data is still |
| 803 // configured for the domain. | 808 // configured for the domain. |
| 804 EXPECT_TRUE(state.AddHSTSHeader(domain, "includesubdomains; max-age=10000")); | 809 EXPECT_TRUE(state.AddHSTSHeader(domain, "includesubdomains; max-age=10000")); |
| 805 EXPECT_TRUE(state.ShouldUpgradeToSSL(domain)); | 810 EXPECT_TRUE(state.ShouldUpgradeToSSL(domain)); |
| 806 std::string failure_log; | 811 std::string failure_log; |
| 807 const bool is_issued_by_known_root = true; | 812 const bool is_issued_by_known_root = true; |
| 808 EXPECT_TRUE(state.CheckPublicKeyPins(domain, | 813 HostPortPair domain_port(domain, 443); |
| 809 is_issued_by_known_root, | 814 EXPECT_TRUE(state.CheckPublicKeyPins( |
| 810 saved_hashes, | 815 domain_port, is_issued_by_known_root, saved_hashes, nullptr, nullptr, |
| 811 &failure_log)); | 816 TransportSecurityState::DISABLE_PIN_REPORTS, &failure_log)); |
| 812 | 817 |
| 813 // Add an HPKP header, which should only update the dynamic state. | 818 // Add an HPKP header, which should only update the dynamic state. |
| 814 HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA1); | 819 HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA1); |
| 815 std::string good_pin = GetTestPin(1, HASH_VALUE_SHA1); | 820 std::string good_pin = GetTestPin(1, HASH_VALUE_SHA1); |
| 816 std::string backup_pin = GetTestPin(2, HASH_VALUE_SHA1); | 821 std::string backup_pin = GetTestPin(2, HASH_VALUE_SHA1); |
| 817 std::string header = "max-age = 10000; " + good_pin + "; " + backup_pin; | 822 std::string header = "max-age = 10000; " + good_pin + "; " + backup_pin; |
| 818 | 823 |
| 819 // Construct a fake SSLInfo that will pass AddHPKPHeader's checks. | 824 // Construct a fake SSLInfo that will pass AddHPKPHeader's checks. |
| 820 SSLInfo ssl_info; | 825 SSLInfo ssl_info; |
| 821 ssl_info.public_key_hashes.push_back(good_hash); | 826 ssl_info.public_key_hashes.push_back(good_hash); |
| 822 ssl_info.public_key_hashes.push_back(saved_hashes[0]); | 827 ssl_info.public_key_hashes.push_back(saved_hashes[0]); |
| 823 EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info)); | 828 EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info)); |
| 824 | 829 |
| 825 EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info)); | 830 EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info)); |
| 826 // HSTS should still be configured for this domain. | 831 // HSTS should still be configured for this domain. |
| 827 EXPECT_TRUE(sts_state.ShouldUpgradeToSSL()); | 832 EXPECT_TRUE(sts_state.ShouldUpgradeToSSL()); |
| 828 EXPECT_TRUE(state.ShouldUpgradeToSSL(domain)); | 833 EXPECT_TRUE(state.ShouldUpgradeToSSL(domain)); |
| 829 // The dynamic pins, which do not match |saved_hashes|, should take | 834 // The dynamic pins, which do not match |saved_hashes|, should take |
| 830 // precedence over the static pins and cause the check to fail. | 835 // precedence over the static pins and cause the check to fail. |
| 831 EXPECT_FALSE(state.CheckPublicKeyPins(domain, | 836 EXPECT_FALSE(state.CheckPublicKeyPins( |
| 832 is_issued_by_known_root, | 837 domain_port, is_issued_by_known_root, saved_hashes, nullptr, nullptr, |
| 833 saved_hashes, | 838 TransportSecurityState::DISABLE_PIN_REPORTS, &failure_log)); |
| 834 &failure_log)); | |
| 835 } | 839 } |
| 836 | 840 |
| 837 // Tests that seeing an invalid HPKP header leaves the existing one alone. | 841 // Tests that seeing an invalid HPKP header leaves the existing one alone. |
| 838 TEST_F(HttpSecurityHeadersTest, IgnoreInvalidHeaders) { | 842 TEST_F(HttpSecurityHeadersTest, IgnoreInvalidHeaders) { |
| 839 TransportSecurityState state; | 843 TransportSecurityState state; |
| 840 | 844 |
| 841 HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA256); | 845 HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA256); |
| 842 std::string good_pin = GetTestPin(1, HASH_VALUE_SHA256); | 846 std::string good_pin = GetTestPin(1, HASH_VALUE_SHA256); |
| 843 std::string bad_pin = GetTestPin(2, HASH_VALUE_SHA256); | 847 std::string bad_pin = GetTestPin(2, HASH_VALUE_SHA256); |
| 844 std::string backup_pin = GetTestPin(3, HASH_VALUE_SHA256); | 848 std::string backup_pin = GetTestPin(3, HASH_VALUE_SHA256); |
| 845 | 849 |
| 846 SSLInfo ssl_info; | 850 SSLInfo ssl_info; |
| 847 ssl_info.public_key_hashes.push_back(good_hash); | 851 ssl_info.public_key_hashes.push_back(good_hash); |
| 848 | 852 |
| 849 // Add a valid HPKP header. | 853 // Add a valid HPKP header. |
| 850 EXPECT_TRUE(state.AddHPKPHeader( | 854 EXPECT_TRUE(state.AddHPKPHeader( |
| 851 "example.com", "max-age = 10000; " + good_pin + "; " + backup_pin, | 855 "example.com", "max-age = 10000; " + good_pin + "; " + backup_pin, |
| 852 ssl_info)); | 856 ssl_info)); |
| 853 | 857 |
| 854 // Check the insertion was valid. | 858 // Check the insertion was valid. |
| 855 EXPECT_TRUE(state.HasPublicKeyPins("example.com")); | 859 EXPECT_TRUE(state.HasPublicKeyPins("example.com")); |
| 856 std::string failure_log; | 860 std::string failure_log; |
| 857 bool is_issued_by_known_root = true; | 861 bool is_issued_by_known_root = true; |
| 858 EXPECT_TRUE(state.CheckPublicKeyPins("example.com", is_issued_by_known_root, | 862 HostPortPair domain_port("example.com", 443); |
| 859 ssl_info.public_key_hashes, | 863 EXPECT_TRUE(state.CheckPublicKeyPins( |
| 860 &failure_log)); | 864 domain_port, is_issued_by_known_root, ssl_info.public_key_hashes, nullptr, |
| 865 nullptr, TransportSecurityState::DISABLE_PIN_REPORTS, &failure_log)); |
| 861 | 866 |
| 862 // Now assert an invalid one. This should fail. | 867 // Now assert an invalid one. This should fail. |
| 863 EXPECT_FALSE(state.AddHPKPHeader( | 868 EXPECT_FALSE(state.AddHPKPHeader( |
| 864 "example.com", "max-age = 10000; " + bad_pin + "; " + backup_pin, | 869 "example.com", "max-age = 10000; " + bad_pin + "; " + backup_pin, |
| 865 ssl_info)); | 870 ssl_info)); |
| 866 | 871 |
| 867 // The old pins must still exist. | 872 // The old pins must still exist. |
| 868 EXPECT_TRUE(state.HasPublicKeyPins("example.com")); | 873 EXPECT_TRUE(state.HasPublicKeyPins("example.com")); |
| 869 EXPECT_TRUE(state.CheckPublicKeyPins("example.com", is_issued_by_known_root, | 874 EXPECT_TRUE(state.CheckPublicKeyPins( |
| 870 ssl_info.public_key_hashes, | 875 domain_port, is_issued_by_known_root, ssl_info.public_key_hashes, nullptr, |
| 871 &failure_log)); | 876 nullptr, TransportSecurityState::DISABLE_PIN_REPORTS, &failure_log)); |
| 872 } | 877 } |
| 873 | 878 |
| 874 }; // namespace net | 879 }; // namespace net |
| OLD | NEW |