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