| 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 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <memory> | 8 #include <memory> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| (...skipping 646 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 657 } | 657 } |
| 658 | 658 |
| 659 bool TransportSecurityState::CheckPublicKeyPins( | 659 bool TransportSecurityState::CheckPublicKeyPins( |
| 660 const HostPortPair& host_port_pair, | 660 const HostPortPair& host_port_pair, |
| 661 bool is_issued_by_known_root, | 661 bool is_issued_by_known_root, |
| 662 const HashValueVector& public_key_hashes, | 662 const HashValueVector& public_key_hashes, |
| 663 const X509Certificate* served_certificate_chain, | 663 const X509Certificate* served_certificate_chain, |
| 664 const X509Certificate* validated_certificate_chain, | 664 const X509Certificate* validated_certificate_chain, |
| 665 const PublicKeyPinReportStatus report_status, | 665 const PublicKeyPinReportStatus report_status, |
| 666 std::string* pinning_failure_log) { | 666 std::string* pinning_failure_log) { |
| 667 // Perform pin validation if, and only if, all these conditions obtain: | 667 // Perform pin validation only if the server actually has public key pins. |
| 668 // | 668 if (!HasPublicKeyPins(host_port_pair.host())) { |
| 669 // * the server's certificate chain chains up to a known root (i.e. not a | |
| 670 // user-installed trust anchor); and | |
| 671 // * the server actually has public key pins. | |
| 672 if (!is_issued_by_known_root || !HasPublicKeyPins(host_port_pair.host())) { | |
| 673 return true; | 669 return true; |
| 674 } | 670 } |
| 675 | 671 |
| 676 bool pins_are_valid = CheckPublicKeyPinsImpl( | 672 bool pins_are_valid = CheckPublicKeyPinsImpl( |
| 677 host_port_pair, public_key_hashes, served_certificate_chain, | 673 host_port_pair, is_issued_by_known_root, public_key_hashes, |
| 678 validated_certificate_chain, report_status, pinning_failure_log); | 674 served_certificate_chain, validated_certificate_chain, report_status, |
| 675 pinning_failure_log); |
| 676 // Don't track statistics when a local trust anchor would override the pinning |
| 677 // anyway. |
| 678 if (!is_issued_by_known_root) { |
| 679 return pins_are_valid; |
| 680 } |
| 679 if (!pins_are_valid) { | 681 if (!pins_are_valid) { |
| 680 LOG(ERROR) << *pinning_failure_log; | 682 LOG(ERROR) << *pinning_failure_log; |
| 681 ReportUMAOnPinFailure(host_port_pair.host()); | 683 ReportUMAOnPinFailure(host_port_pair.host()); |
| 682 } | 684 } |
| 683 | 685 |
| 684 UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", pins_are_valid); | 686 UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", pins_are_valid); |
| 685 return pins_are_valid; | 687 return pins_are_valid; |
| 686 } | 688 } |
| 687 | 689 |
| 688 bool TransportSecurityState::HasPublicKeyPins(const std::string& host) { | 690 bool TransportSecurityState::HasPublicKeyPins(const std::string& host) { |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 799 } else { | 801 } else { |
| 800 const std::string hashed_host = HashHost(canonicalized_host); | 802 const std::string hashed_host = HashHost(canonicalized_host); |
| 801 enabled_pkp_hosts_.erase(hashed_host); | 803 enabled_pkp_hosts_.erase(hashed_host); |
| 802 } | 804 } |
| 803 | 805 |
| 804 DirtyNotify(); | 806 DirtyNotify(); |
| 805 } | 807 } |
| 806 | 808 |
| 807 bool TransportSecurityState::CheckPinsAndMaybeSendReport( | 809 bool TransportSecurityState::CheckPinsAndMaybeSendReport( |
| 808 const HostPortPair& host_port_pair, | 810 const HostPortPair& host_port_pair, |
| 811 bool is_issued_by_known_root, |
| 809 const TransportSecurityState::PKPState& pkp_state, | 812 const TransportSecurityState::PKPState& pkp_state, |
| 810 const HashValueVector& hashes, | 813 const HashValueVector& hashes, |
| 811 const X509Certificate* served_certificate_chain, | 814 const X509Certificate* served_certificate_chain, |
| 812 const X509Certificate* validated_certificate_chain, | 815 const X509Certificate* validated_certificate_chain, |
| 813 const TransportSecurityState::PublicKeyPinReportStatus report_status, | 816 const TransportSecurityState::PublicKeyPinReportStatus report_status, |
| 814 std::string* failure_log) { | 817 std::string* failure_log) { |
| 815 if (pkp_state.CheckPublicKeyPins(hashes, failure_log)) | 818 if (pkp_state.CheckPublicKeyPins(hashes, failure_log)) |
| 816 return true; | 819 return true; |
| 817 | 820 |
| 818 if (!report_sender_ || | 821 if (!report_sender_ || !is_issued_by_known_root || |
| 819 report_status != TransportSecurityState::ENABLE_PIN_REPORTS || | 822 report_status != TransportSecurityState::ENABLE_PIN_REPORTS || |
| 820 pkp_state.report_uri.is_empty()) { | 823 pkp_state.report_uri.is_empty()) { |
| 821 return false; | 824 return false; |
| 822 } | 825 } |
| 823 | 826 |
| 824 DCHECK(pkp_state.report_uri.is_valid()); | 827 DCHECK(pkp_state.report_uri.is_valid()); |
| 825 // Report URIs should not be used if they are the same host as the pin | 828 // Report URIs should not be used if they are the same host as the pin |
| 826 // and are HTTPS, to avoid going into a report-sending loop. | 829 // and are HTTPS, to avoid going into a report-sending loop. |
| 827 if (!IsReportUriValidForHost(pkp_state.report_uri, host_port_pair.host())) | 830 if (!IsReportUriValidForHost(pkp_state.report_uri, host_port_pair.host())) |
| 828 return false; | 831 return false; |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1050 } | 1053 } |
| 1051 | 1054 |
| 1052 PKPState pkp_state; | 1055 PKPState pkp_state; |
| 1053 pkp_state.last_observed = now; | 1056 pkp_state.last_observed = now; |
| 1054 pkp_state.expiry = now; | 1057 pkp_state.expiry = now; |
| 1055 pkp_state.include_subdomains = include_subdomains; | 1058 pkp_state.include_subdomains = include_subdomains; |
| 1056 pkp_state.spki_hashes = spki_hashes; | 1059 pkp_state.spki_hashes = spki_hashes; |
| 1057 pkp_state.report_uri = report_uri; | 1060 pkp_state.report_uri = report_uri; |
| 1058 pkp_state.domain = DNSDomainToString(CanonicalizeHost(host_port_pair.host())); | 1061 pkp_state.domain = DNSDomainToString(CanonicalizeHost(host_port_pair.host())); |
| 1059 | 1062 |
| 1060 // Only perform pin validation if the cert chains up to a known root. | |
| 1061 if (!ssl_info.is_issued_by_known_root) | |
| 1062 return true; | |
| 1063 | |
| 1064 CheckPinsAndMaybeSendReport( | 1063 CheckPinsAndMaybeSendReport( |
| 1065 host_port_pair, pkp_state, ssl_info.public_key_hashes, | 1064 host_port_pair, ssl_info.is_issued_by_known_root, pkp_state, |
| 1066 ssl_info.unverified_cert.get(), ssl_info.cert.get(), ENABLE_PIN_REPORTS, | 1065 ssl_info.public_key_hashes, ssl_info.unverified_cert.get(), |
| 1067 &unused_failure_log); | 1066 ssl_info.cert.get(), ENABLE_PIN_REPORTS, &unused_failure_log); |
| 1068 return true; | 1067 return true; |
| 1069 } | 1068 } |
| 1070 | 1069 |
| 1071 void TransportSecurityState::ProcessExpectCTHeader( | 1070 void TransportSecurityState::ProcessExpectCTHeader( |
| 1072 const std::string& value, | 1071 const std::string& value, |
| 1073 const HostPortPair& host_port_pair, | 1072 const HostPortPair& host_port_pair, |
| 1074 const SSLInfo& ssl_info) { | 1073 const SSLInfo& ssl_info) { |
| 1075 DCHECK(CalledOnValidThread()); | 1074 DCHECK(CalledOnValidThread()); |
| 1076 | 1075 |
| 1077 if (!expect_ct_reporter_) | 1076 if (!expect_ct_reporter_) |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1114 | 1113 |
| 1115 // static | 1114 // static |
| 1116 bool TransportSecurityState::IsBuildTimely() { | 1115 bool TransportSecurityState::IsBuildTimely() { |
| 1117 const base::Time build_time = base::GetBuildTime(); | 1116 const base::Time build_time = base::GetBuildTime(); |
| 1118 // We consider built-in information to be timely for 10 weeks. | 1117 // We consider built-in information to be timely for 10 weeks. |
| 1119 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; | 1118 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; |
| 1120 } | 1119 } |
| 1121 | 1120 |
| 1122 bool TransportSecurityState::CheckPublicKeyPinsImpl( | 1121 bool TransportSecurityState::CheckPublicKeyPinsImpl( |
| 1123 const HostPortPair& host_port_pair, | 1122 const HostPortPair& host_port_pair, |
| 1123 bool is_issued_by_known_root, |
| 1124 const HashValueVector& hashes, | 1124 const HashValueVector& hashes, |
| 1125 const X509Certificate* served_certificate_chain, | 1125 const X509Certificate* served_certificate_chain, |
| 1126 const X509Certificate* validated_certificate_chain, | 1126 const X509Certificate* validated_certificate_chain, |
| 1127 const PublicKeyPinReportStatus report_status, | 1127 const PublicKeyPinReportStatus report_status, |
| 1128 std::string* failure_log) { | 1128 std::string* failure_log) { |
| 1129 PKPState pkp_state; | 1129 PKPState pkp_state; |
| 1130 STSState unused; | 1130 STSState unused; |
| 1131 | 1131 |
| 1132 if (!GetDynamicPKPState(host_port_pair.host(), &pkp_state) && | 1132 if (!GetDynamicPKPState(host_port_pair.host(), &pkp_state) && |
| 1133 !GetStaticDomainState(host_port_pair.host(), &unused, &pkp_state)) { | 1133 !GetStaticDomainState(host_port_pair.host(), &unused, &pkp_state)) { |
| 1134 // HasPublicKeyPins should have returned true in order for this method | 1134 // HasPublicKeyPins should have returned true in order for this method |
| 1135 // to have been called, so if we fall through to here, it's an error. | 1135 // to have been called, so if we fall through to here, it's an error. |
| 1136 return false; | 1136 return false; |
| 1137 } | 1137 } |
| 1138 | 1138 |
| 1139 return CheckPinsAndMaybeSendReport( | 1139 return CheckPinsAndMaybeSendReport( |
| 1140 host_port_pair, pkp_state, hashes, served_certificate_chain, | 1140 host_port_pair, is_issued_by_known_root, pkp_state, hashes, |
| 1141 validated_certificate_chain, report_status, failure_log); | 1141 served_certificate_chain, validated_certificate_chain, report_status, |
| 1142 failure_log); |
| 1142 } | 1143 } |
| 1143 | 1144 |
| 1144 bool TransportSecurityState::GetStaticDomainState(const std::string& host, | 1145 bool TransportSecurityState::GetStaticDomainState(const std::string& host, |
| 1145 STSState* sts_state, | 1146 STSState* sts_state, |
| 1146 PKPState* pkp_state) const { | 1147 PKPState* pkp_state) const { |
| 1147 DCHECK(CalledOnValidThread()); | 1148 DCHECK(CalledOnValidThread()); |
| 1148 | 1149 |
| 1149 sts_state->upgrade_mode = STSState::MODE_FORCE_HTTPS; | 1150 sts_state->upgrade_mode = STSState::MODE_FORCE_HTTPS; |
| 1150 sts_state->include_subdomains = false; | 1151 sts_state->include_subdomains = false; |
| 1151 pkp_state->include_subdomains = false; | 1152 pkp_state->include_subdomains = false; |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1400 TransportSecurityState::PKPStateIterator::PKPStateIterator( | 1401 TransportSecurityState::PKPStateIterator::PKPStateIterator( |
| 1401 const TransportSecurityState& state) | 1402 const TransportSecurityState& state) |
| 1402 : iterator_(state.enabled_pkp_hosts_.begin()), | 1403 : iterator_(state.enabled_pkp_hosts_.begin()), |
| 1403 end_(state.enabled_pkp_hosts_.end()) { | 1404 end_(state.enabled_pkp_hosts_.end()) { |
| 1404 } | 1405 } |
| 1405 | 1406 |
| 1406 TransportSecurityState::PKPStateIterator::~PKPStateIterator() { | 1407 TransportSecurityState::PKPStateIterator::~PKPStateIterator() { |
| 1407 } | 1408 } |
| 1408 | 1409 |
| 1409 } // namespace | 1410 } // namespace |
| OLD | NEW |