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 #include <vector> | 10 #include <vector> |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 43 #include "net/http/transport_security_state_ct_policies.inc" | 43 #include "net/http/transport_security_state_ct_policies.inc" |
| 44 #include "net/http/transport_security_state_static.h" | 44 #include "net/http/transport_security_state_static.h" |
| 45 | 45 |
| 46 const size_t kMaxHPKPReportCacheEntries = 50; | 46 const size_t kMaxHPKPReportCacheEntries = 50; |
| 47 const int kTimeToRememberHPKPReportsMins = 60; | 47 const int kTimeToRememberHPKPReportsMins = 60; |
| 48 const size_t kReportCacheKeyLength = 16; | 48 const size_t kReportCacheKeyLength = 16; |
| 49 | 49 |
| 50 // Points to the active transport security state source. | 50 // Points to the active transport security state source. |
| 51 const TransportSecurityStateSource* g_hsts_source = &kHSTSSource; | 51 const TransportSecurityStateSource* g_hsts_source = &kHSTSSource; |
| 52 | 52 |
| 53 // Override for ShouldRequireCT() for unit tests. Possible values: | 53 // Override for CheckCTRequirements() for unit tests. Possible values: |
| 54 // -1: Unless a delegate says otherwise, do not require CT. | 54 // -1: Unless a delegate says otherwise, do not require CT. |
| 55 // 0: Use the default implementation (e.g. production) | 55 // 0: Use the default implementation (e.g. production) |
| 56 // 1: Unless a delegate says otherwise, require CT. | 56 // 1: Unless a delegate says otherwise, require CT. |
| 57 int g_ct_required_for_testing = 0; | 57 int g_ct_required_for_testing = 0; |
| 58 | 58 |
| 59 bool IsDynamicExpectCTEnabled() { | 59 bool IsDynamicExpectCTEnabled() { |
| 60 return base::FeatureList::IsEnabled( | 60 return base::FeatureList::IsEnabled( |
| 61 TransportSecurityState::kDynamicExpectCTFeature); | 61 TransportSecurityState::kDynamicExpectCTFeature); |
| 62 } | 62 } |
| 63 | 63 |
| (...skipping 789 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 853 STSState unused; | 853 STSState unused; |
| 854 PKPState static_pkp_state; | 854 PKPState static_pkp_state; |
| 855 if (GetStaticDomainState(host, &unused, &static_pkp_state)) { | 855 if (GetStaticDomainState(host, &unused, &static_pkp_state)) { |
| 856 if (static_pkp_state.HasPublicKeyPins()) | 856 if (static_pkp_state.HasPublicKeyPins()) |
| 857 return true; | 857 return true; |
| 858 } | 858 } |
| 859 | 859 |
| 860 return false; | 860 return false; |
| 861 } | 861 } |
| 862 | 862 |
| 863 bool TransportSecurityState::ShouldRequireCT( | 863 bool TransportSecurityState::CheckCTRequirements( |
|
mattm
2017/05/04 01:57:11
do you think it's worth returning an enum value so
estark
2017/05/04 04:03:25
Yes, I think that makes sense. Done.
| |
| 864 const std::string& hostname, | 864 const net::HostPortPair& host_port_pair, |
| 865 bool is_issued_by_known_root, | |
| 866 const HashValueVector& public_key_hashes, | |
| 865 const X509Certificate* validated_certificate_chain, | 867 const X509Certificate* validated_certificate_chain, |
| 866 const HashValueVector& public_key_hashes) { | 868 const X509Certificate* served_certificate_chain, |
| 869 const SignedCertificateTimestampAndStatusList& | |
| 870 signed_certificate_timestamps, | |
| 871 const ExpectCTReportStatus report_status, | |
| 872 ct::CertPolicyCompliance cert_policy_compliance) { | |
| 867 using CTRequirementLevel = RequireCTDelegate::CTRequirementLevel; | 873 using CTRequirementLevel = RequireCTDelegate::CTRequirementLevel; |
| 874 std::string hostname = host_port_pair.host(); | |
| 875 | |
| 876 // If the connection complies with CT policy, then no further checks are | |
| 877 // necessary. | |
| 878 if (cert_policy_compliance == | |
| 879 ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS || | |
| 880 cert_policy_compliance == | |
| 881 ct::CertPolicyCompliance::CERT_POLICY_BUILD_NOT_TIMELY) { | |
| 882 return true; | |
| 883 } | |
| 884 | |
| 885 // Check Expect-CT first so that other CT requirements do not prevent | |
| 886 // Expect-CT reports from being sent. | |
| 887 ExpectCTState state; | |
| 888 if (is_issued_by_known_root && IsDynamicExpectCTEnabled() && | |
| 889 GetDynamicExpectCTState(hostname, &state)) { | |
| 890 if (expect_ct_reporter_ && !state.report_uri.is_empty() && | |
| 891 report_status == ENABLE_EXPECT_CT_REPORTS) { | |
| 892 expect_ct_reporter_->OnExpectCTFailed( | |
| 893 host_port_pair, state.report_uri, validated_certificate_chain, | |
| 894 served_certificate_chain, signed_certificate_timestamps); | |
| 895 } | |
| 896 if (state.enforce) | |
| 897 return false; | |
| 898 } | |
| 868 | 899 |
| 869 CTRequirementLevel ct_required = CTRequirementLevel::DEFAULT; | 900 CTRequirementLevel ct_required = CTRequirementLevel::DEFAULT; |
| 870 if (require_ct_delegate_) | 901 if (require_ct_delegate_) |
| 871 ct_required = require_ct_delegate_->IsCTRequiredForHost(hostname); | 902 ct_required = require_ct_delegate_->IsCTRequiredForHost(hostname); |
| 872 if (ct_required != CTRequirementLevel::DEFAULT) | 903 if (ct_required != CTRequirementLevel::DEFAULT) |
| 873 return ct_required == CTRequirementLevel::REQUIRED; | 904 return ct_required != CTRequirementLevel::REQUIRED; |
| 874 | 905 |
| 875 // Allow unittests to override the default result. | 906 // Allow unittests to override the default result. |
| 876 if (g_ct_required_for_testing) | 907 if (g_ct_required_for_testing) |
| 877 return g_ct_required_for_testing == 1; | 908 return g_ct_required_for_testing == 1; |
|
mattm
2017/05/04 01:57:11
should that be != now?
estark
2017/05/04 04:03:25
Fixed with the new enum return value.
| |
| 878 | 909 |
| 879 // Until CT is required for all secure hosts on the Internet, this should | 910 // Until CT is required for all secure hosts on the Internet, this should |
| 880 // remain false. It is provided to simplify the various short-circuit | 911 // remain true. It is provided to simplify the various short-circuit |
| 881 // returns below. | 912 // returns below. |
| 882 bool default_response = false; | 913 bool default_response = true; |
|
mattm
2017/05/04 01:57:11
since you're touching this anyway, make this const
estark
2017/05/04 04:03:24
Done.
| |
| 883 | 914 |
| 884 // FieldTrials are not supported in Native Client apps. | 915 // FieldTrials are not supported in Native Client apps. |
| 885 #if !defined(OS_NACL) | 916 #if !defined(OS_NACL) |
| 886 // Emergency escape valve; not to be activated until there's an actual | 917 // Emergency escape valve; not to be activated until there's an actual |
| 887 // emergency (e.g. a weird path-building bug due to a CA's failed | 918 // emergency (e.g. a weird path-building bug due to a CA's failed |
| 888 // disclosure of cross-signed sub-CAs). | 919 // disclosure of cross-signed sub-CAs). |
| 889 std::string group_name = | 920 std::string group_name = |
| 890 base::FieldTrialList::FindFullName("EnforceCTForProblematicRoots"); | 921 base::FieldTrialList::FindFullName("EnforceCTForProblematicRoots"); |
| 891 if (base::StartsWith(group_name, "disabled", | 922 if (base::StartsWith(group_name, "disabled", |
| 892 base::CompareCase::INSENSITIVE_ASCII)) { | 923 base::CompareCase::INSENSITIVE_ASCII)) { |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 923 if (std::binary_search( | 954 if (std::binary_search( |
| 924 restricted_ca.exceptions, | 955 restricted_ca.exceptions, |
| 925 restricted_ca.exceptions + restricted_ca.exceptions_length, | 956 restricted_ca.exceptions + restricted_ca.exceptions_length, |
| 926 sub_ca_hash, SHA256ToHashValueComparator())) { | 957 sub_ca_hash, SHA256ToHashValueComparator())) { |
| 927 // Found an excluded sub-CA; CT is not required. | 958 // Found an excluded sub-CA; CT is not required. |
| 928 return default_response; | 959 return default_response; |
| 929 } | 960 } |
| 930 } | 961 } |
| 931 | 962 |
| 932 // No exception found. This certificate must conform to the CT policy. | 963 // No exception found. This certificate must conform to the CT policy. |
| 933 return true; | 964 return true; |
|
mattm
2017/05/04 01:57:11
should that be false now? (Is there a test for thi
estark
2017/05/04 04:03:25
Oops. There was a test; I just forgot to run it. S
| |
| 934 } | 965 } |
| 935 } | 966 } |
| 936 | 967 |
| 937 return default_response; | 968 return default_response; |
| 938 } | 969 } |
| 939 | 970 |
| 940 void TransportSecurityState::SetDelegate( | 971 void TransportSecurityState::SetDelegate( |
| 941 TransportSecurityState::Delegate* delegate) { | 972 TransportSecurityState::Delegate* delegate) { |
| 942 DCHECK(CalledOnValidThread()); | 973 DCHECK(CalledOnValidThread()); |
| 943 delegate_ = delegate; | 974 delegate_ = delegate; |
| (...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1406 return; | 1437 return; |
| 1407 if (!ssl_info.is_issued_by_known_root) | 1438 if (!ssl_info.is_issued_by_known_root) |
| 1408 return; | 1439 return; |
| 1409 if (!ssl_info.ct_compliance_details_available) | 1440 if (!ssl_info.ct_compliance_details_available) |
| 1410 return; | 1441 return; |
| 1411 if (ssl_info.ct_cert_policy_compliance == | 1442 if (ssl_info.ct_cert_policy_compliance == |
| 1412 ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS) | 1443 ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS) |
| 1413 return; | 1444 return; |
| 1414 ExpectCTState state; | 1445 ExpectCTState state; |
| 1415 if (GetStaticExpectCTState(host_port_pair.host(), &state)) { | 1446 if (GetStaticExpectCTState(host_port_pair.host(), &state)) { |
| 1416 expect_ct_reporter_->OnExpectCTFailed(host_port_pair, state.report_uri, | 1447 expect_ct_reporter_->OnExpectCTFailed( |
| 1417 ssl_info); | 1448 host_port_pair, state.report_uri, ssl_info.cert.get(), |
| 1449 ssl_info.unverified_cert.get(), | |
| 1450 ssl_info.signed_certificate_timestamps); | |
| 1418 } | 1451 } |
| 1419 return; | 1452 return; |
| 1420 } | 1453 } |
| 1421 | 1454 |
| 1422 // Otherwise, see if the site has sent a valid Expect-CT header to dynamically | 1455 // Otherwise, see if the site has sent a valid Expect-CT header to dynamically |
| 1423 // turn on reporting and/or enforcement. | 1456 // turn on reporting and/or enforcement. |
| 1424 if (!IsDynamicExpectCTEnabled()) | 1457 if (!IsDynamicExpectCTEnabled()) |
| 1425 return; | 1458 return; |
| 1426 base::Time now = base::Time::Now(); | 1459 base::Time now = base::Time::Now(); |
| 1427 base::TimeDelta max_age; | 1460 base::TimeDelta max_age; |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1440 ExpectCTState state; | 1473 ExpectCTState state; |
| 1441 // If an Expect-CT header is observed over a non-compliant connection, the | 1474 // If an Expect-CT header is observed over a non-compliant connection, the |
| 1442 // site owner should be notified about the misconfiguration. If the site was | 1475 // site owner should be notified about the misconfiguration. If the site was |
| 1443 // already opted in to Expect-CT, this report would have been sent at | 1476 // already opted in to Expect-CT, this report would have been sent at |
| 1444 // connection setup time. If the host is not already a noted Expect-CT host, | 1477 // connection setup time. If the host is not already a noted Expect-CT host, |
| 1445 // however, the lack of CT compliance would not have been evaluated/reported | 1478 // however, the lack of CT compliance would not have been evaluated/reported |
| 1446 // at connection setup time, so it needs to be reported here while | 1479 // at connection setup time, so it needs to be reported here while |
| 1447 // processing the header. | 1480 // processing the header. |
| 1448 if (expect_ct_reporter_ && !report_uri.is_empty() && | 1481 if (expect_ct_reporter_ && !report_uri.is_empty() && |
| 1449 !GetDynamicExpectCTState(host_port_pair.host(), &state)) { | 1482 !GetDynamicExpectCTState(host_port_pair.host(), &state)) { |
| 1450 expect_ct_reporter_->OnExpectCTFailed(host_port_pair, report_uri, | 1483 expect_ct_reporter_->OnExpectCTFailed( |
| 1451 ssl_info); | 1484 host_port_pair, report_uri, ssl_info.cert.get(), |
| 1485 ssl_info.unverified_cert.get(), | |
| 1486 ssl_info.signed_certificate_timestamps); | |
| 1452 } | 1487 } |
| 1453 return; | 1488 return; |
| 1454 } | 1489 } |
| 1455 AddExpectCTInternal(host_port_pair.host(), now, now + max_age, enforce, | 1490 AddExpectCTInternal(host_port_pair.host(), now, now + max_age, enforce, |
| 1456 report_uri); | 1491 report_uri); |
| 1457 } | 1492 } |
| 1458 | 1493 |
| 1459 // static | 1494 // static |
| 1460 void TransportSecurityState::SetShouldRequireCTForTesting(bool* required) { | 1495 void TransportSecurityState::SetShouldRequireCTForTesting(bool* required) { |
| 1461 if (!required) { | 1496 if (!required) { |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1790 TransportSecurityState::PKPStateIterator::PKPStateIterator( | 1825 TransportSecurityState::PKPStateIterator::PKPStateIterator( |
| 1791 const TransportSecurityState& state) | 1826 const TransportSecurityState& state) |
| 1792 : iterator_(state.enabled_pkp_hosts_.begin()), | 1827 : iterator_(state.enabled_pkp_hosts_.begin()), |
| 1793 end_(state.enabled_pkp_hosts_.end()) { | 1828 end_(state.enabled_pkp_hosts_.end()) { |
| 1794 } | 1829 } |
| 1795 | 1830 |
| 1796 TransportSecurityState::PKPStateIterator::~PKPStateIterator() { | 1831 TransportSecurityState::PKPStateIterator::~PKPStateIterator() { |
| 1797 } | 1832 } |
| 1798 | 1833 |
| 1799 } // namespace | 1834 } // namespace |
| OLD | NEW |