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