| 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 630 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 641 } | 641 } |
| 642 | 642 |
| 643 bool TransportSecurityState::CheckPublicKeyPins( | 643 bool TransportSecurityState::CheckPublicKeyPins( |
| 644 const HostPortPair& host_port_pair, | 644 const HostPortPair& host_port_pair, |
| 645 bool is_issued_by_known_root, | 645 bool is_issued_by_known_root, |
| 646 const HashValueVector& public_key_hashes, | 646 const HashValueVector& public_key_hashes, |
| 647 const X509Certificate* served_certificate_chain, | 647 const X509Certificate* served_certificate_chain, |
| 648 const X509Certificate* validated_certificate_chain, | 648 const X509Certificate* validated_certificate_chain, |
| 649 const PublicKeyPinReportStatus report_status, | 649 const PublicKeyPinReportStatus report_status, |
| 650 std::string* pinning_failure_log) { | 650 std::string* pinning_failure_log) { |
| 651 // Perform pin validation if, and only if, all these conditions obtain: | 651 // Perform pin validation only if the server actually has public key pins. |
| 652 // | 652 if (!HasPublicKeyPins(host_port_pair.host())) { |
| 653 // * the server's certificate chain chains up to a known root (i.e. not a | |
| 654 // user-installed trust anchor); and | |
| 655 // * the server actually has public key pins. | |
| 656 if (!is_issued_by_known_root || !HasPublicKeyPins(host_port_pair.host())) { | |
| 657 return true; | 653 return true; |
| 658 } | 654 } |
| 659 | 655 |
| 660 bool pins_are_valid = CheckPublicKeyPinsImpl( | 656 bool pins_are_valid = CheckPublicKeyPinsImpl( |
| 661 host_port_pair, public_key_hashes, served_certificate_chain, | 657 host_port_pair, is_issued_by_known_root, public_key_hashes, |
| 662 validated_certificate_chain, report_status, pinning_failure_log); | 658 served_certificate_chain, validated_certificate_chain, report_status, |
| 659 pinning_failure_log); |
| 660 // Don't track statistics when a local trust anchor would override the pinning |
| 661 // anyway. |
| 662 if (!is_issued_by_known_root) { |
| 663 return pins_are_valid; |
| 664 } |
| 663 if (!pins_are_valid) { | 665 if (!pins_are_valid) { |
| 664 LOG(ERROR) << *pinning_failure_log; | 666 LOG(ERROR) << *pinning_failure_log; |
| 665 ReportUMAOnPinFailure(host_port_pair.host()); | 667 ReportUMAOnPinFailure(host_port_pair.host()); |
| 666 } | 668 } |
| 667 | 669 |
| 668 UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", pins_are_valid); | 670 UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", pins_are_valid); |
| 669 return pins_are_valid; | 671 return pins_are_valid; |
| 670 } | 672 } |
| 671 | 673 |
| 672 bool TransportSecurityState::HasPublicKeyPins(const std::string& host) { | 674 bool TransportSecurityState::HasPublicKeyPins(const std::string& host) { |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 783 } else { | 785 } else { |
| 784 const std::string hashed_host = HashHost(canonicalized_host); | 786 const std::string hashed_host = HashHost(canonicalized_host); |
| 785 enabled_pkp_hosts_.erase(hashed_host); | 787 enabled_pkp_hosts_.erase(hashed_host); |
| 786 } | 788 } |
| 787 | 789 |
| 788 DirtyNotify(); | 790 DirtyNotify(); |
| 789 } | 791 } |
| 790 | 792 |
| 791 bool TransportSecurityState::CheckPinsAndMaybeSendReport( | 793 bool TransportSecurityState::CheckPinsAndMaybeSendReport( |
| 792 const HostPortPair& host_port_pair, | 794 const HostPortPair& host_port_pair, |
| 795 bool is_issued_by_known_root, |
| 793 const TransportSecurityState::PKPState& pkp_state, | 796 const TransportSecurityState::PKPState& pkp_state, |
| 794 const HashValueVector& hashes, | 797 const HashValueVector& hashes, |
| 795 const X509Certificate* served_certificate_chain, | 798 const X509Certificate* served_certificate_chain, |
| 796 const X509Certificate* validated_certificate_chain, | 799 const X509Certificate* validated_certificate_chain, |
| 797 const TransportSecurityState::PublicKeyPinReportStatus report_status, | 800 const TransportSecurityState::PublicKeyPinReportStatus report_status, |
| 798 std::string* failure_log) { | 801 std::string* failure_log) { |
| 799 if (pkp_state.CheckPublicKeyPins(hashes, failure_log)) | 802 if (pkp_state.CheckPublicKeyPins(hashes, failure_log)) |
| 800 return true; | 803 return true; |
| 801 | 804 |
| 802 if (!report_sender_ || | 805 if (!report_sender_ || !is_issued_by_known_root || |
| 803 report_status != TransportSecurityState::ENABLE_PIN_REPORTS || | 806 report_status != TransportSecurityState::ENABLE_PIN_REPORTS || |
| 804 pkp_state.report_uri.is_empty()) { | 807 pkp_state.report_uri.is_empty()) { |
| 805 return false; | 808 return false; |
| 806 } | 809 } |
| 807 | 810 |
| 808 DCHECK(pkp_state.report_uri.is_valid()); | 811 DCHECK(pkp_state.report_uri.is_valid()); |
| 809 // Report URIs should not be used if they are the same host as the pin | 812 // Report URIs should not be used if they are the same host as the pin |
| 810 // and are HTTPS, to avoid going into a report-sending loop. | 813 // and are HTTPS, to avoid going into a report-sending loop. |
| 811 if (!IsReportUriValidForHost(pkp_state.report_uri, host_port_pair.host())) | 814 if (!IsReportUriValidForHost(pkp_state.report_uri, host_port_pair.host())) |
| 812 return false; | 815 return false; |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1011 } | 1014 } |
| 1012 | 1015 |
| 1013 PKPState pkp_state; | 1016 PKPState pkp_state; |
| 1014 pkp_state.last_observed = now; | 1017 pkp_state.last_observed = now; |
| 1015 pkp_state.expiry = now; | 1018 pkp_state.expiry = now; |
| 1016 pkp_state.include_subdomains = include_subdomains; | 1019 pkp_state.include_subdomains = include_subdomains; |
| 1017 pkp_state.spki_hashes = spki_hashes; | 1020 pkp_state.spki_hashes = spki_hashes; |
| 1018 pkp_state.report_uri = report_uri; | 1021 pkp_state.report_uri = report_uri; |
| 1019 pkp_state.domain = DNSDomainToString(CanonicalizeHost(host_port_pair.host())); | 1022 pkp_state.domain = DNSDomainToString(CanonicalizeHost(host_port_pair.host())); |
| 1020 | 1023 |
| 1021 // Only perform pin validation if the cert chains up to a known root. | |
| 1022 if (!ssl_info.is_issued_by_known_root) | |
| 1023 return true; | |
| 1024 | |
| 1025 CheckPinsAndMaybeSendReport( | 1024 CheckPinsAndMaybeSendReport( |
| 1026 host_port_pair, pkp_state, ssl_info.public_key_hashes, | 1025 host_port_pair, ssl_info.is_issued_by_known_root, pkp_state, |
| 1027 ssl_info.unverified_cert.get(), ssl_info.cert.get(), ENABLE_PIN_REPORTS, | 1026 ssl_info.public_key_hashes, ssl_info.unverified_cert.get(), |
| 1028 &unused_failure_log); | 1027 ssl_info.cert.get(), ENABLE_PIN_REPORTS, &unused_failure_log); |
| 1029 return true; | 1028 return true; |
| 1030 } | 1029 } |
| 1031 | 1030 |
| 1032 void TransportSecurityState::ProcessExpectCTHeader( | 1031 void TransportSecurityState::ProcessExpectCTHeader( |
| 1033 const std::string& value, | 1032 const std::string& value, |
| 1034 const HostPortPair& host_port_pair, | 1033 const HostPortPair& host_port_pair, |
| 1035 const SSLInfo& ssl_info) { | 1034 const SSLInfo& ssl_info) { |
| 1036 DCHECK(CalledOnValidThread()); | 1035 DCHECK(CalledOnValidThread()); |
| 1037 | 1036 |
| 1038 if (!expect_ct_reporter_) | 1037 if (!expect_ct_reporter_) |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1075 | 1074 |
| 1076 // static | 1075 // static |
| 1077 bool TransportSecurityState::IsBuildTimely() { | 1076 bool TransportSecurityState::IsBuildTimely() { |
| 1078 const base::Time build_time = base::GetBuildTime(); | 1077 const base::Time build_time = base::GetBuildTime(); |
| 1079 // We consider built-in information to be timely for 10 weeks. | 1078 // We consider built-in information to be timely for 10 weeks. |
| 1080 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; | 1079 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; |
| 1081 } | 1080 } |
| 1082 | 1081 |
| 1083 bool TransportSecurityState::CheckPublicKeyPinsImpl( | 1082 bool TransportSecurityState::CheckPublicKeyPinsImpl( |
| 1084 const HostPortPair& host_port_pair, | 1083 const HostPortPair& host_port_pair, |
| 1084 bool is_issued_by_known_root, |
| 1085 const HashValueVector& hashes, | 1085 const HashValueVector& hashes, |
| 1086 const X509Certificate* served_certificate_chain, | 1086 const X509Certificate* served_certificate_chain, |
| 1087 const X509Certificate* validated_certificate_chain, | 1087 const X509Certificate* validated_certificate_chain, |
| 1088 const PublicKeyPinReportStatus report_status, | 1088 const PublicKeyPinReportStatus report_status, |
| 1089 std::string* failure_log) { | 1089 std::string* failure_log) { |
| 1090 PKPState pkp_state; | 1090 PKPState pkp_state; |
| 1091 STSState unused; | 1091 STSState unused; |
| 1092 | 1092 |
| 1093 if (!GetDynamicPKPState(host_port_pair.host(), &pkp_state) && | 1093 if (!GetDynamicPKPState(host_port_pair.host(), &pkp_state) && |
| 1094 !GetStaticDomainState(host_port_pair.host(), &unused, &pkp_state)) { | 1094 !GetStaticDomainState(host_port_pair.host(), &unused, &pkp_state)) { |
| 1095 // HasPublicKeyPins should have returned true in order for this method | 1095 // HasPublicKeyPins should have returned true in order for this method |
| 1096 // to have been called, so if we fall through to here, it's an error. | 1096 // to have been called, so if we fall through to here, it's an error. |
| 1097 return false; | 1097 return false; |
| 1098 } | 1098 } |
| 1099 | 1099 |
| 1100 return CheckPinsAndMaybeSendReport( | 1100 return CheckPinsAndMaybeSendReport( |
| 1101 host_port_pair, pkp_state, hashes, served_certificate_chain, | 1101 host_port_pair, is_issued_by_known_root, pkp_state, hashes, |
| 1102 validated_certificate_chain, report_status, failure_log); | 1102 served_certificate_chain, validated_certificate_chain, report_status, |
| 1103 failure_log); |
| 1103 } | 1104 } |
| 1104 | 1105 |
| 1105 bool TransportSecurityState::GetStaticDomainState(const std::string& host, | 1106 bool TransportSecurityState::GetStaticDomainState(const std::string& host, |
| 1106 STSState* sts_state, | 1107 STSState* sts_state, |
| 1107 PKPState* pkp_state) const { | 1108 PKPState* pkp_state) const { |
| 1108 DCHECK(CalledOnValidThread()); | 1109 DCHECK(CalledOnValidThread()); |
| 1109 | 1110 |
| 1110 sts_state->upgrade_mode = STSState::MODE_FORCE_HTTPS; | 1111 sts_state->upgrade_mode = STSState::MODE_FORCE_HTTPS; |
| 1111 sts_state->include_subdomains = false; | 1112 sts_state->include_subdomains = false; |
| 1112 pkp_state->include_subdomains = false; | 1113 pkp_state->include_subdomains = false; |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1356 TransportSecurityState::PKPStateIterator::PKPStateIterator( | 1357 TransportSecurityState::PKPStateIterator::PKPStateIterator( |
| 1357 const TransportSecurityState& state) | 1358 const TransportSecurityState& state) |
| 1358 : iterator_(state.enabled_pkp_hosts_.begin()), | 1359 : iterator_(state.enabled_pkp_hosts_.begin()), |
| 1359 end_(state.enabled_pkp_hosts_.end()) { | 1360 end_(state.enabled_pkp_hosts_.end()) { |
| 1360 } | 1361 } |
| 1361 | 1362 |
| 1362 TransportSecurityState::PKPStateIterator::~PKPStateIterator() { | 1363 TransportSecurityState::PKPStateIterator::~PKPStateIterator() { |
| 1363 } | 1364 } |
| 1364 | 1365 |
| 1365 } // namespace | 1366 } // namespace |
| OLD | NEW |