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 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <memory> | 8 #include <memory> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| (...skipping 638 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 649 STSState static_sts_state; | 649 STSState static_sts_state; |
| 650 PKPState unused; | 650 PKPState unused; |
| 651 if (GetStaticDomainState(host, &static_sts_state, &unused) && | 651 if (GetStaticDomainState(host, &static_sts_state, &unused) && |
| 652 static_sts_state.ShouldUpgradeToSSL()) { | 652 static_sts_state.ShouldUpgradeToSSL()) { |
| 653 return true; | 653 return true; |
| 654 } | 654 } |
| 655 | 655 |
| 656 return false; | 656 return false; |
| 657 } | 657 } |
| 658 | 658 |
| 659 bool TransportSecurityState::CheckPublicKeyPins( | 659 TransportSecurityState::PKPStatus 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 only if the server actually has public key pins. | 667 // Perform pin validation only if the server actually has public key pins. |
| 668 if (!HasPublicKeyPins(host_port_pair.host())) { | 668 if (!HasPublicKeyPins(host_port_pair.host())) { |
| 669 return true; | 669 return PKPStatus::OK; |
| 670 } | 670 } |
| 671 | 671 |
| 672 bool pins_are_valid = CheckPublicKeyPinsImpl( | 672 PKPStatus pin_validity = CheckPublicKeyPinsImpl( |
| 673 host_port_pair, is_issued_by_known_root, public_key_hashes, | 673 host_port_pair, is_issued_by_known_root, public_key_hashes, |
| 674 served_certificate_chain, validated_certificate_chain, report_status, | 674 served_certificate_chain, validated_certificate_chain, report_status, |
| 675 pinning_failure_log); | 675 pinning_failure_log); |
| 676 | |
| 676 // Don't track statistics when a local trust anchor would override the pinning | 677 // Don't track statistics when a local trust anchor would override the pinning |
| 677 // anyway. | 678 // anyway. |
| 678 if (!is_issued_by_known_root) | 679 if (is_issued_by_known_root) { |
| 679 return pins_are_valid; | 680 if (pin_validity == PKPStatus::VIOLATED) { |
| 680 | 681 LOG(ERROR) << *pinning_failure_log; |
| 681 if (!pins_are_valid) { | 682 ReportUMAOnPinFailure(host_port_pair.host()); |
| 682 LOG(ERROR) << *pinning_failure_log; | 683 } |
| 683 ReportUMAOnPinFailure(host_port_pair.host()); | 684 bool pin_success = (pin_validity == PKPStatus::OK); |
| 685 UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", pin_success); | |
| 684 } | 686 } |
| 685 | 687 return pin_validity; |
|
Ryan Sleevi
2016/06/15 02:04:03
I'm not sure why you changed it, but we prefer to
estark
2016/06/15 02:35:00
Both |pinning_failure_log| and the UMA histograms
Ryan Sleevi
2016/06/15 02:44:36
In order for the histograms to be useful, the UMA
dadrian
2016/06/15 02:47:55
|pinning_failure_log| is added to the certificate
estark
2016/06/15 02:48:04
Ah, I see.
dadrian
2016/06/15 18:58:28
Added the bail-out-early, but am currently leaving
| |
| 686 UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", pins_are_valid); | |
| 687 return pins_are_valid; | |
| 688 } | 688 } |
| 689 | 689 |
| 690 bool TransportSecurityState::HasPublicKeyPins(const std::string& host) { | 690 bool TransportSecurityState::HasPublicKeyPins(const std::string& host) { |
| 691 PKPState dynamic_state; | 691 PKPState dynamic_state; |
| 692 if (GetDynamicPKPState(host, &dynamic_state)) | 692 if (GetDynamicPKPState(host, &dynamic_state)) |
| 693 return dynamic_state.HasPublicKeyPins(); | 693 return dynamic_state.HasPublicKeyPins(); |
| 694 | 694 |
| 695 STSState unused; | 695 STSState unused; |
| 696 PKPState static_pkp_state; | 696 PKPState static_pkp_state; |
| 697 if (GetStaticDomainState(host, &unused, &static_pkp_state)) { | 697 if (GetStaticDomainState(host, &unused, &static_pkp_state)) { |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 799 | 799 |
| 800 enabled_pkp_hosts_[HashHost(canonicalized_host)] = pkp_state; | 800 enabled_pkp_hosts_[HashHost(canonicalized_host)] = pkp_state; |
| 801 } else { | 801 } else { |
| 802 const std::string hashed_host = HashHost(canonicalized_host); | 802 const std::string hashed_host = HashHost(canonicalized_host); |
| 803 enabled_pkp_hosts_.erase(hashed_host); | 803 enabled_pkp_hosts_.erase(hashed_host); |
| 804 } | 804 } |
| 805 | 805 |
| 806 DirtyNotify(); | 806 DirtyNotify(); |
| 807 } | 807 } |
| 808 | 808 |
| 809 bool TransportSecurityState::CheckPinsAndMaybeSendReport( | 809 TransportSecurityState::PKPStatus |
| 810 TransportSecurityState::CheckPinsAndMaybeSendReport( | |
| 810 const HostPortPair& host_port_pair, | 811 const HostPortPair& host_port_pair, |
| 811 bool is_issued_by_known_root, | 812 bool is_issued_by_known_root, |
| 812 const TransportSecurityState::PKPState& pkp_state, | 813 const TransportSecurityState::PKPState& pkp_state, |
| 813 const HashValueVector& hashes, | 814 const HashValueVector& hashes, |
| 814 const X509Certificate* served_certificate_chain, | 815 const X509Certificate* served_certificate_chain, |
| 815 const X509Certificate* validated_certificate_chain, | 816 const X509Certificate* validated_certificate_chain, |
| 816 const TransportSecurityState::PublicKeyPinReportStatus report_status, | 817 const TransportSecurityState::PublicKeyPinReportStatus report_status, |
| 817 std::string* failure_log) { | 818 std::string* failure_log) { |
| 818 if (pkp_state.CheckPublicKeyPins(hashes, failure_log)) | 819 if (pkp_state.CheckPublicKeyPins(hashes, failure_log)) |
| 819 return true; | 820 return PKPStatus::OK; |
| 820 | 821 |
| 821 if (!report_sender_ || !is_issued_by_known_root || | 822 // Don't report violations for certificates that chain to local roots. |
| 823 if (!is_issued_by_known_root) | |
| 824 return PKPStatus::BYPASSED; | |
| 825 | |
| 826 if (!report_sender_ || | |
| 822 report_status != TransportSecurityState::ENABLE_PIN_REPORTS || | 827 report_status != TransportSecurityState::ENABLE_PIN_REPORTS || |
| 823 pkp_state.report_uri.is_empty()) { | 828 pkp_state.report_uri.is_empty()) { |
| 824 return false; | 829 return PKPStatus::VIOLATED; |
| 825 } | 830 } |
| 826 | 831 |
| 827 DCHECK(pkp_state.report_uri.is_valid()); | 832 DCHECK(pkp_state.report_uri.is_valid()); |
| 828 // Report URIs should not be used if they are the same host as the pin | 833 // Report URIs should not be used if they are the same host as the pin |
| 829 // and are HTTPS, to avoid going into a report-sending loop. | 834 // and are HTTPS, to avoid going into a report-sending loop. |
| 830 if (!IsReportUriValidForHost(pkp_state.report_uri, host_port_pair.host())) | 835 if (!IsReportUriValidForHost(pkp_state.report_uri, host_port_pair.host())) |
| 831 return false; | 836 return PKPStatus::VIOLATED; |
| 832 | 837 |
| 833 std::string serialized_report; | 838 std::string serialized_report; |
| 834 std::string report_cache_key; | 839 std::string report_cache_key; |
| 835 if (!GetHPKPReport(host_port_pair, pkp_state, served_certificate_chain, | 840 if (!GetHPKPReport(host_port_pair, pkp_state, served_certificate_chain, |
| 836 validated_certificate_chain, &serialized_report, | 841 validated_certificate_chain, &serialized_report, |
| 837 &report_cache_key)) { | 842 &report_cache_key)) { |
| 838 return false; | 843 return PKPStatus::VIOLATED; |
| 839 } | 844 } |
| 840 | 845 |
| 841 // Limit the rate at which duplicate reports are sent to the same | 846 // Limit the rate at which duplicate reports are sent to the same |
| 842 // report URI. The same report will not be sent within | 847 // report URI. The same report will not be sent within |
| 843 // |kTimeToRememberHPKPReportsMins|, which reduces load on servers and | 848 // |kTimeToRememberHPKPReportsMins|, which reduces load on servers and |
| 844 // also prevents accidental loops (a.com triggers a report to b.com | 849 // also prevents accidental loops (a.com triggers a report to b.com |
| 845 // which triggers a report to a.com). See section 2.1.4 of RFC 7469. | 850 // which triggers a report to a.com). See section 2.1.4 of RFC 7469. |
| 846 if (sent_reports_cache_.Get(report_cache_key, base::TimeTicks::Now())) | 851 if (sent_reports_cache_.Get(report_cache_key, base::TimeTicks::Now())) |
| 847 return false; | 852 return PKPStatus::VIOLATED; |
| 848 sent_reports_cache_.Put( | 853 sent_reports_cache_.Put( |
| 849 report_cache_key, true, base::TimeTicks::Now(), | 854 report_cache_key, true, base::TimeTicks::Now(), |
| 850 base::TimeTicks::Now() + | 855 base::TimeTicks::Now() + |
| 851 base::TimeDelta::FromMinutes(kTimeToRememberHPKPReportsMins)); | 856 base::TimeDelta::FromMinutes(kTimeToRememberHPKPReportsMins)); |
| 852 | 857 |
| 853 report_sender_->Send(pkp_state.report_uri, serialized_report); | 858 report_sender_->Send(pkp_state.report_uri, serialized_report); |
| 854 return false; | 859 return PKPStatus::VIOLATED; |
| 855 } | 860 } |
| 856 | 861 |
| 857 bool TransportSecurityState::GetStaticExpectCTState( | 862 bool TransportSecurityState::GetStaticExpectCTState( |
| 858 const std::string& host, | 863 const std::string& host, |
| 859 ExpectCTState* expect_ct_state) const { | 864 ExpectCTState* expect_ct_state) const { |
| 860 DCHECK(CalledOnValidThread()); | 865 DCHECK(CalledOnValidThread()); |
| 861 | 866 |
| 862 if (!IsBuildTimely()) | 867 if (!IsBuildTimely()) |
| 863 return false; | 868 return false; |
| 864 | 869 |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1111 "Net.PublicKeyPinFailureDomain", result.domain_id); | 1116 "Net.PublicKeyPinFailureDomain", result.domain_id); |
| 1112 } | 1117 } |
| 1113 | 1118 |
| 1114 // static | 1119 // static |
| 1115 bool TransportSecurityState::IsBuildTimely() { | 1120 bool TransportSecurityState::IsBuildTimely() { |
| 1116 const base::Time build_time = base::GetBuildTime(); | 1121 const base::Time build_time = base::GetBuildTime(); |
| 1117 // We consider built-in information to be timely for 10 weeks. | 1122 // We consider built-in information to be timely for 10 weeks. |
| 1118 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; | 1123 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; |
| 1119 } | 1124 } |
| 1120 | 1125 |
| 1121 bool TransportSecurityState::CheckPublicKeyPinsImpl( | 1126 TransportSecurityState::PKPStatus |
| 1127 TransportSecurityState::CheckPublicKeyPinsImpl( | |
| 1122 const HostPortPair& host_port_pair, | 1128 const HostPortPair& host_port_pair, |
| 1123 bool is_issued_by_known_root, | 1129 bool is_issued_by_known_root, |
| 1124 const HashValueVector& hashes, | 1130 const HashValueVector& hashes, |
| 1125 const X509Certificate* served_certificate_chain, | 1131 const X509Certificate* served_certificate_chain, |
| 1126 const X509Certificate* validated_certificate_chain, | 1132 const X509Certificate* validated_certificate_chain, |
| 1127 const PublicKeyPinReportStatus report_status, | 1133 const PublicKeyPinReportStatus report_status, |
| 1128 std::string* failure_log) { | 1134 std::string* failure_log) { |
| 1129 PKPState pkp_state; | 1135 PKPState pkp_state; |
| 1130 STSState unused; | 1136 STSState unused; |
| 1131 | 1137 |
| 1132 if (!GetDynamicPKPState(host_port_pair.host(), &pkp_state) && | 1138 if (!GetDynamicPKPState(host_port_pair.host(), &pkp_state) && |
| 1133 !GetStaticDomainState(host_port_pair.host(), &unused, &pkp_state)) { | 1139 !GetStaticDomainState(host_port_pair.host(), &unused, &pkp_state)) { |
| 1134 // HasPublicKeyPins should have returned true in order for this method | 1140 // 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. | 1141 // to have been called, so if we fall through to here, it's an error. |
| 1136 return false; | 1142 return PKPStatus::VIOLATED; |
|
estark
2016/06/15 02:48:04
This whole little block should really be a DCHECK,
dadrian
2016/06/15 18:58:28
Acknowledged.
| |
| 1137 } | 1143 } |
| 1138 | 1144 |
| 1139 return CheckPinsAndMaybeSendReport( | 1145 return CheckPinsAndMaybeSendReport( |
| 1140 host_port_pair, is_issued_by_known_root, pkp_state, hashes, | 1146 host_port_pair, is_issued_by_known_root, pkp_state, hashes, |
| 1141 served_certificate_chain, validated_certificate_chain, report_status, | 1147 served_certificate_chain, validated_certificate_chain, report_status, |
| 1142 failure_log); | 1148 failure_log); |
| 1143 } | 1149 } |
| 1144 | 1150 |
| 1145 bool TransportSecurityState::GetStaticDomainState(const std::string& host, | 1151 bool TransportSecurityState::GetStaticDomainState(const std::string& host, |
| 1146 STSState* sts_state, | 1152 STSState* sts_state, |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1401 TransportSecurityState::PKPStateIterator::PKPStateIterator( | 1407 TransportSecurityState::PKPStateIterator::PKPStateIterator( |
| 1402 const TransportSecurityState& state) | 1408 const TransportSecurityState& state) |
| 1403 : iterator_(state.enabled_pkp_hosts_.begin()), | 1409 : iterator_(state.enabled_pkp_hosts_.begin()), |
| 1404 end_(state.enabled_pkp_hosts_.end()) { | 1410 end_(state.enabled_pkp_hosts_.end()) { |
| 1405 } | 1411 } |
| 1406 | 1412 |
| 1407 TransportSecurityState::PKPStateIterator::~PKPStateIterator() { | 1413 TransportSecurityState::PKPStateIterator::~PKPStateIterator() { |
| 1408 } | 1414 } |
| 1409 | 1415 |
| 1410 } // namespace | 1416 } // namespace |
| OLD | NEW |