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

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

Issue 433123003: Centralize the logic for checking public key pins (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix comments from sleevi Created 6 years, 4 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 | Annotate | Revision Log
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 "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 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 HashValueVector* out) { 77 HashValueVector* out) {
78 HashValue hash(HASH_VALUE_SHA1); 78 HashValue hash(HASH_VALUE_SHA1);
79 memcpy(hash.data(), sha1_hash, hash.size()); 79 memcpy(hash.data(), sha1_hash, hash.size());
80 out->push_back(hash); 80 out->push_back(hash);
81 return true; 81 return true;
82 } 82 }
83 83
84 } // namespace 84 } // namespace
85 85
86 TransportSecurityState::TransportSecurityState() 86 TransportSecurityState::TransportSecurityState()
87 : delegate_(NULL) { 87 : delegate_(NULL),
88 enable_static_pinning_(true) {
89 // Static pinning is only enabled for official builds to make sure that
90 // others don't end up with pins that cannot be easily updated.
91 #if !defined(OFFICIAL_BUILD) || defined(OS_ANDROID) || defined(OS_IOS)
92 enable_static_pinning_ = false;
93 #endif
88 DCHECK(CalledOnValidThread()); 94 DCHECK(CalledOnValidThread());
89 } 95 }
90 96
91 TransportSecurityState::Iterator::Iterator(const TransportSecurityState& state) 97 TransportSecurityState::Iterator::Iterator(const TransportSecurityState& state)
92 : iterator_(state.enabled_hosts_.begin()), 98 : iterator_(state.enabled_hosts_.begin()),
93 end_(state.enabled_hosts_.end()) { 99 end_(state.enabled_hosts_.end()) {
94 } 100 }
95 101
96 TransportSecurityState::Iterator::~Iterator() {} 102 TransportSecurityState::Iterator::~Iterator() {}
97 103
(...skipping 13 matching lines...) Expand all
111 117
112 DomainState static_state; 118 DomainState static_state;
113 if (GetStaticDomainState(host, sni_enabled, &static_state) && 119 if (GetStaticDomainState(host, sni_enabled, &static_state) &&
114 static_state.ShouldUpgradeToSSL()) { 120 static_state.ShouldUpgradeToSSL()) {
115 return true; 121 return true;
116 } 122 }
117 123
118 return false; 124 return false;
119 } 125 }
120 126
121 bool TransportSecurityState::CheckPublicKeyPins(const std::string& host, 127 bool TransportSecurityState::CheckPublicKeyPins(
122 bool sni_enabled, 128 const std::string& host,
123 const HashValueVector& hashes, 129 bool sni_available,
124 std::string* failure_log) { 130 bool is_issued_by_known_root,
131 const HashValueVector& public_key_hashes,
132 std::string* pinning_failure_log) {
133 // Perform pin validation if, and only if, all these conditions obtain:
134 //
135 // * the server's certificate chain chains up to a known root (i.e. not a
136 // user-installed trust anchor); and
137 // * the build is recent (very old builds should fail open so that users
138 // have some chance to recover).
139 //
140 if (!is_issued_by_known_root ||
141 !TransportSecurityState::IsBuildTimely() ||
wtc 2014/08/07 22:51:44 Nit: omit "TransportSecurityState::"
Ryan Hamilton 2014/08/07 23:19:04 Done.
142 !HasPublicKeyPins(host, sni_available)) {
143 return true;
144 }
145
146 bool pins_are_valid = CheckPublicKeyPinsImpl(host,
147 sni_available,
148 public_key_hashes,
149 pinning_failure_log);
150 if (!pins_are_valid) {
151 LOG(ERROR) << *pinning_failure_log;
152 ReportUMAOnPinFailure(host);
153 }
154
155 UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", pins_are_valid);
156 return pins_are_valid;
157 }
158
159 bool TransportSecurityState::CheckPublicKeyPinsImpl(
Ryan Sleevi 2014/08/07 22:19:07 So, I know you did this for the diff, but move thi
Ryan Hamilton 2014/08/07 22:49:39 Will do. I'll leave it here until I get an LGTM so
160 const std::string& host,
161 bool sni_enabled,
162 const HashValueVector& hashes,
163 std::string* failure_log) {
125 DomainState dynamic_state; 164 DomainState dynamic_state;
126 if (GetDynamicDomainState(host, &dynamic_state)) 165 if (GetDynamicDomainState(host, &dynamic_state))
127 return dynamic_state.CheckPublicKeyPins(hashes, failure_log); 166 return dynamic_state.CheckPublicKeyPins(hashes, failure_log);
128 167
129 DomainState static_state; 168 DomainState static_state;
130 if (GetStaticDomainState(host, sni_enabled, &static_state) && 169 if (GetStaticDomainState(host, sni_enabled, &static_state))
131 static_state.CheckPublicKeyPins(hashes, failure_log)) { 170 return static_state.CheckPublicKeyPins(hashes, failure_log);
132 return true;
133 }
134 171
172 // HasPublicKeyPins should have returned true in order for this method
173 // to have been called, so if we fall through to here, it's an error.
135 return false; 174 return false;
136 } 175 }
137 176
138 bool TransportSecurityState::HasPublicKeyPins(const std::string& host, 177 bool TransportSecurityState::HasPublicKeyPins(const std::string& host,
139 bool sni_enabled) { 178 bool sni_enabled) {
140 DomainState dynamic_state; 179 DomainState dynamic_state;
141 if (GetDynamicDomainState(host, &dynamic_state)) 180 if (GetDynamicDomainState(host, &dynamic_state))
142 return dynamic_state.HasPublicKeyPins(); 181 return dynamic_state.HasPublicKeyPins();
143 182
144 DomainState static_state; 183 DomainState static_state;
(...skipping 579 matching lines...) Expand 10 before | Expand all | Expand 10 after
724 if (sni_enabled) { 763 if (sni_enabled) {
725 entry = GetHSTSPreload(canonicalized_host, kPreloadedSNISTS, 764 entry = GetHSTSPreload(canonicalized_host, kPreloadedSNISTS,
726 kNumPreloadedSNISTS); 765 kNumPreloadedSNISTS);
727 if (entry && entry->pins.required_hashes == kGoogleAcceptableCerts) 766 if (entry && entry->pins.required_hashes == kGoogleAcceptableCerts)
728 return true; 767 return true;
729 } 768 }
730 769
731 return false; 770 return false;
732 } 771 }
733 772
734 // static 773 void TransportSecurityState::ReportUMAOnPinFailure(
735 void TransportSecurityState::ReportUMAOnPinFailure(const std::string& host) { 774 const std::string& host) const{
736 std::string canonicalized_host = CanonicalizeHost(host); 775 std::string canonicalized_host = CanonicalizeHost(host);
737 776
738 const struct HSTSPreload* entry = 777 const struct HSTSPreload* entry =
739 GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS); 778 GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS);
740 779
741 if (!entry) { 780 if (!entry) {
742 entry = GetHSTSPreload(canonicalized_host, kPreloadedSNISTS, 781 entry = GetHSTSPreload(canonicalized_host, kPreloadedSNISTS,
743 kNumPreloadedSNISTS); 782 kNumPreloadedSNISTS);
744 } 783 }
745 784
746 if (!entry) { 785 if (!entry) {
747 // We don't care to report pin failures for dynamic pins. 786 // We don't care to report pin failures for dynamic pins.
748 return; 787 return;
749 } 788 }
750 789
751 DCHECK(entry); 790 DCHECK(entry);
752 DCHECK(entry->pins.required_hashes); 791 DCHECK(entry->pins.required_hashes);
753 DCHECK(entry->second_level_domain_name != DOMAIN_NOT_PINNED); 792 DCHECK(entry->second_level_domain_name != DOMAIN_NOT_PINNED);
754 793
755 UMA_HISTOGRAM_ENUMERATION("Net.PublicKeyPinFailureDomain", 794 UMA_HISTOGRAM_ENUMERATION("Net.PublicKeyPinFailureDomain",
756 entry->second_level_domain_name, DOMAIN_NUM_EVENTS); 795 entry->second_level_domain_name, DOMAIN_NUM_EVENTS);
757 } 796 }
758 797
759 // static 798 bool TransportSecurityState::IsBuildTimely() const {
760 bool TransportSecurityState::IsBuildTimely() {
761 const base::Time build_time = base::GetBuildTime(); 799 const base::Time build_time = base::GetBuildTime();
762 // We consider built-in information to be timely for 10 weeks. 800 // We consider built-in information to be timely for 10 weeks.
763 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; 801 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */;
764 } 802 }
765 803
766 bool TransportSecurityState::GetStaticDomainState(const std::string& host, 804 bool TransportSecurityState::GetStaticDomainState(const std::string& host,
767 bool sni_enabled, 805 bool sni_enabled,
768 DomainState* out) const { 806 DomainState* out) const {
769 DCHECK(CalledOnValidThread()); 807 DCHECK(CalledOnValidThread());
770 808
809 if (!enable_static_pinning_)
810 return false;
811
771 const std::string canonicalized_host = CanonicalizeHost(host); 812 const std::string canonicalized_host = CanonicalizeHost(host);
772 813
773 out->sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS; 814 out->sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS;
774 out->sts.include_subdomains = false; 815 out->sts.include_subdomains = false;
775 out->pkp.include_subdomains = false; 816 out->pkp.include_subdomains = false;
776 817
777 const bool is_build_timely = IsBuildTimely(); 818 const bool is_build_timely = IsBuildTimely();
778 819
779 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) { 820 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
780 std::string host_sub_chunk(&canonicalized_host[i], 821 std::string host_sub_chunk(&canonicalized_host[i],
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
901 return pkp.spki_hashes.size() > 0 || pkp.bad_spki_hashes.size() > 0; 942 return pkp.spki_hashes.size() > 0 || pkp.bad_spki_hashes.size() > 0;
902 } 943 }
903 944
904 TransportSecurityState::DomainState::PKPState::PKPState() { 945 TransportSecurityState::DomainState::PKPState::PKPState() {
905 } 946 }
906 947
907 TransportSecurityState::DomainState::PKPState::~PKPState() { 948 TransportSecurityState::DomainState::PKPState::~PKPState() {
908 } 949 }
909 950
910 } // namespace 951 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698