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 "net/http/transport_security_state.h" | 5 #include "net/http/transport_security_state.h" |
6 | 6 |
7 #if defined(USE_OPENSSL) | 7 #if defined(USE_OPENSSL) |
8 #include <openssl/ecdsa.h> | 8 #include <openssl/ecdsa.h> |
9 #include <openssl/ssl.h> | 9 #include <openssl/ssl.h> |
10 #else // !defined(USE_OPENSSL) | 10 #else // !defined(USE_OPENSSL) |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 DCHECK(CalledOnValidThread()); | 93 DCHECK(CalledOnValidThread()); |
94 } | 94 } |
95 | 95 |
96 TransportSecurityState::Iterator::Iterator(const TransportSecurityState& state) | 96 TransportSecurityState::Iterator::Iterator(const TransportSecurityState& state) |
97 : iterator_(state.enabled_hosts_.begin()), | 97 : iterator_(state.enabled_hosts_.begin()), |
98 end_(state.enabled_hosts_.end()) { | 98 end_(state.enabled_hosts_.end()) { |
99 } | 99 } |
100 | 100 |
101 TransportSecurityState::Iterator::~Iterator() {} | 101 TransportSecurityState::Iterator::~Iterator() {} |
102 | 102 |
103 bool TransportSecurityState::ShouldSSLErrorsBeFatal(const std::string& host, | 103 bool TransportSecurityState::ShouldSSLErrorsBeFatal(const std::string& host) { |
104 bool sni_enabled) { | |
105 DomainState state; | 104 DomainState state; |
106 if (GetStaticDomainState(host, sni_enabled, &state)) | 105 if (GetStaticDomainState(host, &state)) |
107 return true; | 106 return true; |
108 return GetDynamicDomainState(host, &state); | 107 return GetDynamicDomainState(host, &state); |
109 } | 108 } |
110 | 109 |
111 bool TransportSecurityState::ShouldUpgradeToSSL(const std::string& host, | 110 bool TransportSecurityState::ShouldUpgradeToSSL(const std::string& host) { |
112 bool sni_enabled) { | |
113 DomainState dynamic_state; | 111 DomainState dynamic_state; |
114 if (GetDynamicDomainState(host, &dynamic_state)) | 112 if (GetDynamicDomainState(host, &dynamic_state)) |
115 return dynamic_state.ShouldUpgradeToSSL(); | 113 return dynamic_state.ShouldUpgradeToSSL(); |
116 | 114 |
117 DomainState static_state; | 115 DomainState static_state; |
118 if (GetStaticDomainState(host, sni_enabled, &static_state) && | 116 if (GetStaticDomainState(host, &static_state) && |
119 static_state.ShouldUpgradeToSSL()) { | 117 static_state.ShouldUpgradeToSSL()) { |
120 return true; | 118 return true; |
121 } | 119 } |
122 | 120 |
123 return false; | 121 return false; |
124 } | 122 } |
125 | 123 |
126 bool TransportSecurityState::CheckPublicKeyPins( | 124 bool TransportSecurityState::CheckPublicKeyPins( |
127 const std::string& host, | 125 const std::string& host, |
128 bool sni_available, | |
129 bool is_issued_by_known_root, | 126 bool is_issued_by_known_root, |
130 const HashValueVector& public_key_hashes, | 127 const HashValueVector& public_key_hashes, |
131 std::string* pinning_failure_log) { | 128 std::string* pinning_failure_log) { |
132 // Perform pin validation if, and only if, all these conditions obtain: | 129 // Perform pin validation if, and only if, all these conditions obtain: |
133 // | 130 // |
134 // * the server's certificate chain chains up to a known root (i.e. not a | 131 // * the server's certificate chain chains up to a known root (i.e. not a |
135 // user-installed trust anchor); and | 132 // user-installed trust anchor); and |
136 // * the server actually has public key pins. | 133 // * the server actually has public key pins. |
137 if (!is_issued_by_known_root || !HasPublicKeyPins(host, sni_available)) { | 134 if (!is_issued_by_known_root || !HasPublicKeyPins(host)) { |
138 return true; | 135 return true; |
139 } | 136 } |
140 | 137 |
141 bool pins_are_valid = CheckPublicKeyPinsImpl( | 138 bool pins_are_valid = CheckPublicKeyPinsImpl( |
142 host, sni_available, public_key_hashes, pinning_failure_log); | 139 host, public_key_hashes, pinning_failure_log); |
143 if (!pins_are_valid) { | 140 if (!pins_are_valid) { |
144 LOG(ERROR) << *pinning_failure_log; | 141 LOG(ERROR) << *pinning_failure_log; |
145 ReportUMAOnPinFailure(host); | 142 ReportUMAOnPinFailure(host); |
146 } | 143 } |
147 | 144 |
148 UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", pins_are_valid); | 145 UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", pins_are_valid); |
149 return pins_are_valid; | 146 return pins_are_valid; |
150 } | 147 } |
151 | 148 |
152 bool TransportSecurityState::HasPublicKeyPins(const std::string& host, | 149 bool TransportSecurityState::HasPublicKeyPins(const std::string& host) { |
153 bool sni_enabled) { | |
154 DomainState dynamic_state; | 150 DomainState dynamic_state; |
155 if (GetDynamicDomainState(host, &dynamic_state)) | 151 if (GetDynamicDomainState(host, &dynamic_state)) |
156 return dynamic_state.HasPublicKeyPins(); | 152 return dynamic_state.HasPublicKeyPins(); |
157 | 153 |
158 DomainState static_state; | 154 DomainState static_state; |
159 if (GetStaticDomainState(host, sni_enabled, &static_state)) { | 155 if (GetStaticDomainState(host, &static_state)) { |
160 if (static_state.HasPublicKeyPins()) | 156 if (static_state.HasPublicKeyPins()) |
161 return true; | 157 return true; |
162 } | 158 } |
163 | 159 |
164 return false; | 160 return false; |
165 } | 161 } |
166 | 162 |
167 void TransportSecurityState::SetDelegate( | 163 void TransportSecurityState::SetDelegate( |
168 TransportSecurityState::Delegate* delegate) { | 164 TransportSecurityState::Delegate* delegate) { |
169 DCHECK(CalledOnValidThread()); | 165 DCHECK(CalledOnValidThread()); |
(...skipping 558 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
728 | 724 |
729 domain_state.pkp.last_observed = base::Time::Now(); | 725 domain_state.pkp.last_observed = base::Time::Now(); |
730 domain_state.pkp.include_subdomains = include_subdomains; | 726 domain_state.pkp.include_subdomains = include_subdomains; |
731 domain_state.pkp.expiry = expiry; | 727 domain_state.pkp.expiry = expiry; |
732 domain_state.pkp.spki_hashes = hashes; | 728 domain_state.pkp.spki_hashes = hashes; |
733 EnableHost(host, domain_state); | 729 EnableHost(host, domain_state); |
734 return true; | 730 return true; |
735 } | 731 } |
736 | 732 |
737 // static | 733 // static |
738 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host, | 734 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host) { |
739 bool sni_enabled) { | |
740 std::string canonicalized_host = CanonicalizeHost(host); | 735 std::string canonicalized_host = CanonicalizeHost(host); |
741 const struct HSTSPreload* entry = | 736 const struct HSTSPreload* entry = |
742 GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS); | 737 GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS); |
743 | 738 |
744 if (entry && entry->pins.required_hashes == kGoogleAcceptableCerts) | 739 return entry && entry->pins.required_hashes == kGoogleAcceptableCerts; |
745 return true; | |
746 | |
747 if (sni_enabled) { | |
748 entry = GetHSTSPreload(canonicalized_host, kPreloadedSNISTS, | |
749 kNumPreloadedSNISTS); | |
750 if (entry && entry->pins.required_hashes == kGoogleAcceptableCerts) | |
751 return true; | |
752 } | |
753 | |
754 return false; | |
755 } | 740 } |
756 | 741 |
757 // static | 742 // static |
758 void TransportSecurityState::ReportUMAOnPinFailure(const std::string& host) { | 743 void TransportSecurityState::ReportUMAOnPinFailure(const std::string& host) { |
759 std::string canonicalized_host = CanonicalizeHost(host); | 744 std::string canonicalized_host = CanonicalizeHost(host); |
760 | 745 |
761 const struct HSTSPreload* entry = | 746 const struct HSTSPreload* entry = |
762 GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS); | 747 GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS); |
763 | 748 |
764 if (!entry) { | 749 if (!entry) { |
765 entry = GetHSTSPreload(canonicalized_host, kPreloadedSNISTS, | |
766 kNumPreloadedSNISTS); | |
767 } | |
768 | |
769 if (!entry) { | |
770 // We don't care to report pin failures for dynamic pins. | 750 // We don't care to report pin failures for dynamic pins. |
771 return; | 751 return; |
772 } | 752 } |
773 | 753 |
774 DCHECK(entry); | 754 DCHECK(entry); |
775 DCHECK(entry->pins.required_hashes); | 755 DCHECK(entry->pins.required_hashes); |
776 DCHECK(entry->second_level_domain_name != DOMAIN_NOT_PINNED); | 756 DCHECK(entry->second_level_domain_name != DOMAIN_NOT_PINNED); |
777 | 757 |
778 UMA_HISTOGRAM_ENUMERATION("Net.PublicKeyPinFailureDomain", | 758 UMA_HISTOGRAM_ENUMERATION("Net.PublicKeyPinFailureDomain", |
779 entry->second_level_domain_name, DOMAIN_NUM_EVENTS); | 759 entry->second_level_domain_name, DOMAIN_NUM_EVENTS); |
780 } | 760 } |
781 | 761 |
782 // static | 762 // static |
783 bool TransportSecurityState::IsBuildTimely() { | 763 bool TransportSecurityState::IsBuildTimely() { |
784 const base::Time build_time = base::GetBuildTime(); | 764 const base::Time build_time = base::GetBuildTime(); |
785 // We consider built-in information to be timely for 10 weeks. | 765 // We consider built-in information to be timely for 10 weeks. |
786 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; | 766 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; |
787 } | 767 } |
788 | 768 |
789 bool TransportSecurityState::CheckPublicKeyPinsImpl( | 769 bool TransportSecurityState::CheckPublicKeyPinsImpl( |
790 const std::string& host, | 770 const std::string& host, |
791 bool sni_enabled, | |
792 const HashValueVector& hashes, | 771 const HashValueVector& hashes, |
793 std::string* failure_log) { | 772 std::string* failure_log) { |
794 DomainState dynamic_state; | 773 DomainState dynamic_state; |
795 if (GetDynamicDomainState(host, &dynamic_state)) | 774 if (GetDynamicDomainState(host, &dynamic_state)) |
796 return dynamic_state.CheckPublicKeyPins(hashes, failure_log); | 775 return dynamic_state.CheckPublicKeyPins(hashes, failure_log); |
797 | 776 |
798 DomainState static_state; | 777 DomainState static_state; |
799 if (GetStaticDomainState(host, sni_enabled, &static_state)) | 778 if (GetStaticDomainState(host, &static_state)) |
800 return static_state.CheckPublicKeyPins(hashes, failure_log); | 779 return static_state.CheckPublicKeyPins(hashes, failure_log); |
801 | 780 |
802 // HasPublicKeyPins should have returned true in order for this method | 781 // HasPublicKeyPins should have returned true in order for this method |
803 // to have been called, so if we fall through to here, it's an error. | 782 // to have been called, so if we fall through to here, it's an error. |
804 return false; | 783 return false; |
805 } | 784 } |
806 | 785 |
807 bool TransportSecurityState::GetStaticDomainState(const std::string& host, | 786 bool TransportSecurityState::GetStaticDomainState(const std::string& host, |
808 bool sni_enabled, | |
809 DomainState* out) const { | 787 DomainState* out) const { |
810 DCHECK(CalledOnValidThread()); | 788 DCHECK(CalledOnValidThread()); |
811 | 789 |
812 const std::string canonicalized_host = CanonicalizeHost(host); | 790 const std::string canonicalized_host = CanonicalizeHost(host); |
813 | 791 |
814 out->sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS; | 792 out->sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS; |
815 out->sts.include_subdomains = false; | 793 out->sts.include_subdomains = false; |
816 out->pkp.include_subdomains = false; | 794 out->pkp.include_subdomains = false; |
817 | 795 |
818 const bool is_build_timely = IsBuildTimely(); | 796 const bool is_build_timely = IsBuildTimely(); |
819 | 797 |
820 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) { | 798 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) { |
821 std::string host_sub_chunk(&canonicalized_host[i], | 799 std::string host_sub_chunk(&canonicalized_host[i], |
822 canonicalized_host.size() - i); | 800 canonicalized_host.size() - i); |
823 out->domain = DNSDomainToString(host_sub_chunk); | 801 out->domain = DNSDomainToString(host_sub_chunk); |
824 bool ret; | 802 bool ret; |
825 if (is_build_timely && HasPreload(kPreloadedSTS, | 803 if (is_build_timely && HasPreload(kPreloadedSTS, |
826 kNumPreloadedSTS, | 804 kNumPreloadedSTS, |
827 canonicalized_host, | 805 canonicalized_host, |
828 i, | 806 i, |
829 enable_static_pins_, | 807 enable_static_pins_, |
830 out, | 808 out, |
831 &ret)) { | 809 &ret)) { |
832 return ret; | 810 return ret; |
833 } | 811 } |
834 if (sni_enabled && is_build_timely && HasPreload(kPreloadedSNISTS, | |
835 kNumPreloadedSNISTS, | |
836 canonicalized_host, | |
837 i, | |
838 enable_static_pins_, | |
839 out, | |
840 &ret)) { | |
841 return ret; | |
842 } | |
843 } | 812 } |
844 | 813 |
845 return false; | 814 return false; |
846 } | 815 } |
847 | 816 |
848 bool TransportSecurityState::GetDynamicDomainState(const std::string& host, | 817 bool TransportSecurityState::GetDynamicDomainState(const std::string& host, |
849 DomainState* result) { | 818 DomainState* result) { |
850 DCHECK(CalledOnValidThread()); | 819 DCHECK(CalledOnValidThread()); |
851 | 820 |
852 DomainState state; | 821 DomainState state; |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
949 return pkp.spki_hashes.size() > 0 || pkp.bad_spki_hashes.size() > 0; | 918 return pkp.spki_hashes.size() > 0 || pkp.bad_spki_hashes.size() > 0; |
950 } | 919 } |
951 | 920 |
952 TransportSecurityState::DomainState::PKPState::PKPState() { | 921 TransportSecurityState::DomainState::PKPState::PKPState() { |
953 } | 922 } |
954 | 923 |
955 TransportSecurityState::DomainState::PKPState::~PKPState() { | 924 TransportSecurityState::DomainState::PKPState::~PKPState() { |
956 } | 925 } |
957 | 926 |
958 } // namespace | 927 } // namespace |
OLD | NEW |