Chromium Code Reviews| 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 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 | 202 |
| 203 DomainStateMap::iterator i = enabled_hosts_.begin(); | 203 DomainStateMap::iterator i = enabled_hosts_.begin(); |
| 204 while (i != enabled_hosts_.end()) { | 204 while (i != enabled_hosts_.end()) { |
| 205 if (i->second.created >= time) { | 205 if (i->second.sts_observed >= time && i->second.pkp_observed >= time) { |
| 206 dirtied = true; | 206 dirtied = true; |
| 207 enabled_hosts_.erase(i++); | 207 enabled_hosts_.erase(i++); |
| 208 } else if (i->second.sts_observed >= time) { | |
| 209 dirtied = true; | |
| 210 i->second.upgrade_mode = DomainState::MODE_DEFAULT; | |
| 211 i++; | |
| 212 } else if (i->second.pkp_observed >= time) { | |
| 213 dirtied = true; | |
| 214 i->second.dynamic_spki_hashes.clear(); | |
| 215 i++; | |
| 208 } else { | 216 } else { |
| 209 i++; | 217 i++; |
| 210 } | 218 } |
|
wtc
2013/12/12 23:20:44
Since we do |i++| in all cases, this can be writte
palmer
2013/12/13 01:42:42
Actually, that exposed a bug: when we do enabled_h
wtc
2013/12/13 02:35:04
Ah, I remember this issue, and your original code
| |
| 211 } | 219 } |
| 212 | 220 |
| 213 if (dirtied) | 221 if (dirtied) |
| 214 DirtyNotify(); | 222 DirtyNotify(); |
| 215 } | 223 } |
| 216 | 224 |
| 217 TransportSecurityState::~TransportSecurityState() { | 225 TransportSecurityState::~TransportSecurityState() { |
| 218 DCHECK(CalledOnValidThread()); | 226 DCHECK(CalledOnValidThread()); |
| 219 } | 227 } |
| 220 | 228 |
| (...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 607 base::Time now = base::Time::Now(); | 615 base::Time now = base::Time::Now(); |
| 608 base::TimeDelta max_age; | 616 base::TimeDelta max_age; |
| 609 TransportSecurityState::DomainState domain_state; | 617 TransportSecurityState::DomainState domain_state; |
| 610 GetDynamicDomainState(host, &domain_state); | 618 GetDynamicDomainState(host, &domain_state); |
| 611 if (ParseHSTSHeader(value, &max_age, &domain_state.sts_include_subdomains)) { | 619 if (ParseHSTSHeader(value, &max_age, &domain_state.sts_include_subdomains)) { |
| 612 // Handle max-age == 0 | 620 // Handle max-age == 0 |
| 613 if (max_age.InSeconds() == 0) | 621 if (max_age.InSeconds() == 0) |
| 614 domain_state.upgrade_mode = DomainState::MODE_DEFAULT; | 622 domain_state.upgrade_mode = DomainState::MODE_DEFAULT; |
| 615 else | 623 else |
| 616 domain_state.upgrade_mode = DomainState::MODE_FORCE_HTTPS; | 624 domain_state.upgrade_mode = DomainState::MODE_FORCE_HTTPS; |
| 617 domain_state.created = now; | 625 domain_state.sts_observed = now; |
| 618 domain_state.upgrade_expiry = now + max_age; | 626 domain_state.upgrade_expiry = now + max_age; |
| 619 EnableHost(host, domain_state); | 627 EnableHost(host, domain_state); |
| 620 return true; | 628 return true; |
| 621 } | 629 } |
| 622 return false; | 630 return false; |
| 623 } | 631 } |
| 624 | 632 |
| 625 bool TransportSecurityState::AddHPKPHeader(const std::string& host, | 633 bool TransportSecurityState::AddHPKPHeader(const std::string& host, |
| 626 const std::string& value, | 634 const std::string& value, |
| 627 const SSLInfo& ssl_info) { | 635 const SSLInfo& ssl_info) { |
| 628 DCHECK(CalledOnValidThread()); | 636 DCHECK(CalledOnValidThread()); |
| 629 | 637 |
| 630 base::Time now = base::Time::Now(); | 638 base::Time now = base::Time::Now(); |
| 631 base::TimeDelta max_age; | 639 base::TimeDelta max_age; |
| 632 TransportSecurityState::DomainState domain_state; | 640 TransportSecurityState::DomainState domain_state; |
| 633 GetDynamicDomainState(host, &domain_state); | 641 GetDynamicDomainState(host, &domain_state); |
| 634 if (ParseHPKPHeader(value, ssl_info.public_key_hashes, | 642 if (ParseHPKPHeader(value, ssl_info.public_key_hashes, |
| 635 &max_age, &domain_state.pkp_include_subdomains, | 643 &max_age, &domain_state.pkp_include_subdomains, |
| 636 &domain_state.dynamic_spki_hashes)) { | 644 &domain_state.dynamic_spki_hashes)) { |
| 637 // TODO(palmer): http://crbug.com/243865 handle max-age == 0. | 645 // TODO(palmer): http://crbug.com/243865 handle max-age == 0. |
| 638 domain_state.created = now; | 646 domain_state.pkp_observed = now; |
| 639 domain_state.dynamic_spki_hashes_expiry = now + max_age; | 647 domain_state.dynamic_spki_hashes_expiry = now + max_age; |
| 640 EnableHost(host, domain_state); | 648 EnableHost(host, domain_state); |
| 641 return true; | 649 return true; |
| 642 } | 650 } |
| 643 return false; | 651 return false; |
| 644 } | 652 } |
| 645 | 653 |
| 646 bool TransportSecurityState::AddHSTS(const std::string& host, | 654 bool TransportSecurityState::AddHSTS(const std::string& host, |
| 647 const base::Time& expiry, | 655 const base::Time& expiry, |
| 648 bool include_subdomains) { | 656 bool include_subdomains) { |
| 649 DCHECK(CalledOnValidThread()); | 657 DCHECK(CalledOnValidThread()); |
| 650 | 658 |
| 651 // Copy-and-modify the existing DomainState for this host (if any). | 659 // Copy-and-modify the existing DomainState for this host (if any). |
| 652 TransportSecurityState::DomainState domain_state; | 660 TransportSecurityState::DomainState domain_state; |
| 653 const std::string canonicalized_host = CanonicalizeHost(host); | 661 const std::string canonicalized_host = CanonicalizeHost(host); |
| 654 const std::string hashed_host = HashHost(canonicalized_host); | 662 const std::string hashed_host = HashHost(canonicalized_host); |
| 655 DomainStateMap::const_iterator i = enabled_hosts_.find( | 663 DomainStateMap::const_iterator i = enabled_hosts_.find( |
| 656 hashed_host); | 664 hashed_host); |
| 657 if (i != enabled_hosts_.end()) | 665 if (i != enabled_hosts_.end()) |
| 658 domain_state = i->second; | 666 domain_state = i->second; |
| 659 | 667 |
| 660 domain_state.created = base::Time::Now(); | 668 domain_state.sts_observed = base::Time::Now(); |
| 661 domain_state.sts_include_subdomains = include_subdomains; | 669 domain_state.sts_include_subdomains = include_subdomains; |
| 662 domain_state.upgrade_expiry = expiry; | 670 domain_state.upgrade_expiry = expiry; |
| 663 domain_state.upgrade_mode = DomainState::MODE_FORCE_HTTPS; | 671 domain_state.upgrade_mode = DomainState::MODE_FORCE_HTTPS; |
| 664 EnableHost(host, domain_state); | 672 EnableHost(host, domain_state); |
| 665 return true; | 673 return true; |
| 666 } | 674 } |
| 667 | 675 |
| 668 bool TransportSecurityState::AddHPKP(const std::string& host, | 676 bool TransportSecurityState::AddHPKP(const std::string& host, |
| 669 const base::Time& expiry, | 677 const base::Time& expiry, |
| 670 bool include_subdomains, | 678 bool include_subdomains, |
| 671 const HashValueVector& hashes) { | 679 const HashValueVector& hashes) { |
| 672 DCHECK(CalledOnValidThread()); | 680 DCHECK(CalledOnValidThread()); |
| 673 | 681 |
| 674 // Copy-and-modify the existing DomainState for this host (if any). | 682 // Copy-and-modify the existing DomainState for this host (if any). |
| 675 TransportSecurityState::DomainState domain_state; | 683 TransportSecurityState::DomainState domain_state; |
| 676 const std::string canonicalized_host = CanonicalizeHost(host); | 684 const std::string canonicalized_host = CanonicalizeHost(host); |
| 677 const std::string hashed_host = HashHost(canonicalized_host); | 685 const std::string hashed_host = HashHost(canonicalized_host); |
| 678 DomainStateMap::const_iterator i = enabled_hosts_.find( | 686 DomainStateMap::const_iterator i = enabled_hosts_.find( |
| 679 hashed_host); | 687 hashed_host); |
| 680 if (i != enabled_hosts_.end()) | 688 if (i != enabled_hosts_.end()) |
| 681 domain_state = i->second; | 689 domain_state = i->second; |
| 682 | 690 |
| 683 domain_state.created = base::Time::Now(); | 691 domain_state.pkp_observed = base::Time::Now(); |
| 684 domain_state.pkp_include_subdomains = include_subdomains; | 692 domain_state.pkp_include_subdomains = include_subdomains; |
| 685 domain_state.dynamic_spki_hashes_expiry = expiry; | 693 domain_state.dynamic_spki_hashes_expiry = expiry; |
| 686 domain_state.dynamic_spki_hashes = hashes; | 694 domain_state.dynamic_spki_hashes = hashes; |
| 687 EnableHost(host, domain_state); | 695 EnableHost(host, domain_state); |
| 688 return true; | 696 return true; |
| 689 } | 697 } |
| 690 | 698 |
| 691 // static | 699 // static |
| 692 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host, | 700 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host, |
| 693 bool sni_enabled) { | 701 bool sni_enabled) { |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 818 | 826 |
| 819 | 827 |
| 820 void TransportSecurityState::AddOrUpdateEnabledHosts( | 828 void TransportSecurityState::AddOrUpdateEnabledHosts( |
| 821 const std::string& hashed_host, const DomainState& state) { | 829 const std::string& hashed_host, const DomainState& state) { |
| 822 DCHECK(CalledOnValidThread()); | 830 DCHECK(CalledOnValidThread()); |
| 823 enabled_hosts_[hashed_host] = state; | 831 enabled_hosts_[hashed_host] = state; |
| 824 } | 832 } |
| 825 | 833 |
| 826 TransportSecurityState::DomainState::DomainState() | 834 TransportSecurityState::DomainState::DomainState() |
| 827 : upgrade_mode(MODE_DEFAULT), | 835 : upgrade_mode(MODE_DEFAULT), |
| 828 created(base::Time::Now()), | |
| 829 sts_include_subdomains(false), | 836 sts_include_subdomains(false), |
| 830 pkp_include_subdomains(false) { | 837 pkp_include_subdomains(false) { |
| 838 base::Time now(base::Time::Now()); | |
| 839 sts_observed = now; | |
| 840 pkp_observed = now; | |
| 831 } | 841 } |
| 832 | 842 |
| 833 TransportSecurityState::DomainState::~DomainState() { | 843 TransportSecurityState::DomainState::~DomainState() { |
| 834 } | 844 } |
| 835 | 845 |
| 836 bool TransportSecurityState::DomainState::CheckPublicKeyPins( | 846 bool TransportSecurityState::DomainState::CheckPublicKeyPins( |
| 837 const HashValueVector& hashes) const { | 847 const HashValueVector& hashes) const { |
| 838 // Validate that hashes is not empty. By the time this code is called (in | 848 // Validate that hashes is not empty. By the time this code is called (in |
| 839 // production), that should never happen, but it's good to be defensive. | 849 // production), that should never happen, but it's good to be defensive. |
| 840 // And, hashes *can* be empty in some test scenarios. | 850 // And, hashes *can* be empty in some test scenarios. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 876 return true; | 886 return true; |
| 877 } | 887 } |
| 878 | 888 |
| 879 bool TransportSecurityState::DomainState::HasPublicKeyPins() const { | 889 bool TransportSecurityState::DomainState::HasPublicKeyPins() const { |
| 880 return static_spki_hashes.size() > 0 || | 890 return static_spki_hashes.size() > 0 || |
| 881 bad_static_spki_hashes.size() > 0 || | 891 bad_static_spki_hashes.size() > 0 || |
| 882 dynamic_spki_hashes.size() > 0; | 892 dynamic_spki_hashes.size() > 0; |
| 883 } | 893 } |
| 884 | 894 |
| 885 } // namespace | 895 } // namespace |
| OLD | NEW |