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