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