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

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

Issue 1213783005: Send HPKP violation reports when a pin check fails (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rsleevi comments Created 5 years, 5 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
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 <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"
(...skipping 652 matching lines...) Expand 10 before | Expand all | Expand 10 after
663 HashValuesEqual(backup_hash)); 663 HashValuesEqual(backup_hash));
664 EXPECT_NE(dynamic_pkp_state.spki_hashes.end(), hash); 664 EXPECT_NE(dynamic_pkp_state.spki_hashes.end(), hash);
665 665
666 // Expect the overall state to reflect the header, too. 666 // Expect the overall state to reflect the header, too.
667 EXPECT_TRUE(state.HasPublicKeyPins(domain)); 667 EXPECT_TRUE(state.HasPublicKeyPins(domain));
668 HashValueVector hashes; 668 HashValueVector hashes;
669 hashes.push_back(good_hash); 669 hashes.push_back(good_hash);
670 std::string failure_log; 670 std::string failure_log;
671 const bool is_issued_by_known_root = true; 671 const bool is_issued_by_known_root = true;
672 EXPECT_TRUE(state.CheckPublicKeyPins( 672 EXPECT_TRUE(state.CheckPublicKeyPins(
673 domain, is_issued_by_known_root, hashes, &failure_log)); 673 domain, is_issued_by_known_root, hashes, 0, nullptr, nullptr,
674 TransportSecurityState::DO_NOT_SEND_PUBLIC_KEY_PIN_REPORT, &failure_log));
674 675
675 TransportSecurityState::PKPState new_dynamic_pkp_state; 676 TransportSecurityState::PKPState new_dynamic_pkp_state;
676 EXPECT_TRUE(state.GetDynamicPKPState(domain, &new_dynamic_pkp_state)); 677 EXPECT_TRUE(state.GetDynamicPKPState(domain, &new_dynamic_pkp_state));
677 EXPECT_EQ(2UL, new_dynamic_pkp_state.spki_hashes.size()); 678 EXPECT_EQ(2UL, new_dynamic_pkp_state.spki_hashes.size());
678 EXPECT_EQ(report_uri, new_dynamic_pkp_state.report_uri); 679 EXPECT_EQ(report_uri, new_dynamic_pkp_state.report_uri);
679 680
680 hash = std::find_if(new_dynamic_pkp_state.spki_hashes.begin(), 681 hash = std::find_if(new_dynamic_pkp_state.spki_hashes.begin(),
681 new_dynamic_pkp_state.spki_hashes.end(), 682 new_dynamic_pkp_state.spki_hashes.end(),
682 HashValuesEqual(good_hash)); 683 HashValuesEqual(good_hash));
683 EXPECT_NE(new_dynamic_pkp_state.spki_hashes.end(), hash); 684 EXPECT_NE(new_dynamic_pkp_state.spki_hashes.end(), hash);
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
755 EXPECT_TRUE(state.HasPublicKeyPins(domain)); 756 EXPECT_TRUE(state.HasPublicKeyPins(domain));
756 EXPECT_TRUE(state.ShouldSSLErrorsBeFatal(domain)); 757 EXPECT_TRUE(state.ShouldSSLErrorsBeFatal(domain));
757 std::string failure_log; 758 std::string failure_log;
758 759
759 // Damage the hashes to cause a pin validation failure. 760 // Damage the hashes to cause a pin validation failure.
760 new_static_pkp_state2.spki_hashes[0].data()[0] ^= 0x80; 761 new_static_pkp_state2.spki_hashes[0].data()[0] ^= 0x80;
761 new_static_pkp_state2.spki_hashes[1].data()[0] ^= 0x80; 762 new_static_pkp_state2.spki_hashes[1].data()[0] ^= 0x80;
762 new_static_pkp_state2.spki_hashes[2].data()[0] ^= 0x80; 763 new_static_pkp_state2.spki_hashes[2].data()[0] ^= 0x80;
763 764
764 const bool is_issued_by_known_root = true; 765 const bool is_issued_by_known_root = true;
765 EXPECT_FALSE(state.CheckPublicKeyPins(domain, is_issued_by_known_root, 766 EXPECT_FALSE(state.CheckPublicKeyPins(
766 new_static_pkp_state2.spki_hashes, 767 domain, is_issued_by_known_root, new_static_pkp_state2.spki_hashes, 0,
767 &failure_log)); 768 nullptr, nullptr,
769 TransportSecurityState::DO_NOT_SEND_PUBLIC_KEY_PIN_REPORT, &failure_log));
768 EXPECT_NE(0UL, failure_log.length()); 770 EXPECT_NE(0UL, failure_log.length());
769 } 771 }
770 772
771 // Tests that when a static HSTS and a static HPKP entry are present, adding a 773 // Tests that when a static HSTS and a static HPKP entry are present, adding a
772 // dynamic HSTS header does not clobber the static HPKP entry. Further, adding a 774 // dynamic HSTS header does not clobber the static HPKP entry. Further, adding a
773 // dynamic HPKP entry could not affect the HSTS entry for the site. 775 // dynamic HPKP entry could not affect the HSTS entry for the site.
774 TEST_F(HttpSecurityHeadersTest, NoClobberPins) { 776 TEST_F(HttpSecurityHeadersTest, NoClobberPins) {
775 TransportSecurityState state; 777 TransportSecurityState state;
776 TransportSecurityState::STSState sts_state; 778 TransportSecurityState::STSState sts_state;
777 TransportSecurityState::PKPState pkp_state; 779 TransportSecurityState::PKPState pkp_state;
(...skipping 11 matching lines...) Expand all
789 EXPECT_TRUE(state.ShouldUpgradeToSSL(domain)); 791 EXPECT_TRUE(state.ShouldUpgradeToSSL(domain));
790 EXPECT_TRUE(state.HasPublicKeyPins(domain)); 792 EXPECT_TRUE(state.HasPublicKeyPins(domain));
791 793
792 // Add a dynamic HSTS header. CheckPublicKeyPins should still pass when given 794 // Add a dynamic HSTS header. CheckPublicKeyPins should still pass when given
793 // the original |saved_hashes|, indicating that the static PKP data is still 795 // the original |saved_hashes|, indicating that the static PKP data is still
794 // configured for the domain. 796 // configured for the domain.
795 EXPECT_TRUE(state.AddHSTSHeader(domain, "includesubdomains; max-age=10000")); 797 EXPECT_TRUE(state.AddHSTSHeader(domain, "includesubdomains; max-age=10000"));
796 EXPECT_TRUE(state.ShouldUpgradeToSSL(domain)); 798 EXPECT_TRUE(state.ShouldUpgradeToSSL(domain));
797 std::string failure_log; 799 std::string failure_log;
798 const bool is_issued_by_known_root = true; 800 const bool is_issued_by_known_root = true;
799 EXPECT_TRUE(state.CheckPublicKeyPins(domain, 801 EXPECT_TRUE(state.CheckPublicKeyPins(
800 is_issued_by_known_root, 802 domain, is_issued_by_known_root, saved_hashes, 0, nullptr, nullptr,
801 saved_hashes, 803 TransportSecurityState::DO_NOT_SEND_PUBLIC_KEY_PIN_REPORT, &failure_log));
802 &failure_log));
803 804
804 // Add an HPKP header, which should only update the dynamic state. 805 // Add an HPKP header, which should only update the dynamic state.
805 HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA1); 806 HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA1);
806 std::string good_pin = GetTestPin(1, HASH_VALUE_SHA1); 807 std::string good_pin = GetTestPin(1, HASH_VALUE_SHA1);
807 std::string backup_pin = GetTestPin(2, HASH_VALUE_SHA1); 808 std::string backup_pin = GetTestPin(2, HASH_VALUE_SHA1);
808 std::string header = "max-age = 10000; " + good_pin + "; " + backup_pin; 809 std::string header = "max-age = 10000; " + good_pin + "; " + backup_pin;
809 810
810 // Construct a fake SSLInfo that will pass AddHPKPHeader's checks. 811 // Construct a fake SSLInfo that will pass AddHPKPHeader's checks.
811 SSLInfo ssl_info; 812 SSLInfo ssl_info;
812 ssl_info.public_key_hashes.push_back(good_hash); 813 ssl_info.public_key_hashes.push_back(good_hash);
813 ssl_info.public_key_hashes.push_back(saved_hashes[0]); 814 ssl_info.public_key_hashes.push_back(saved_hashes[0]);
814 EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info)); 815 EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info));
815 816
816 EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info)); 817 EXPECT_TRUE(state.AddHPKPHeader(domain, header, ssl_info));
817 // HSTS should still be configured for this domain. 818 // HSTS should still be configured for this domain.
818 EXPECT_TRUE(sts_state.ShouldUpgradeToSSL()); 819 EXPECT_TRUE(sts_state.ShouldUpgradeToSSL());
819 EXPECT_TRUE(state.ShouldUpgradeToSSL(domain)); 820 EXPECT_TRUE(state.ShouldUpgradeToSSL(domain));
820 // The dynamic pins, which do not match |saved_hashes|, should take 821 // The dynamic pins, which do not match |saved_hashes|, should take
821 // precedence over the static pins and cause the check to fail. 822 // precedence over the static pins and cause the check to fail.
822 EXPECT_FALSE(state.CheckPublicKeyPins(domain, 823 EXPECT_FALSE(state.CheckPublicKeyPins(
823 is_issued_by_known_root, 824 domain, is_issued_by_known_root, saved_hashes, 0, nullptr, nullptr,
824 saved_hashes, 825 TransportSecurityState::DO_NOT_SEND_PUBLIC_KEY_PIN_REPORT, &failure_log));
825 &failure_log));
826 } 826 }
827 827
828 // Tests that seeing an invalid HPKP header leaves the existing one alone. 828 // Tests that seeing an invalid HPKP header leaves the existing one alone.
829 TEST_F(HttpSecurityHeadersTest, IgnoreInvalidHeaders) { 829 TEST_F(HttpSecurityHeadersTest, IgnoreInvalidHeaders) {
830 TransportSecurityState state; 830 TransportSecurityState state;
831 831
832 HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA256); 832 HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA256);
833 std::string good_pin = GetTestPin(1, HASH_VALUE_SHA256); 833 std::string good_pin = GetTestPin(1, HASH_VALUE_SHA256);
834 std::string bad_pin = GetTestPin(2, HASH_VALUE_SHA256); 834 std::string bad_pin = GetTestPin(2, HASH_VALUE_SHA256);
835 std::string backup_pin = GetTestPin(3, HASH_VALUE_SHA256); 835 std::string backup_pin = GetTestPin(3, HASH_VALUE_SHA256);
836 836
837 SSLInfo ssl_info; 837 SSLInfo ssl_info;
838 ssl_info.public_key_hashes.push_back(good_hash); 838 ssl_info.public_key_hashes.push_back(good_hash);
839 839
840 // Add a valid HPKP header. 840 // Add a valid HPKP header.
841 EXPECT_TRUE(state.AddHPKPHeader( 841 EXPECT_TRUE(state.AddHPKPHeader(
842 "example.com", "max-age = 10000; " + good_pin + "; " + backup_pin, 842 "example.com", "max-age = 10000; " + good_pin + "; " + backup_pin,
843 ssl_info)); 843 ssl_info));
844 844
845 // Check the insertion was valid. 845 // Check the insertion was valid.
846 EXPECT_TRUE(state.HasPublicKeyPins("example.com")); 846 EXPECT_TRUE(state.HasPublicKeyPins("example.com"));
847 std::string failure_log; 847 std::string failure_log;
848 bool is_issued_by_known_root = true; 848 bool is_issued_by_known_root = true;
849 EXPECT_TRUE(state.CheckPublicKeyPins("example.com", is_issued_by_known_root, 849 EXPECT_TRUE(state.CheckPublicKeyPins(
850 ssl_info.public_key_hashes, 850 "example.com", is_issued_by_known_root, ssl_info.public_key_hashes, 0,
851 &failure_log)); 851 nullptr, nullptr,
852 TransportSecurityState::DO_NOT_SEND_PUBLIC_KEY_PIN_REPORT, &failure_log));
852 853
853 // Now assert an invalid one. This should fail. 854 // Now assert an invalid one. This should fail.
854 EXPECT_FALSE(state.AddHPKPHeader( 855 EXPECT_FALSE(state.AddHPKPHeader(
855 "example.com", "max-age = 10000; " + bad_pin + "; " + backup_pin, 856 "example.com", "max-age = 10000; " + bad_pin + "; " + backup_pin,
856 ssl_info)); 857 ssl_info));
857 858
858 // The old pins must still exist. 859 // The old pins must still exist.
859 EXPECT_TRUE(state.HasPublicKeyPins("example.com")); 860 EXPECT_TRUE(state.HasPublicKeyPins("example.com"));
860 EXPECT_TRUE(state.CheckPublicKeyPins("example.com", is_issued_by_known_root, 861 EXPECT_TRUE(state.CheckPublicKeyPins(
861 ssl_info.public_key_hashes, 862 "example.com", is_issued_by_known_root, ssl_info.public_key_hashes, 0,
862 &failure_log)); 863 nullptr, nullptr,
864 TransportSecurityState::DO_NOT_SEND_PUBLIC_KEY_PIN_REPORT, &failure_log));
863 } 865 }
864 866
865 }; // namespace net 867 }; // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698