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 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
74 } | 74 } |
75 | 75 |
76 bool AddHash(const char* sha1_hash, | 76 bool AddHash(const char* sha1_hash, |
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 // Updates |other| to contain the most recent observations found | |
85 // between the states |state| and |other|. | |
86 void MergeDomainStates(const TransportSecurityState::DomainState& state, | |
87 TransportSecurityState::DomainState* other) { | |
88 if (other->pkp.last_observed < state.pkp.last_observed) | |
89 other->pkp = state.pkp; | |
90 if (other->sts.last_observed < state.sts.last_observed) | |
91 other->sts = state.sts; | |
92 } | |
93 | |
84 } // namespace | 94 } // namespace |
85 | 95 |
86 TransportSecurityState::TransportSecurityState() | 96 TransportSecurityState::TransportSecurityState() |
87 : delegate_(NULL) { | 97 : delegate_(NULL) { |
88 DCHECK(CalledOnValidThread()); | 98 DCHECK(CalledOnValidThread()); |
89 } | 99 } |
90 | 100 |
91 TransportSecurityState::Iterator::Iterator(const TransportSecurityState& state) | 101 TransportSecurityState::Iterator::Iterator(const TransportSecurityState& state) |
92 : iterator_(state.enabled_hosts_.begin()), | 102 : iterator_(state.enabled_hosts_.begin()), |
93 end_(state.enabled_hosts_.end()) { | 103 end_(state.enabled_hosts_.end()) { |
94 } | 104 } |
95 | 105 |
96 TransportSecurityState::Iterator::~Iterator() {} | 106 TransportSecurityState::Iterator::~Iterator() {} |
97 | 107 |
108 bool TransportSecurityState::ShouldSSLErrorsBeFatal(const std::string& host, | |
109 bool sni_enabled) { | |
110 DomainState state; | |
111 if (GetStaticDomainState(host, sni_enabled, &state)) | |
112 return true; | |
113 return GetDynamicDomainState(host, &state); | |
114 } | |
115 | |
116 bool TransportSecurityState::ShouldUpgradeToSSL(const std::string& host, | |
117 bool sni_enabled) { | |
118 DomainState dynamic_state; | |
119 if (GetDynamicDomainState(host, &dynamic_state)) | |
120 return dynamic_state.ShouldUpgradeToSSL(); | |
121 | |
122 DomainState static_state; | |
123 if (GetStaticDomainState(host, sni_enabled, &static_state)) { | |
124 if (static_state.ShouldUpgradeToSSL()) | |
Ryan Sleevi
2014/05/05 23:24:23
just combine?
if (GetStaticDomainState(...) &&
palmer
2014/05/06 18:38:00
Done.
| |
125 return true; | |
126 } | |
127 | |
128 return false; | |
129 } | |
130 | |
131 bool TransportSecurityState::CheckPublicKeyPins(const std::string& host, | |
132 bool sni_enabled, | |
133 const HashValueVector& hashes, | |
134 std::string* failure_log) { | |
135 DomainState dynamic_state; | |
136 if (GetDynamicDomainState(host, &dynamic_state)) | |
137 return dynamic_state.CheckPublicKeyPins(hashes, failure_log); | |
138 | |
139 DomainState static_state; | |
140 if (GetStaticDomainState(host, sni_enabled, &static_state)) { | |
141 if (static_state.CheckPublicKeyPins(hashes, failure_log)) | |
142 return true; | |
Ryan Sleevi
2014/05/05 23:24:23
ditto re: combining
palmer
2014/05/06 18:38:00
Done.
| |
143 } | |
144 | |
145 return false; | |
146 } | |
147 | |
148 bool TransportSecurityState::HasPublicKeyPins(const std::string& host, | |
149 bool sni_enabled) { | |
150 DomainState dynamic_state; | |
151 if (GetDynamicDomainState(host, &dynamic_state)) | |
152 return dynamic_state.HasPublicKeyPins(); | |
153 | |
154 DomainState static_state; | |
155 if (GetStaticDomainState(host, sni_enabled, &static_state)) { | |
156 if (static_state.HasPublicKeyPins()) | |
157 return true; | |
158 } | |
159 | |
160 return false; | |
161 } | |
162 | |
98 void TransportSecurityState::SetDelegate( | 163 void TransportSecurityState::SetDelegate( |
99 TransportSecurityState::Delegate* delegate) { | 164 TransportSecurityState::Delegate* delegate) { |
100 DCHECK(CalledOnValidThread()); | 165 DCHECK(CalledOnValidThread()); |
101 delegate_ = delegate; | 166 delegate_ = delegate; |
102 } | 167 } |
103 | 168 |
104 void TransportSecurityState::EnableHost(const std::string& host, | 169 void TransportSecurityState::EnableHost(const std::string& host, |
105 const DomainState& state) { | 170 const DomainState& state) { |
106 DCHECK(CalledOnValidThread()); | 171 DCHECK(CalledOnValidThread()); |
107 | 172 |
(...skipping 20 matching lines...) Expand all Loading... | |
128 DomainStateMap::iterator i = enabled_hosts_.find( | 193 DomainStateMap::iterator i = enabled_hosts_.find( |
129 HashHost(canonicalized_host)); | 194 HashHost(canonicalized_host)); |
130 if (i != enabled_hosts_.end()) { | 195 if (i != enabled_hosts_.end()) { |
131 enabled_hosts_.erase(i); | 196 enabled_hosts_.erase(i); |
132 DirtyNotify(); | 197 DirtyNotify(); |
133 return true; | 198 return true; |
134 } | 199 } |
135 return false; | 200 return false; |
136 } | 201 } |
137 | 202 |
138 bool TransportSecurityState::GetDomainState(const std::string& host, | |
139 bool sni_enabled, | |
140 DomainState* result) { | |
141 DCHECK(CalledOnValidThread()); | |
142 | |
143 DomainState state; | |
144 const std::string canonicalized_host = CanonicalizeHost(host); | |
145 if (canonicalized_host.empty()) | |
146 return false; | |
147 | |
148 bool has_preload = GetStaticDomainState(canonicalized_host, sni_enabled, | |
149 &state); | |
150 std::string canonicalized_preload = CanonicalizeHost(state.domain); | |
151 GetDynamicDomainState(host, &state); | |
152 | |
153 base::Time current_time(base::Time::Now()); | |
154 | |
155 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) { | |
156 std::string host_sub_chunk(&canonicalized_host[i], | |
157 canonicalized_host.size() - i); | |
158 // Exact match of a preload always wins. | |
159 if (has_preload && host_sub_chunk == canonicalized_preload) { | |
160 *result = state; | |
161 return true; | |
162 } | |
163 | |
164 DomainStateMap::iterator j = | |
165 enabled_hosts_.find(HashHost(host_sub_chunk)); | |
166 if (j == enabled_hosts_.end()) | |
167 continue; | |
168 | |
169 if (current_time > j->second.upgrade_expiry && | |
170 current_time > j->second.dynamic_spki_hashes_expiry) { | |
171 enabled_hosts_.erase(j); | |
172 DirtyNotify(); | |
173 continue; | |
174 } | |
175 | |
176 state = j->second; | |
177 state.domain = DNSDomainToString(host_sub_chunk); | |
178 | |
179 // Succeed if we matched the domain exactly or if subdomain matches are | |
180 // allowed. | |
181 if (i == 0 || j->second.sts_include_subdomains || | |
182 j->second.pkp_include_subdomains) { | |
183 *result = state; | |
184 return true; | |
185 } | |
186 | |
187 return false; | |
188 } | |
189 | |
190 return false; | |
191 } | |
192 | |
193 void TransportSecurityState::ClearDynamicData() { | 203 void TransportSecurityState::ClearDynamicData() { |
194 DCHECK(CalledOnValidThread()); | 204 DCHECK(CalledOnValidThread()); |
195 enabled_hosts_.clear(); | 205 enabled_hosts_.clear(); |
196 } | 206 } |
197 | 207 |
198 void TransportSecurityState::DeleteAllDynamicDataSince(const base::Time& time) { | 208 void TransportSecurityState::DeleteAllDynamicDataSince(const base::Time& time) { |
199 DCHECK(CalledOnValidThread()); | 209 DCHECK(CalledOnValidThread()); |
200 | 210 |
201 bool dirtied = false; | 211 bool dirtied = false; |
202 DomainStateMap::iterator i = enabled_hosts_.begin(); | 212 DomainStateMap::iterator i = enabled_hosts_.begin(); |
203 while (i != enabled_hosts_.end()) { | 213 while (i != enabled_hosts_.end()) { |
204 if (i->second.sts_observed >= time && i->second.pkp_observed >= time) { | 214 if (i->second.sts.last_observed >= time && |
215 i->second.pkp.last_observed >= time) { | |
205 dirtied = true; | 216 dirtied = true; |
206 enabled_hosts_.erase(i++); | 217 enabled_hosts_.erase(i++); |
207 continue; | 218 continue; |
208 } | 219 } |
209 | 220 |
210 if (i->second.sts_observed >= time) { | 221 if (i->second.sts.last_observed >= time) { |
211 dirtied = true; | 222 dirtied = true; |
212 i->second.upgrade_mode = DomainState::MODE_DEFAULT; | 223 i->second.sts.upgrade_mode = DomainState::MODE_DEFAULT; |
213 } else if (i->second.pkp_observed >= time) { | 224 } else if (i->second.pkp.last_observed >= time) { |
214 dirtied = true; | 225 dirtied = true; |
215 i->second.dynamic_spki_hashes.clear(); | 226 i->second.pkp.spki_hashes.clear(); |
Ryan Sleevi
2014/05/05 23:24:23
Shouldn't you also update the expiry (to clear it
palmer
2014/05/06 18:38:00
Done.
| |
216 } | 227 } |
217 ++i; | 228 ++i; |
218 } | 229 } |
219 | 230 |
220 if (dirtied) | 231 if (dirtied) |
221 DirtyNotify(); | 232 DirtyNotify(); |
222 } | 233 } |
223 | 234 |
224 TransportSecurityState::~TransportSecurityState() { | 235 TransportSecurityState::~TransportSecurityState() { |
225 DCHECK(CalledOnValidThread()); | 236 DCHECK(CalledOnValidThread()); |
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
548 static bool HasPreload(const struct HSTSPreload* entries, size_t num_entries, | 559 static bool HasPreload(const struct HSTSPreload* entries, size_t num_entries, |
549 const std::string& canonicalized_host, size_t i, | 560 const std::string& canonicalized_host, size_t i, |
550 TransportSecurityState::DomainState* out, bool* ret) { | 561 TransportSecurityState::DomainState* out, bool* ret) { |
551 for (size_t j = 0; j < num_entries; j++) { | 562 for (size_t j = 0; j < num_entries; j++) { |
552 if (entries[j].length == canonicalized_host.size() - i && | 563 if (entries[j].length == canonicalized_host.size() - i && |
553 memcmp(entries[j].dns_name, &canonicalized_host[i], | 564 memcmp(entries[j].dns_name, &canonicalized_host[i], |
554 entries[j].length) == 0) { | 565 entries[j].length) == 0) { |
555 if (!entries[j].include_subdomains && i != 0) { | 566 if (!entries[j].include_subdomains && i != 0) { |
556 *ret = false; | 567 *ret = false; |
557 } else { | 568 } else { |
558 out->sts_include_subdomains = entries[j].include_subdomains; | 569 out->sts.include_subdomains = entries[j].include_subdomains; |
559 out->pkp_include_subdomains = entries[j].include_subdomains; | 570 out->sts.last_observed = base::GetBuildTime(); |
571 out->pkp.include_subdomains = entries[j].include_subdomains; | |
572 out->pkp.last_observed = base::GetBuildTime(); | |
560 *ret = true; | 573 *ret = true; |
574 out->sts.upgrade_mode = | |
575 TransportSecurityState::DomainState::MODE_FORCE_HTTPS; | |
561 if (!entries[j].https_required) | 576 if (!entries[j].https_required) |
562 out->upgrade_mode = TransportSecurityState::DomainState::MODE_DEFAULT; | 577 out->sts.upgrade_mode = |
578 TransportSecurityState::DomainState::MODE_DEFAULT; | |
563 if (entries[j].pins.required_hashes) { | 579 if (entries[j].pins.required_hashes) { |
564 const char* const* sha1_hash = entries[j].pins.required_hashes; | 580 const char* const* sha1_hash = entries[j].pins.required_hashes; |
565 while (*sha1_hash) { | 581 while (*sha1_hash) { |
566 AddHash(*sha1_hash, &out->static_spki_hashes); | 582 AddHash(*sha1_hash, &out->pkp.spki_hashes); |
567 sha1_hash++; | 583 sha1_hash++; |
568 } | 584 } |
569 } | 585 } |
570 if (entries[j].pins.excluded_hashes) { | 586 if (entries[j].pins.excluded_hashes) { |
571 const char* const* sha1_hash = entries[j].pins.excluded_hashes; | 587 const char* const* sha1_hash = entries[j].pins.excluded_hashes; |
572 while (*sha1_hash) { | 588 while (*sha1_hash) { |
573 AddHash(*sha1_hash, &out->bad_static_spki_hashes); | 589 AddHash(*sha1_hash, &out->pkp.bad_spki_hashes); |
574 sha1_hash++; | 590 sha1_hash++; |
575 } | 591 } |
576 } | 592 } |
577 } | 593 } |
578 return true; | 594 return true; |
579 } | 595 } |
580 } | 596 } |
581 return false; | 597 return false; |
582 } | 598 } |
583 | 599 |
(...skipping 27 matching lines...) Expand all Loading... | |
611 } | 627 } |
612 | 628 |
613 bool TransportSecurityState::AddHSTSHeader(const std::string& host, | 629 bool TransportSecurityState::AddHSTSHeader(const std::string& host, |
614 const std::string& value) { | 630 const std::string& value) { |
615 DCHECK(CalledOnValidThread()); | 631 DCHECK(CalledOnValidThread()); |
616 | 632 |
617 base::Time now = base::Time::Now(); | 633 base::Time now = base::Time::Now(); |
618 base::TimeDelta max_age; | 634 base::TimeDelta max_age; |
619 TransportSecurityState::DomainState domain_state; | 635 TransportSecurityState::DomainState domain_state; |
620 GetDynamicDomainState(host, &domain_state); | 636 GetDynamicDomainState(host, &domain_state); |
621 if (ParseHSTSHeader(value, &max_age, &domain_state.sts_include_subdomains)) { | 637 if (ParseHSTSHeader(value, &max_age, &domain_state.sts.include_subdomains)) { |
622 // Handle max-age == 0 | 638 // Handle max-age == 0 |
623 if (max_age.InSeconds() == 0) | 639 if (max_age.InSeconds() == 0) |
624 domain_state.upgrade_mode = DomainState::MODE_DEFAULT; | 640 domain_state.sts.upgrade_mode = DomainState::MODE_DEFAULT; |
625 else | 641 else |
626 domain_state.upgrade_mode = DomainState::MODE_FORCE_HTTPS; | 642 domain_state.sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS; |
627 domain_state.sts_observed = now; | 643 domain_state.sts.last_observed = now; |
628 domain_state.upgrade_expiry = now + max_age; | 644 domain_state.sts.expiry = now + max_age; |
629 EnableHost(host, domain_state); | 645 EnableHost(host, domain_state); |
630 return true; | 646 return true; |
631 } | 647 } |
632 return false; | 648 return false; |
633 } | 649 } |
634 | 650 |
635 bool TransportSecurityState::AddHPKPHeader(const std::string& host, | 651 bool TransportSecurityState::AddHPKPHeader(const std::string& host, |
636 const std::string& value, | 652 const std::string& value, |
637 const SSLInfo& ssl_info) { | 653 const SSLInfo& ssl_info) { |
638 DCHECK(CalledOnValidThread()); | 654 DCHECK(CalledOnValidThread()); |
639 | 655 |
640 base::Time now = base::Time::Now(); | 656 base::Time now = base::Time::Now(); |
641 base::TimeDelta max_age; | 657 base::TimeDelta max_age; |
642 TransportSecurityState::DomainState domain_state; | 658 TransportSecurityState::DomainState domain_state; |
643 GetDynamicDomainState(host, &domain_state); | 659 GetDynamicDomainState(host, &domain_state); |
644 if (ParseHPKPHeader(value, ssl_info.public_key_hashes, | 660 if (ParseHPKPHeader(value, |
645 &max_age, &domain_state.pkp_include_subdomains, | 661 ssl_info.public_key_hashes, |
646 &domain_state.dynamic_spki_hashes)) { | 662 &max_age, |
663 &domain_state.pkp.include_subdomains, | |
664 &domain_state.pkp.spki_hashes)) { | |
647 // TODO(palmer): http://crbug.com/243865 handle max-age == 0. | 665 // TODO(palmer): http://crbug.com/243865 handle max-age == 0. |
648 domain_state.pkp_observed = now; | 666 domain_state.pkp.last_observed = now; |
649 domain_state.dynamic_spki_hashes_expiry = now + max_age; | 667 domain_state.pkp.expiry = now + max_age; |
650 EnableHost(host, domain_state); | 668 EnableHost(host, domain_state); |
651 return true; | 669 return true; |
652 } | 670 } |
653 return false; | 671 return false; |
654 } | 672 } |
655 | 673 |
656 bool TransportSecurityState::AddHSTS(const std::string& host, | 674 bool TransportSecurityState::AddHSTS(const std::string& host, |
657 const base::Time& expiry, | 675 const base::Time& expiry, |
658 bool include_subdomains) { | 676 bool include_subdomains) { |
659 DCHECK(CalledOnValidThread()); | 677 DCHECK(CalledOnValidThread()); |
660 | 678 |
661 // Copy-and-modify the existing DomainState for this host (if any). | 679 // Copy-and-modify the existing DomainState for this host (if any). |
662 TransportSecurityState::DomainState domain_state; | 680 TransportSecurityState::DomainState domain_state; |
663 const std::string canonicalized_host = CanonicalizeHost(host); | 681 const std::string canonicalized_host = CanonicalizeHost(host); |
664 const std::string hashed_host = HashHost(canonicalized_host); | 682 const std::string hashed_host = HashHost(canonicalized_host); |
665 DomainStateMap::const_iterator i = enabled_hosts_.find( | 683 DomainStateMap::const_iterator i = enabled_hosts_.find( |
666 hashed_host); | 684 hashed_host); |
667 if (i != enabled_hosts_.end()) | 685 if (i != enabled_hosts_.end()) |
668 domain_state = i->second; | 686 domain_state = i->second; |
669 | 687 |
670 domain_state.sts_observed = base::Time::Now(); | 688 domain_state.sts.last_observed = base::Time::Now(); |
671 domain_state.sts_include_subdomains = include_subdomains; | 689 domain_state.sts.include_subdomains = include_subdomains; |
672 domain_state.upgrade_expiry = expiry; | 690 domain_state.sts.expiry = expiry; |
673 domain_state.upgrade_mode = DomainState::MODE_FORCE_HTTPS; | 691 domain_state.sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS; |
674 EnableHost(host, domain_state); | 692 EnableHost(host, domain_state); |
675 return true; | 693 return true; |
676 } | 694 } |
677 | 695 |
678 bool TransportSecurityState::AddHPKP(const std::string& host, | 696 bool TransportSecurityState::AddHPKP(const std::string& host, |
679 const base::Time& expiry, | 697 const base::Time& expiry, |
680 bool include_subdomains, | 698 bool include_subdomains, |
681 const HashValueVector& hashes) { | 699 const HashValueVector& hashes) { |
682 DCHECK(CalledOnValidThread()); | 700 DCHECK(CalledOnValidThread()); |
683 | 701 |
684 // Copy-and-modify the existing DomainState for this host (if any). | 702 // Copy-and-modify the existing DomainState for this host (if any). |
685 TransportSecurityState::DomainState domain_state; | 703 TransportSecurityState::DomainState domain_state; |
686 const std::string canonicalized_host = CanonicalizeHost(host); | 704 const std::string canonicalized_host = CanonicalizeHost(host); |
687 const std::string hashed_host = HashHost(canonicalized_host); | 705 const std::string hashed_host = HashHost(canonicalized_host); |
688 DomainStateMap::const_iterator i = enabled_hosts_.find( | 706 DomainStateMap::const_iterator i = enabled_hosts_.find( |
689 hashed_host); | 707 hashed_host); |
690 if (i != enabled_hosts_.end()) | 708 if (i != enabled_hosts_.end()) |
691 domain_state = i->second; | 709 domain_state = i->second; |
692 | 710 |
693 domain_state.pkp_observed = base::Time::Now(); | 711 domain_state.pkp.last_observed = base::Time::Now(); |
694 domain_state.pkp_include_subdomains = include_subdomains; | 712 domain_state.pkp.include_subdomains = include_subdomains; |
695 domain_state.dynamic_spki_hashes_expiry = expiry; | 713 domain_state.pkp.expiry = expiry; |
696 domain_state.dynamic_spki_hashes = hashes; | 714 domain_state.pkp.spki_hashes = hashes; |
697 EnableHost(host, domain_state); | 715 EnableHost(host, domain_state); |
698 return true; | 716 return true; |
699 } | 717 } |
700 | 718 |
701 // static | 719 // static |
702 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host, | 720 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host, |
703 bool sni_enabled) { | 721 bool sni_enabled) { |
704 std::string canonicalized_host = CanonicalizeHost(host); | 722 std::string canonicalized_host = CanonicalizeHost(host); |
705 const struct HSTSPreload* entry = | 723 const struct HSTSPreload* entry = |
706 GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS); | 724 GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
743 entry->second_level_domain_name, DOMAIN_NUM_EVENTS); | 761 entry->second_level_domain_name, DOMAIN_NUM_EVENTS); |
744 } | 762 } |
745 | 763 |
746 // static | 764 // static |
747 bool TransportSecurityState::IsBuildTimely() { | 765 bool TransportSecurityState::IsBuildTimely() { |
748 const base::Time build_time = base::GetBuildTime(); | 766 const base::Time build_time = base::GetBuildTime(); |
749 // We consider built-in information to be timely for 10 weeks. | 767 // We consider built-in information to be timely for 10 weeks. |
750 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; | 768 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; |
751 } | 769 } |
752 | 770 |
753 bool TransportSecurityState::GetStaticDomainState( | 771 bool TransportSecurityState::GetStaticDomainState(const std::string& host, |
754 const std::string& canonicalized_host, | 772 bool sni_enabled, |
755 bool sni_enabled, | 773 DomainState* out) { |
756 DomainState* out) { | |
757 DCHECK(CalledOnValidThread()); | 774 DCHECK(CalledOnValidThread()); |
758 | 775 |
759 out->upgrade_mode = DomainState::MODE_FORCE_HTTPS; | 776 const std::string canonicalized_host = CanonicalizeHost(host); |
760 out->sts_include_subdomains = false; | 777 |
761 out->pkp_include_subdomains = false; | 778 out->sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS; |
779 out->sts.include_subdomains = false; | |
780 out->pkp.include_subdomains = false; | |
762 | 781 |
763 const bool is_build_timely = IsBuildTimely(); | 782 const bool is_build_timely = IsBuildTimely(); |
764 | 783 |
765 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) { | 784 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) { |
766 std::string host_sub_chunk(&canonicalized_host[i], | 785 std::string host_sub_chunk(&canonicalized_host[i], |
767 canonicalized_host.size() - i); | 786 canonicalized_host.size() - i); |
768 out->domain = DNSDomainToString(host_sub_chunk); | 787 out->domain = DNSDomainToString(host_sub_chunk); |
769 bool ret; | 788 bool ret; |
770 if (is_build_timely && | 789 if (is_build_timely && |
771 HasPreload(kPreloadedSTS, kNumPreloadedSTS, canonicalized_host, i, out, | 790 HasPreload(kPreloadedSTS, kNumPreloadedSTS, canonicalized_host, i, out, |
(...skipping 23 matching lines...) Expand all Loading... | |
795 base::Time current_time(base::Time::Now()); | 814 base::Time current_time(base::Time::Now()); |
796 | 815 |
797 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) { | 816 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) { |
798 std::string host_sub_chunk(&canonicalized_host[i], | 817 std::string host_sub_chunk(&canonicalized_host[i], |
799 canonicalized_host.size() - i); | 818 canonicalized_host.size() - i); |
800 DomainStateMap::iterator j = | 819 DomainStateMap::iterator j = |
801 enabled_hosts_.find(HashHost(host_sub_chunk)); | 820 enabled_hosts_.find(HashHost(host_sub_chunk)); |
802 if (j == enabled_hosts_.end()) | 821 if (j == enabled_hosts_.end()) |
803 continue; | 822 continue; |
804 | 823 |
805 if (current_time > j->second.upgrade_expiry && | 824 if (current_time > j->second.sts.expiry && |
806 current_time > j->second.dynamic_spki_hashes_expiry) { | 825 current_time > j->second.pkp.expiry) { |
807 enabled_hosts_.erase(j); | 826 enabled_hosts_.erase(j); |
808 DirtyNotify(); | 827 DirtyNotify(); |
809 continue; | 828 continue; |
810 } | 829 } |
811 | 830 |
812 state = j->second; | 831 state = j->second; |
813 state.domain = DNSDomainToString(host_sub_chunk); | 832 state.domain = DNSDomainToString(host_sub_chunk); |
814 | 833 |
815 // Succeed if we matched the domain exactly or if subdomain matches are | 834 // Succeed if we matched the domain exactly or if subdomain matches are |
816 // allowed. | 835 // allowed. |
817 if (i == 0 || j->second.sts_include_subdomains || | 836 if (i == 0 || j->second.sts.include_subdomains || |
818 j->second.pkp_include_subdomains) { | 837 j->second.pkp.include_subdomains) { |
819 *result = state; | 838 *result = state; |
820 return true; | 839 return true; |
821 } | 840 } |
822 | 841 |
823 return false; | 842 return false; |
824 } | 843 } |
825 | 844 |
826 return false; | 845 return false; |
827 } | 846 } |
828 | 847 |
829 | |
830 void TransportSecurityState::AddOrUpdateEnabledHosts( | 848 void TransportSecurityState::AddOrUpdateEnabledHosts( |
831 const std::string& hashed_host, const DomainState& state) { | 849 const std::string& hashed_host, const DomainState& state) { |
832 DCHECK(CalledOnValidThread()); | 850 DCHECK(CalledOnValidThread()); |
833 enabled_hosts_[hashed_host] = state; | 851 enabled_hosts_[hashed_host] = state; |
834 } | 852 } |
835 | 853 |
836 TransportSecurityState::DomainState::DomainState() | 854 TransportSecurityState::DomainState::DomainState() { |
837 : upgrade_mode(MODE_DEFAULT), | 855 sts.upgrade_mode = MODE_DEFAULT; |
838 sts_include_subdomains(false), | 856 sts.include_subdomains = false; |
839 pkp_include_subdomains(false) { | 857 pkp.include_subdomains = false; |
840 base::Time now(base::Time::Now()); | |
841 sts_observed = now; | |
842 pkp_observed = now; | |
843 } | 858 } |
844 | 859 |
845 TransportSecurityState::DomainState::~DomainState() { | 860 TransportSecurityState::DomainState::~DomainState() { |
846 } | 861 } |
847 | 862 |
848 bool TransportSecurityState::DomainState::CheckPublicKeyPins( | 863 bool TransportSecurityState::DomainState::CheckPublicKeyPins( |
849 const HashValueVector& hashes, std::string* failure_log) const { | 864 const HashValueVector& hashes, std::string* failure_log) const { |
850 // Validate that hashes is not empty. By the time this code is called (in | 865 // Validate that hashes is not empty. By the time this code is called (in |
851 // production), that should never happen, but it's good to be defensive. | 866 // production), that should never happen, but it's good to be defensive. |
852 // And, hashes *can* be empty in some test scenarios. | 867 // And, hashes *can* be empty in some test scenarios. |
853 if (hashes.empty()) { | 868 if (hashes.empty()) { |
854 *failure_log = "Rejecting empty public key chain for public-key-pinned " | 869 failure_log->append( |
855 "domains: " + domain; | 870 "Rejecting empty public key chain for public-key-pinned domains: " + |
871 domain); | |
856 return false; | 872 return false; |
857 } | 873 } |
858 | 874 |
859 if (HashesIntersect(bad_static_spki_hashes, hashes)) { | 875 if (HashesIntersect(pkp.bad_spki_hashes, hashes)) { |
860 *failure_log = "Rejecting public key chain for domain " + domain + | 876 failure_log->append("Rejecting public key chain for domain " + domain + |
861 ". Validated chain: " + HashesToBase64String(hashes) + | 877 ". Validated chain: " + HashesToBase64String(hashes) + |
862 ", matches one or more bad hashes: " + | 878 ", matches one or more bad hashes: " + |
863 HashesToBase64String(bad_static_spki_hashes); | 879 HashesToBase64String(pkp.bad_spki_hashes)); |
864 return false; | 880 return false; |
865 } | 881 } |
866 | 882 |
867 // If there are no pins, then any valid chain is acceptable. | 883 // If there are no pins, then any valid chain is acceptable. |
868 if (dynamic_spki_hashes.empty() && static_spki_hashes.empty()) | 884 if (pkp.spki_hashes.empty()) |
869 return true; | 885 return true; |
870 | 886 |
871 if (HashesIntersect(dynamic_spki_hashes, hashes) || | 887 if (HashesIntersect(pkp.spki_hashes, hashes)) { |
872 HashesIntersect(static_spki_hashes, hashes)) { | |
873 return true; | 888 return true; |
874 } | 889 } |
875 | 890 |
876 *failure_log = "Rejecting public key chain for domain " + domain + | 891 failure_log->append("Rejecting public key chain for domain " + domain + |
877 ". Validated chain: " + HashesToBase64String(hashes) + | 892 ". Validated chain: " + HashesToBase64String(hashes) + |
878 ", expected: " + HashesToBase64String(dynamic_spki_hashes) + | 893 ", expected: " + HashesToBase64String(pkp.spki_hashes)); |
879 " or: " + HashesToBase64String(static_spki_hashes); | |
880 return false; | 894 return false; |
881 } | 895 } |
882 | 896 |
883 bool TransportSecurityState::DomainState::ShouldUpgradeToSSL() const { | 897 bool TransportSecurityState::DomainState::ShouldUpgradeToSSL() const { |
884 return upgrade_mode == MODE_FORCE_HTTPS; | 898 return sts.upgrade_mode == MODE_FORCE_HTTPS; |
885 } | 899 } |
886 | 900 |
887 bool TransportSecurityState::DomainState::ShouldSSLErrorsBeFatal() const { | 901 bool TransportSecurityState::DomainState::ShouldSSLErrorsBeFatal() const { |
888 return true; | 902 return true; |
889 } | 903 } |
890 | 904 |
891 bool TransportSecurityState::DomainState::HasPublicKeyPins() const { | 905 bool TransportSecurityState::DomainState::HasPublicKeyPins() const { |
892 return static_spki_hashes.size() > 0 || | 906 return pkp.spki_hashes.size() > 0 || pkp.bad_spki_hashes.size() > 0; |
893 bad_static_spki_hashes.size() > 0 || | |
894 dynamic_spki_hashes.size() > 0; | |
895 } | 907 } |
896 | 908 |
897 } // namespace | 909 } // namespace |
OLD | NEW |