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) const { |
| 110 // TODO(palmer): Implement this. |
| 111 return true; |
| 112 } |
| 113 |
| 114 bool TransportSecurityState::ShouldUpgradeToSSL(const std::string& host, |
| 115 bool sni_enabled) const { |
| 116 // TODO(palmer): Implement this. |
| 117 return true; |
| 118 } |
| 119 |
| 120 bool TransportSecurityState::CheckPublicKeyPins( |
| 121 const std::string& host, |
| 122 bool sni_enabled, |
| 123 const HashValueVector& hashes) const { |
| 124 // TODO(palmer): Implement this. |
| 125 return true; |
| 126 } |
| 127 |
| 128 bool TransportSecurityState::HasPublicKeyPins(const std::string& host, |
| 129 bool sni_enabled) const { |
| 130 // TODO(palmer): Implement this. |
| 131 return true; |
| 132 } |
| 133 |
98 void TransportSecurityState::SetDelegate( | 134 void TransportSecurityState::SetDelegate( |
99 TransportSecurityState::Delegate* delegate) { | 135 TransportSecurityState::Delegate* delegate) { |
100 DCHECK(CalledOnValidThread()); | 136 DCHECK(CalledOnValidThread()); |
101 delegate_ = delegate; | 137 delegate_ = delegate; |
102 } | 138 } |
103 | 139 |
104 void TransportSecurityState::EnableHost(const std::string& host, | 140 void TransportSecurityState::EnableHost(const std::string& host, |
105 const DomainState& state) { | 141 const DomainState& state) { |
106 DCHECK(CalledOnValidThread()); | 142 DCHECK(CalledOnValidThread()); |
107 | 143 |
(...skipping 20 matching lines...) Expand all Loading... |
128 DomainStateMap::iterator i = enabled_hosts_.find( | 164 DomainStateMap::iterator i = enabled_hosts_.find( |
129 HashHost(canonicalized_host)); | 165 HashHost(canonicalized_host)); |
130 if (i != enabled_hosts_.end()) { | 166 if (i != enabled_hosts_.end()) { |
131 enabled_hosts_.erase(i); | 167 enabled_hosts_.erase(i); |
132 DirtyNotify(); | 168 DirtyNotify(); |
133 return true; | 169 return true; |
134 } | 170 } |
135 return false; | 171 return false; |
136 } | 172 } |
137 | 173 |
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() { | 174 void TransportSecurityState::ClearDynamicData() { |
194 DCHECK(CalledOnValidThread()); | 175 DCHECK(CalledOnValidThread()); |
195 enabled_hosts_.clear(); | 176 enabled_hosts_.clear(); |
196 } | 177 } |
197 | 178 |
198 void TransportSecurityState::DeleteAllDynamicDataSince(const base::Time& time) { | 179 void TransportSecurityState::DeleteAllDynamicDataSince(const base::Time& time) { |
199 DCHECK(CalledOnValidThread()); | 180 DCHECK(CalledOnValidThread()); |
200 | 181 |
201 bool dirtied = false; | 182 bool dirtied = false; |
202 DomainStateMap::iterator i = enabled_hosts_.begin(); | 183 DomainStateMap::iterator i = enabled_hosts_.begin(); |
203 while (i != enabled_hosts_.end()) { | 184 while (i != enabled_hosts_.end()) { |
204 if (i->second.sts_observed >= time && i->second.pkp_observed >= time) { | 185 if (i->second.sts.last_observed >= time && |
| 186 i->second.pkp.last_observed >= time) { |
205 dirtied = true; | 187 dirtied = true; |
206 enabled_hosts_.erase(i++); | 188 enabled_hosts_.erase(i++); |
207 continue; | 189 continue; |
208 } | 190 } |
209 | 191 |
210 if (i->second.sts_observed >= time) { | 192 if (i->second.sts.last_observed >= time) { |
211 dirtied = true; | 193 dirtied = true; |
212 i->second.upgrade_mode = DomainState::MODE_DEFAULT; | 194 i->second.sts.upgrade_mode = DomainState::MODE_DEFAULT; |
213 } else if (i->second.pkp_observed >= time) { | 195 } else if (i->second.pkp.last_observed >= time) { |
214 dirtied = true; | 196 dirtied = true; |
215 i->second.dynamic_spki_hashes.clear(); | 197 i->second.pkp.spki_hashes.clear(); |
216 } | 198 } |
217 ++i; | 199 ++i; |
218 } | 200 } |
219 | 201 |
220 if (dirtied) | 202 if (dirtied) |
221 DirtyNotify(); | 203 DirtyNotify(); |
222 } | 204 } |
223 | 205 |
224 TransportSecurityState::~TransportSecurityState() { | 206 TransportSecurityState::~TransportSecurityState() { |
225 DCHECK(CalledOnValidThread()); | 207 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, | 529 static bool HasPreload(const struct HSTSPreload* entries, size_t num_entries, |
548 const std::string& canonicalized_host, size_t i, | 530 const std::string& canonicalized_host, size_t i, |
549 TransportSecurityState::DomainState* out, bool* ret) { | 531 TransportSecurityState::DomainState* out, bool* ret) { |
550 for (size_t j = 0; j < num_entries; j++) { | 532 for (size_t j = 0; j < num_entries; j++) { |
551 if (entries[j].length == canonicalized_host.size() - i && | 533 if (entries[j].length == canonicalized_host.size() - i && |
552 memcmp(entries[j].dns_name, &canonicalized_host[i], | 534 memcmp(entries[j].dns_name, &canonicalized_host[i], |
553 entries[j].length) == 0) { | 535 entries[j].length) == 0) { |
554 if (!entries[j].include_subdomains && i != 0) { | 536 if (!entries[j].include_subdomains && i != 0) { |
555 *ret = false; | 537 *ret = false; |
556 } else { | 538 } else { |
557 out->sts_include_subdomains = entries[j].include_subdomains; | 539 out->sts.include_subdomains = entries[j].include_subdomains; |
558 out->pkp_include_subdomains = entries[j].include_subdomains; | 540 out->sts.last_observed = base::GetBuildTime(); |
| 541 out->pkp.include_subdomains = entries[j].include_subdomains; |
| 542 out->pkp.last_observed = base::GetBuildTime(); |
559 *ret = true; | 543 *ret = true; |
| 544 out->sts.upgrade_mode = |
| 545 TransportSecurityState::DomainState::MODE_FORCE_HTTPS; |
560 if (!entries[j].https_required) | 546 if (!entries[j].https_required) |
561 out->upgrade_mode = TransportSecurityState::DomainState::MODE_DEFAULT; | 547 out->sts.upgrade_mode = |
| 548 TransportSecurityState::DomainState::MODE_DEFAULT; |
562 if (entries[j].pins.required_hashes) { | 549 if (entries[j].pins.required_hashes) { |
563 const char* const* sha1_hash = entries[j].pins.required_hashes; | 550 const char* const* sha1_hash = entries[j].pins.required_hashes; |
564 while (*sha1_hash) { | 551 while (*sha1_hash) { |
565 AddHash(*sha1_hash, &out->static_spki_hashes); | 552 AddHash(*sha1_hash, &out->pkp.spki_hashes); |
566 sha1_hash++; | 553 sha1_hash++; |
567 } | 554 } |
568 } | 555 } |
569 if (entries[j].pins.excluded_hashes) { | 556 if (entries[j].pins.excluded_hashes) { |
570 const char* const* sha1_hash = entries[j].pins.excluded_hashes; | 557 const char* const* sha1_hash = entries[j].pins.excluded_hashes; |
571 while (*sha1_hash) { | 558 while (*sha1_hash) { |
572 AddHash(*sha1_hash, &out->bad_static_spki_hashes); | 559 AddHash(*sha1_hash, &out->pkp.bad_spki_hashes); |
573 sha1_hash++; | 560 sha1_hash++; |
574 } | 561 } |
575 } | 562 } |
576 } | 563 } |
577 return true; | 564 return true; |
578 } | 565 } |
579 } | 566 } |
580 return false; | 567 return false; |
581 } | 568 } |
582 | 569 |
(...skipping 27 matching lines...) Expand all Loading... |
610 } | 597 } |
611 | 598 |
612 bool TransportSecurityState::AddHSTSHeader(const std::string& host, | 599 bool TransportSecurityState::AddHSTSHeader(const std::string& host, |
613 const std::string& value) { | 600 const std::string& value) { |
614 DCHECK(CalledOnValidThread()); | 601 DCHECK(CalledOnValidThread()); |
615 | 602 |
616 base::Time now = base::Time::Now(); | 603 base::Time now = base::Time::Now(); |
617 base::TimeDelta max_age; | 604 base::TimeDelta max_age; |
618 TransportSecurityState::DomainState domain_state; | 605 TransportSecurityState::DomainState domain_state; |
619 GetDynamicDomainState(host, &domain_state); | 606 GetDynamicDomainState(host, &domain_state); |
620 if (ParseHSTSHeader(value, &max_age, &domain_state.sts_include_subdomains)) { | 607 if (ParseHSTSHeader(value, &max_age, |
| 608 &domain_state.sts.include_subdomains)) { |
621 // Handle max-age == 0 | 609 // Handle max-age == 0 |
622 if (max_age.InSeconds() == 0) | 610 if (max_age.InSeconds() == 0) |
623 domain_state.upgrade_mode = DomainState::MODE_DEFAULT; | 611 domain_state.sts.upgrade_mode = DomainState::MODE_DEFAULT; |
624 else | 612 else |
625 domain_state.upgrade_mode = DomainState::MODE_FORCE_HTTPS; | 613 domain_state.sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS; |
626 domain_state.sts_observed = now; | 614 domain_state.sts.last_observed = now; |
627 domain_state.upgrade_expiry = now + max_age; | 615 domain_state.sts.expiry = now + max_age; |
628 EnableHost(host, domain_state); | 616 EnableHost(host, domain_state); |
629 return true; | 617 return true; |
630 } | 618 } |
631 return false; | 619 return false; |
632 } | 620 } |
633 | 621 |
634 bool TransportSecurityState::AddHPKPHeader(const std::string& host, | 622 bool TransportSecurityState::AddHPKPHeader(const std::string& host, |
635 const std::string& value, | 623 const std::string& value, |
636 const SSLInfo& ssl_info) { | 624 const SSLInfo& ssl_info) { |
637 DCHECK(CalledOnValidThread()); | 625 DCHECK(CalledOnValidThread()); |
638 | 626 |
639 base::Time now = base::Time::Now(); | 627 base::Time now = base::Time::Now(); |
640 base::TimeDelta max_age; | 628 base::TimeDelta max_age; |
641 TransportSecurityState::DomainState domain_state; | 629 TransportSecurityState::DomainState domain_state; |
642 GetDynamicDomainState(host, &domain_state); | 630 GetDynamicDomainState(host, &domain_state); |
643 if (ParseHPKPHeader(value, ssl_info.public_key_hashes, | 631 if (ParseHPKPHeader(value, ssl_info.public_key_hashes, |
644 &max_age, &domain_state.pkp_include_subdomains, | 632 &max_age, &domain_state.pkp.include_subdomains, |
645 &domain_state.dynamic_spki_hashes)) { | 633 &domain_state.pkp.spki_hashes)) { |
646 // TODO(palmer): http://crbug.com/243865 handle max-age == 0. | 634 // TODO(palmer): http://crbug.com/243865 handle max-age == 0. |
647 domain_state.pkp_observed = now; | 635 domain_state.pkp.last_observed = now; |
648 domain_state.dynamic_spki_hashes_expiry = now + max_age; | 636 domain_state.pkp.expiry = now + max_age; |
649 EnableHost(host, domain_state); | 637 EnableHost(host, domain_state); |
650 return true; | 638 return true; |
651 } | 639 } |
652 return false; | 640 return false; |
653 } | 641 } |
654 | 642 |
655 bool TransportSecurityState::AddHSTS(const std::string& host, | 643 bool TransportSecurityState::AddHSTS(const std::string& host, |
656 const base::Time& expiry, | 644 const base::Time& expiry, |
657 bool include_subdomains) { | 645 bool include_subdomains) { |
658 DCHECK(CalledOnValidThread()); | 646 DCHECK(CalledOnValidThread()); |
659 | 647 |
660 // Copy-and-modify the existing DomainState for this host (if any). | 648 // Copy-and-modify the existing DomainState for this host (if any). |
661 TransportSecurityState::DomainState domain_state; | 649 TransportSecurityState::DomainState domain_state; |
662 const std::string canonicalized_host = CanonicalizeHost(host); | 650 const std::string canonicalized_host = CanonicalizeHost(host); |
663 const std::string hashed_host = HashHost(canonicalized_host); | 651 const std::string hashed_host = HashHost(canonicalized_host); |
664 DomainStateMap::const_iterator i = enabled_hosts_.find( | 652 DomainStateMap::const_iterator i = enabled_hosts_.find( |
665 hashed_host); | 653 hashed_host); |
666 if (i != enabled_hosts_.end()) | 654 if (i != enabled_hosts_.end()) |
667 domain_state = i->second; | 655 domain_state = i->second; |
668 | 656 |
669 domain_state.sts_observed = base::Time::Now(); | 657 domain_state.sts.last_observed = base::Time::Now(); |
670 domain_state.sts_include_subdomains = include_subdomains; | 658 domain_state.sts.include_subdomains = include_subdomains; |
671 domain_state.upgrade_expiry = expiry; | 659 domain_state.sts.expiry = expiry; |
672 domain_state.upgrade_mode = DomainState::MODE_FORCE_HTTPS; | 660 domain_state.sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS; |
673 EnableHost(host, domain_state); | 661 EnableHost(host, domain_state); |
674 return true; | 662 return true; |
675 } | 663 } |
676 | 664 |
677 bool TransportSecurityState::AddHPKP(const std::string& host, | 665 bool TransportSecurityState::AddHPKP(const std::string& host, |
678 const base::Time& expiry, | 666 const base::Time& expiry, |
679 bool include_subdomains, | 667 bool include_subdomains, |
680 const HashValueVector& hashes) { | 668 const HashValueVector& hashes) { |
681 DCHECK(CalledOnValidThread()); | 669 DCHECK(CalledOnValidThread()); |
682 | 670 |
683 // Copy-and-modify the existing DomainState for this host (if any). | 671 // Copy-and-modify the existing DomainState for this host (if any). |
684 TransportSecurityState::DomainState domain_state; | 672 TransportSecurityState::DomainState domain_state; |
685 const std::string canonicalized_host = CanonicalizeHost(host); | 673 const std::string canonicalized_host = CanonicalizeHost(host); |
686 const std::string hashed_host = HashHost(canonicalized_host); | 674 const std::string hashed_host = HashHost(canonicalized_host); |
687 DomainStateMap::const_iterator i = enabled_hosts_.find( | 675 DomainStateMap::const_iterator i = enabled_hosts_.find( |
688 hashed_host); | 676 hashed_host); |
689 if (i != enabled_hosts_.end()) | 677 if (i != enabled_hosts_.end()) |
690 domain_state = i->second; | 678 domain_state = i->second; |
691 | 679 |
692 domain_state.pkp_observed = base::Time::Now(); | 680 domain_state.pkp.last_observed = base::Time::Now(); |
693 domain_state.pkp_include_subdomains = include_subdomains; | 681 domain_state.pkp.include_subdomains = include_subdomains; |
694 domain_state.dynamic_spki_hashes_expiry = expiry; | 682 domain_state.pkp.expiry = expiry; |
695 domain_state.dynamic_spki_hashes = hashes; | 683 domain_state.pkp.spki_hashes = hashes; |
696 EnableHost(host, domain_state); | 684 EnableHost(host, domain_state); |
697 return true; | 685 return true; |
698 } | 686 } |
699 | 687 |
700 // static | 688 // static |
701 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host, | 689 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host, |
702 bool sni_enabled) { | 690 bool sni_enabled) { |
703 std::string canonicalized_host = CanonicalizeHost(host); | 691 std::string canonicalized_host = CanonicalizeHost(host); |
704 const struct HSTSPreload* entry = | 692 const struct HSTSPreload* entry = |
705 GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS); | 693 GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
758 } | 746 } |
759 | 747 |
760 // static | 748 // static |
761 bool TransportSecurityState::IsBuildTimely() { | 749 bool TransportSecurityState::IsBuildTimely() { |
762 const base::Time build_time = base::GetBuildTime(); | 750 const base::Time build_time = base::GetBuildTime(); |
763 // We consider built-in information to be timely for 10 weeks. | 751 // We consider built-in information to be timely for 10 weeks. |
764 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; | 752 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; |
765 } | 753 } |
766 | 754 |
767 bool TransportSecurityState::GetStaticDomainState( | 755 bool TransportSecurityState::GetStaticDomainState( |
768 const std::string& canonicalized_host, | 756 const std::string& host, |
769 bool sni_enabled, | 757 bool sni_enabled, |
770 DomainState* out) { | 758 DomainState* out) { |
771 DCHECK(CalledOnValidThread()); | 759 DCHECK(CalledOnValidThread()); |
772 | 760 |
773 out->upgrade_mode = DomainState::MODE_FORCE_HTTPS; | 761 const std::string canonicalized_host = CanonicalizeHost(host); |
774 out->sts_include_subdomains = false; | 762 |
775 out->pkp_include_subdomains = false; | 763 out->sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS; |
| 764 out->sts.include_subdomains = false; |
| 765 out->pkp.include_subdomains = false; |
776 | 766 |
777 const bool is_build_timely = IsBuildTimely(); | 767 const bool is_build_timely = IsBuildTimely(); |
778 | 768 |
779 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) { | 769 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) { |
780 std::string host_sub_chunk(&canonicalized_host[i], | 770 std::string host_sub_chunk(&canonicalized_host[i], |
781 canonicalized_host.size() - i); | 771 canonicalized_host.size() - i); |
782 out->domain = DNSDomainToString(host_sub_chunk); | 772 out->domain = DNSDomainToString(host_sub_chunk); |
783 bool ret; | 773 bool ret; |
784 if (is_build_timely && | 774 if (is_build_timely && |
785 HasPreload(kPreloadedSTS, kNumPreloadedSTS, canonicalized_host, i, out, | 775 HasPreload(kPreloadedSTS, kNumPreloadedSTS, canonicalized_host, i, out, |
(...skipping 23 matching lines...) Expand all Loading... |
809 base::Time current_time(base::Time::Now()); | 799 base::Time current_time(base::Time::Now()); |
810 | 800 |
811 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) { | 801 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) { |
812 std::string host_sub_chunk(&canonicalized_host[i], | 802 std::string host_sub_chunk(&canonicalized_host[i], |
813 canonicalized_host.size() - i); | 803 canonicalized_host.size() - i); |
814 DomainStateMap::iterator j = | 804 DomainStateMap::iterator j = |
815 enabled_hosts_.find(HashHost(host_sub_chunk)); | 805 enabled_hosts_.find(HashHost(host_sub_chunk)); |
816 if (j == enabled_hosts_.end()) | 806 if (j == enabled_hosts_.end()) |
817 continue; | 807 continue; |
818 | 808 |
819 if (current_time > j->second.upgrade_expiry && | 809 if (current_time > j->second.sts.expiry && |
820 current_time > j->second.dynamic_spki_hashes_expiry) { | 810 current_time > j->second.pkp.expiry) { |
821 enabled_hosts_.erase(j); | 811 enabled_hosts_.erase(j); |
822 DirtyNotify(); | 812 DirtyNotify(); |
823 continue; | 813 continue; |
824 } | 814 } |
825 | 815 |
826 state = j->second; | 816 state = j->second; |
827 state.domain = DNSDomainToString(host_sub_chunk); | 817 state.domain = DNSDomainToString(host_sub_chunk); |
828 | 818 |
829 // Succeed if we matched the domain exactly or if subdomain matches are | 819 // Succeed if we matched the domain exactly or if subdomain matches are |
830 // allowed. | 820 // allowed. |
831 if (i == 0 || j->second.sts_include_subdomains || | 821 if (i == 0 || j->second.sts.include_subdomains || |
832 j->second.pkp_include_subdomains) { | 822 j->second.pkp.include_subdomains) { |
833 *result = state; | 823 *result = state; |
834 return true; | 824 return true; |
835 } | 825 } |
836 | 826 |
837 return false; | 827 return false; |
838 } | 828 } |
839 | 829 |
840 return false; | 830 return false; |
841 } | 831 } |
842 | 832 |
843 | |
844 void TransportSecurityState::AddOrUpdateEnabledHosts( | 833 void TransportSecurityState::AddOrUpdateEnabledHosts( |
845 const std::string& hashed_host, const DomainState& state) { | 834 const std::string& hashed_host, const DomainState& state) { |
846 DCHECK(CalledOnValidThread()); | 835 DCHECK(CalledOnValidThread()); |
847 enabled_hosts_[hashed_host] = state; | 836 enabled_hosts_[hashed_host] = state; |
848 } | 837 } |
849 | 838 |
850 TransportSecurityState::DomainState::DomainState() | 839 TransportSecurityState::DomainState::DomainState() { |
851 : upgrade_mode(MODE_DEFAULT), | 840 sts.upgrade_mode = MODE_DEFAULT; |
852 sts_include_subdomains(false), | 841 sts.include_subdomains = false; |
853 pkp_include_subdomains(false) { | 842 pkp.include_subdomains = false; |
854 base::Time now(base::Time::Now()); | |
855 sts_observed = now; | |
856 pkp_observed = now; | |
857 } | 843 } |
858 | 844 |
859 TransportSecurityState::DomainState::~DomainState() { | 845 TransportSecurityState::DomainState::~DomainState() { |
860 } | 846 } |
861 | 847 |
862 bool TransportSecurityState::DomainState::CheckPublicKeyPins( | 848 bool TransportSecurityState::DomainState::CheckPublicKeyPins( |
863 const HashValueVector& hashes) const { | 849 const HashValueVector& hashes) const { |
864 // Validate that hashes is not empty. By the time this code is called (in | 850 // Validate that hashes is not empty. By the time this code is called (in |
865 // production), that should never happen, but it's good to be defensive. | 851 // production), that should never happen, but it's good to be defensive. |
866 // And, hashes *can* be empty in some test scenarios. | 852 // And, hashes *can* be empty in some test scenarios. |
867 if (hashes.empty()) { | 853 if (hashes.empty()) { |
868 LOG(ERROR) << "Rejecting empty public key chain for public-key-pinned " | 854 LOG(ERROR) << "Rejecting empty public key chain for public-key-pinned " |
869 "domain " << domain; | 855 "domain " << domain; |
870 return false; | 856 return false; |
871 } | 857 } |
872 | 858 |
873 if (HashesIntersect(bad_static_spki_hashes, hashes)) { | 859 if (HashesIntersect(pkp.bad_spki_hashes, hashes)) { |
874 LOG(ERROR) << "Rejecting public key chain for domain " << domain | 860 LOG(ERROR) << "Rejecting public key chain for domain " << domain |
875 << ". Validated chain: " << HashesToBase64String(hashes) | 861 << ". Validated chain: " << HashesToBase64String(hashes) |
876 << ", matches one or more bad hashes: " | 862 << ", matches one or more bad hashes: " |
877 << HashesToBase64String(bad_static_spki_hashes); | 863 << HashesToBase64String(pkp.bad_spki_hashes); |
878 return false; | 864 return false; |
879 } | 865 } |
880 | 866 |
881 // If there are no pins, then any valid chain is acceptable. | 867 // If there are no pins, then any valid chain is acceptable. |
882 if (dynamic_spki_hashes.empty() && static_spki_hashes.empty()) | 868 if (pkp.spki_hashes.empty()) |
883 return true; | 869 return true; |
884 | 870 |
885 if (HashesIntersect(dynamic_spki_hashes, hashes) || | 871 if (HashesIntersect(pkp.spki_hashes, hashes)) { |
886 HashesIntersect(static_spki_hashes, hashes)) { | |
887 return true; | 872 return true; |
888 } | 873 } |
889 | 874 |
890 LOG(ERROR) << "Rejecting public key chain for domain " << domain | 875 LOG(ERROR) << "Rejecting public key chain for domain " << domain |
891 << ". Validated chain: " << HashesToBase64String(hashes) | 876 << ". Validated chain: " << HashesToBase64String(hashes) |
892 << ", expected: " << HashesToBase64String(dynamic_spki_hashes) | 877 << ", expected: " << HashesToBase64String(pkp.spki_hashes); |
893 << " or: " << HashesToBase64String(static_spki_hashes); | |
894 return false; | 878 return false; |
895 } | 879 } |
896 | 880 |
897 bool TransportSecurityState::DomainState::ShouldUpgradeToSSL() const { | 881 bool TransportSecurityState::DomainState::ShouldUpgradeToSSL() const { |
898 return upgrade_mode == MODE_FORCE_HTTPS; | 882 return sts.upgrade_mode == MODE_FORCE_HTTPS; |
899 } | 883 } |
900 | 884 |
901 bool TransportSecurityState::DomainState::ShouldSSLErrorsBeFatal() const { | 885 bool TransportSecurityState::DomainState::ShouldSSLErrorsBeFatal() const { |
902 return true; | 886 return true; |
903 } | 887 } |
904 | 888 |
905 bool TransportSecurityState::DomainState::HasPublicKeyPins() const { | 889 bool TransportSecurityState::DomainState::HasPublicKeyPins() const { |
906 return static_spki_hashes.size() > 0 || | 890 return pkp.spki_hashes.size() > 0 || |
907 bad_static_spki_hashes.size() > 0 || | 891 pkp.bad_spki_hashes.size() > 0; |
908 dynamic_spki_hashes.size() > 0; | |
909 } | 892 } |
910 | 893 |
911 } // namespace | 894 } // namespace |
OLD | NEW |