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 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 } // namespace | 84 } // namespace |
| 85 | 85 |
| 86 TransportSecurityState::TransportSecurityState() | 86 TransportSecurityState::TransportSecurityState() |
| 87 : delegate_(NULL) { | 87 : delegate_(NULL), |
| 88 enable_static_pinning_(true) { | |
| 89 // Static pinning is only enabled for official builds to make sure that | |
| 90 // others don't end up with pins that cannot be easily updated. | |
| 91 #if !defined(OFFICIAL_BUILD) || defined(OS_ANDROID) || defined(OS_IOS) | |
| 92 enable_static_pinning_ = false; | |
| 93 #endif | |
| 88 DCHECK(CalledOnValidThread()); | 94 DCHECK(CalledOnValidThread()); |
| 89 } | 95 } |
| 90 | 96 |
| 91 TransportSecurityState::Iterator::Iterator(const TransportSecurityState& state) | 97 TransportSecurityState::Iterator::Iterator(const TransportSecurityState& state) |
| 92 : iterator_(state.enabled_hosts_.begin()), | 98 : iterator_(state.enabled_hosts_.begin()), |
| 93 end_(state.enabled_hosts_.end()) { | 99 end_(state.enabled_hosts_.end()) { |
| 94 } | 100 } |
| 95 | 101 |
| 96 TransportSecurityState::Iterator::~Iterator() {} | 102 TransportSecurityState::Iterator::~Iterator() {} |
| 97 | 103 |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 111 | 117 |
| 112 DomainState static_state; | 118 DomainState static_state; |
| 113 if (GetStaticDomainState(host, sni_enabled, &static_state) && | 119 if (GetStaticDomainState(host, sni_enabled, &static_state) && |
| 114 static_state.ShouldUpgradeToSSL()) { | 120 static_state.ShouldUpgradeToSSL()) { |
| 115 return true; | 121 return true; |
| 116 } | 122 } |
| 117 | 123 |
| 118 return false; | 124 return false; |
| 119 } | 125 } |
| 120 | 126 |
| 121 bool TransportSecurityState::CheckPublicKeyPins(const std::string& host, | 127 bool TransportSecurityState::CheckPublicKeyPins( |
| 122 bool sni_enabled, | 128 const std::string& host, |
| 123 const HashValueVector& hashes, | 129 bool sni_available, |
| 124 std::string* failure_log) { | 130 bool is_issued_by_known_root, |
| 131 const HashValueVector& public_key_hashes, | |
| 132 std::string* pinning_failure_log) { | |
| 133 // Perform pin validation if, and only if, all these conditions obtain: | |
| 134 // | |
| 135 // * the server's certificate chain chains up to a known root (i.e. not a | |
| 136 // user-installed trust anchor); and | |
| 137 // * the build is recent (very old builds should fail open so that users | |
| 138 // have some chance to recover). | |
| 139 // | |
| 140 if (!is_issued_by_known_root || | |
| 141 !TransportSecurityState::IsBuildTimely() || | |
|
wtc
2014/08/07 22:51:44
Nit: omit "TransportSecurityState::"
Ryan Hamilton
2014/08/07 23:19:04
Done.
| |
| 142 !HasPublicKeyPins(host, sni_available)) { | |
| 143 return true; | |
| 144 } | |
| 145 | |
| 146 bool pins_are_valid = CheckPublicKeyPinsImpl(host, | |
| 147 sni_available, | |
| 148 public_key_hashes, | |
| 149 pinning_failure_log); | |
| 150 if (!pins_are_valid) { | |
| 151 LOG(ERROR) << *pinning_failure_log; | |
| 152 ReportUMAOnPinFailure(host); | |
| 153 } | |
| 154 | |
| 155 UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", pins_are_valid); | |
| 156 return pins_are_valid; | |
| 157 } | |
| 158 | |
| 159 bool TransportSecurityState::CheckPublicKeyPinsImpl( | |
|
Ryan Sleevi
2014/08/07 22:19:07
So, I know you did this for the diff, but move thi
Ryan Hamilton
2014/08/07 22:49:39
Will do. I'll leave it here until I get an LGTM so
| |
| 160 const std::string& host, | |
| 161 bool sni_enabled, | |
| 162 const HashValueVector& hashes, | |
| 163 std::string* failure_log) { | |
| 125 DomainState dynamic_state; | 164 DomainState dynamic_state; |
| 126 if (GetDynamicDomainState(host, &dynamic_state)) | 165 if (GetDynamicDomainState(host, &dynamic_state)) |
| 127 return dynamic_state.CheckPublicKeyPins(hashes, failure_log); | 166 return dynamic_state.CheckPublicKeyPins(hashes, failure_log); |
| 128 | 167 |
| 129 DomainState static_state; | 168 DomainState static_state; |
| 130 if (GetStaticDomainState(host, sni_enabled, &static_state) && | 169 if (GetStaticDomainState(host, sni_enabled, &static_state)) |
| 131 static_state.CheckPublicKeyPins(hashes, failure_log)) { | 170 return static_state.CheckPublicKeyPins(hashes, failure_log); |
| 132 return true; | |
| 133 } | |
| 134 | 171 |
| 172 // HasPublicKeyPins should have returned true in order for this method | |
| 173 // to have been called, so if we fall through to here, it's an error. | |
| 135 return false; | 174 return false; |
| 136 } | 175 } |
| 137 | 176 |
| 138 bool TransportSecurityState::HasPublicKeyPins(const std::string& host, | 177 bool TransportSecurityState::HasPublicKeyPins(const std::string& host, |
| 139 bool sni_enabled) { | 178 bool sni_enabled) { |
| 140 DomainState dynamic_state; | 179 DomainState dynamic_state; |
| 141 if (GetDynamicDomainState(host, &dynamic_state)) | 180 if (GetDynamicDomainState(host, &dynamic_state)) |
| 142 return dynamic_state.HasPublicKeyPins(); | 181 return dynamic_state.HasPublicKeyPins(); |
| 143 | 182 |
| 144 DomainState static_state; | 183 DomainState static_state; |
| (...skipping 579 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 724 if (sni_enabled) { | 763 if (sni_enabled) { |
| 725 entry = GetHSTSPreload(canonicalized_host, kPreloadedSNISTS, | 764 entry = GetHSTSPreload(canonicalized_host, kPreloadedSNISTS, |
| 726 kNumPreloadedSNISTS); | 765 kNumPreloadedSNISTS); |
| 727 if (entry && entry->pins.required_hashes == kGoogleAcceptableCerts) | 766 if (entry && entry->pins.required_hashes == kGoogleAcceptableCerts) |
| 728 return true; | 767 return true; |
| 729 } | 768 } |
| 730 | 769 |
| 731 return false; | 770 return false; |
| 732 } | 771 } |
| 733 | 772 |
| 734 // static | 773 void TransportSecurityState::ReportUMAOnPinFailure( |
| 735 void TransportSecurityState::ReportUMAOnPinFailure(const std::string& host) { | 774 const std::string& host) const{ |
| 736 std::string canonicalized_host = CanonicalizeHost(host); | 775 std::string canonicalized_host = CanonicalizeHost(host); |
| 737 | 776 |
| 738 const struct HSTSPreload* entry = | 777 const struct HSTSPreload* entry = |
| 739 GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS); | 778 GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS); |
| 740 | 779 |
| 741 if (!entry) { | 780 if (!entry) { |
| 742 entry = GetHSTSPreload(canonicalized_host, kPreloadedSNISTS, | 781 entry = GetHSTSPreload(canonicalized_host, kPreloadedSNISTS, |
| 743 kNumPreloadedSNISTS); | 782 kNumPreloadedSNISTS); |
| 744 } | 783 } |
| 745 | 784 |
| 746 if (!entry) { | 785 if (!entry) { |
| 747 // We don't care to report pin failures for dynamic pins. | 786 // We don't care to report pin failures for dynamic pins. |
| 748 return; | 787 return; |
| 749 } | 788 } |
| 750 | 789 |
| 751 DCHECK(entry); | 790 DCHECK(entry); |
| 752 DCHECK(entry->pins.required_hashes); | 791 DCHECK(entry->pins.required_hashes); |
| 753 DCHECK(entry->second_level_domain_name != DOMAIN_NOT_PINNED); | 792 DCHECK(entry->second_level_domain_name != DOMAIN_NOT_PINNED); |
| 754 | 793 |
| 755 UMA_HISTOGRAM_ENUMERATION("Net.PublicKeyPinFailureDomain", | 794 UMA_HISTOGRAM_ENUMERATION("Net.PublicKeyPinFailureDomain", |
| 756 entry->second_level_domain_name, DOMAIN_NUM_EVENTS); | 795 entry->second_level_domain_name, DOMAIN_NUM_EVENTS); |
| 757 } | 796 } |
| 758 | 797 |
| 759 // static | 798 bool TransportSecurityState::IsBuildTimely() const { |
| 760 bool TransportSecurityState::IsBuildTimely() { | |
| 761 const base::Time build_time = base::GetBuildTime(); | 799 const base::Time build_time = base::GetBuildTime(); |
| 762 // We consider built-in information to be timely for 10 weeks. | 800 // We consider built-in information to be timely for 10 weeks. |
| 763 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; | 801 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; |
| 764 } | 802 } |
| 765 | 803 |
| 766 bool TransportSecurityState::GetStaticDomainState(const std::string& host, | 804 bool TransportSecurityState::GetStaticDomainState(const std::string& host, |
| 767 bool sni_enabled, | 805 bool sni_enabled, |
| 768 DomainState* out) const { | 806 DomainState* out) const { |
| 769 DCHECK(CalledOnValidThread()); | 807 DCHECK(CalledOnValidThread()); |
| 770 | 808 |
| 809 if (!enable_static_pinning_) | |
| 810 return false; | |
| 811 | |
| 771 const std::string canonicalized_host = CanonicalizeHost(host); | 812 const std::string canonicalized_host = CanonicalizeHost(host); |
| 772 | 813 |
| 773 out->sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS; | 814 out->sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS; |
| 774 out->sts.include_subdomains = false; | 815 out->sts.include_subdomains = false; |
| 775 out->pkp.include_subdomains = false; | 816 out->pkp.include_subdomains = false; |
| 776 | 817 |
| 777 const bool is_build_timely = IsBuildTimely(); | 818 const bool is_build_timely = IsBuildTimely(); |
| 778 | 819 |
| 779 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) { | 820 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) { |
| 780 std::string host_sub_chunk(&canonicalized_host[i], | 821 std::string host_sub_chunk(&canonicalized_host[i], |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 901 return pkp.spki_hashes.size() > 0 || pkp.bad_spki_hashes.size() > 0; | 942 return pkp.spki_hashes.size() > 0 || pkp.bad_spki_hashes.size() > 0; |
| 902 } | 943 } |
| 903 | 944 |
| 904 TransportSecurityState::DomainState::PKPState::PKPState() { | 945 TransportSecurityState::DomainState::PKPState::PKPState() { |
| 905 } | 946 } |
| 906 | 947 |
| 907 TransportSecurityState::DomainState::PKPState::~PKPState() { | 948 TransportSecurityState::DomainState::PKPState::~PKPState() { |
| 908 } | 949 } |
| 909 | 950 |
| 910 } // namespace | 951 } // namespace |
| OLD | NEW |