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 25 matching lines...) Expand all Loading... |
36 #include "base/metrics/field_trial.h" | 36 #include "base/metrics/field_trial.h" |
37 #endif | 37 #endif |
38 | 38 |
39 namespace net { | 39 namespace net { |
40 | 40 |
41 namespace { | 41 namespace { |
42 | 42 |
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 // Parameters for remembering sent HPKP and Expect-CT reports. |
47 const int kTimeToRememberHPKPReportsMins = 60; | 47 const size_t kMaxReportCacheEntries = 50; |
| 48 const int kTimeToRememberReportsMins = 60; |
48 const size_t kReportCacheKeyLength = 16; | 49 const size_t kReportCacheKeyLength = 16; |
49 | 50 |
50 // Points to the active transport security state source. | 51 // Points to the active transport security state source. |
51 const TransportSecurityStateSource* g_hsts_source = &kHSTSSource; | 52 const TransportSecurityStateSource* g_hsts_source = &kHSTSSource; |
52 | 53 |
53 // Override for CheckCTRequirements() for unit tests. Possible values: | 54 // Override for CheckCTRequirements() for unit tests. Possible values: |
54 // -1: Unless a delegate says otherwise, do not require CT. | 55 // -1: Unless a delegate says otherwise, do not require CT. |
55 // 0: Use the default implementation (e.g. production) | 56 // 0: Use the default implementation (e.g. production) |
56 // 1: Unless a delegate says otherwise, require CT. | 57 // 1: Unless a delegate says otherwise, require CT. |
57 int g_ct_required_for_testing = 0; | 58 int g_ct_required_for_testing = 0; |
(...skipping 677 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
735 void SetTransportSecurityStateSourceForTesting( | 736 void SetTransportSecurityStateSourceForTesting( |
736 const TransportSecurityStateSource* source) { | 737 const TransportSecurityStateSource* source) { |
737 g_hsts_source = source ? source : &kHSTSSource; | 738 g_hsts_source = source ? source : &kHSTSSource; |
738 } | 739 } |
739 | 740 |
740 TransportSecurityState::TransportSecurityState() | 741 TransportSecurityState::TransportSecurityState() |
741 : enable_static_pins_(true), | 742 : enable_static_pins_(true), |
742 enable_static_expect_ct_(true), | 743 enable_static_expect_ct_(true), |
743 enable_static_expect_staple_(true), | 744 enable_static_expect_staple_(true), |
744 enable_pkp_bypass_for_local_trust_anchors_(true), | 745 enable_pkp_bypass_for_local_trust_anchors_(true), |
745 sent_reports_cache_(kMaxHPKPReportCacheEntries) { | 746 sent_hpkp_reports_cache_(kMaxReportCacheEntries), |
| 747 sent_expect_ct_reports_cache_(kMaxReportCacheEntries) { |
746 // Static pinning is only enabled for official builds to make sure that | 748 // Static pinning is only enabled for official builds to make sure that |
747 // others don't end up with pins that cannot be easily updated. | 749 // others don't end up with pins that cannot be easily updated. |
748 #if !defined(GOOGLE_CHROME_BUILD) || defined(OS_ANDROID) || defined(OS_IOS) | 750 #if !defined(GOOGLE_CHROME_BUILD) || defined(OS_ANDROID) || defined(OS_IOS) |
749 enable_static_pins_ = false; | 751 enable_static_pins_ = false; |
750 enable_static_expect_ct_ = false; | 752 enable_static_expect_ct_ = false; |
751 #endif | 753 #endif |
752 DCHECK(CalledOnValidThread()); | 754 DCHECK(CalledOnValidThread()); |
753 } | 755 } |
754 | 756 |
755 // Both HSTS and HPKP cause fatal SSL errors, so return true if a | 757 // Both HSTS and HPKP cause fatal SSL errors, so return true if a |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
883 return CT_REQUIREMENTS_MET; | 885 return CT_REQUIREMENTS_MET; |
884 } | 886 } |
885 | 887 |
886 // Check Expect-CT first so that other CT requirements do not prevent | 888 // Check Expect-CT first so that other CT requirements do not prevent |
887 // Expect-CT reports from being sent. | 889 // Expect-CT reports from being sent. |
888 ExpectCTState state; | 890 ExpectCTState state; |
889 if (is_issued_by_known_root && IsDynamicExpectCTEnabled() && | 891 if (is_issued_by_known_root && IsDynamicExpectCTEnabled() && |
890 GetDynamicExpectCTState(hostname, &state)) { | 892 GetDynamicExpectCTState(hostname, &state)) { |
891 if (expect_ct_reporter_ && !state.report_uri.is_empty() && | 893 if (expect_ct_reporter_ && !state.report_uri.is_empty() && |
892 report_status == ENABLE_EXPECT_CT_REPORTS) { | 894 report_status == ENABLE_EXPECT_CT_REPORTS) { |
893 expect_ct_reporter_->OnExpectCTFailed( | 895 MaybeNotifyExpectCTFailed( |
894 host_port_pair, state.report_uri, validated_certificate_chain, | 896 host_port_pair, state.report_uri, validated_certificate_chain, |
895 served_certificate_chain, signed_certificate_timestamps); | 897 served_certificate_chain, signed_certificate_timestamps); |
896 } | 898 } |
897 if (state.enforce) | 899 if (state.enforce) |
898 return CT_REQUIREMENTS_NOT_MET; | 900 return CT_REQUIREMENTS_NOT_MET; |
899 } | 901 } |
900 | 902 |
901 CTRequirementLevel ct_required = CTRequirementLevel::DEFAULT; | 903 CTRequirementLevel ct_required = CTRequirementLevel::DEFAULT; |
902 if (require_ct_delegate_) | 904 if (require_ct_delegate_) |
903 ct_required = require_ct_delegate_->IsCTRequiredForHost(hostname); | 905 ct_required = require_ct_delegate_->IsCTRequiredForHost(hostname); |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1160 std::string serialized_report; | 1162 std::string serialized_report; |
1161 std::string report_cache_key; | 1163 std::string report_cache_key; |
1162 if (!GetHPKPReport(host_port_pair, pkp_state, served_certificate_chain, | 1164 if (!GetHPKPReport(host_port_pair, pkp_state, served_certificate_chain, |
1163 validated_certificate_chain, &serialized_report, | 1165 validated_certificate_chain, &serialized_report, |
1164 &report_cache_key)) { | 1166 &report_cache_key)) { |
1165 return PKPStatus::VIOLATED; | 1167 return PKPStatus::VIOLATED; |
1166 } | 1168 } |
1167 | 1169 |
1168 // Limit the rate at which duplicate reports are sent to the same | 1170 // Limit the rate at which duplicate reports are sent to the same |
1169 // report URI. The same report will not be sent within | 1171 // report URI. The same report will not be sent within |
1170 // |kTimeToRememberHPKPReportsMins|, which reduces load on servers and | 1172 // |kTimeToRememberReportsMins|, which reduces load on servers and |
1171 // also prevents accidental loops (a.com triggers a report to b.com | 1173 // also prevents accidental loops (a.com triggers a report to b.com |
1172 // which triggers a report to a.com). See section 2.1.4 of RFC 7469. | 1174 // which triggers a report to a.com). See section 2.1.4 of RFC 7469. |
1173 if (sent_reports_cache_.Get(report_cache_key, base::TimeTicks::Now())) | 1175 if (sent_hpkp_reports_cache_.Get(report_cache_key, base::TimeTicks::Now())) |
1174 return PKPStatus::VIOLATED; | 1176 return PKPStatus::VIOLATED; |
1175 sent_reports_cache_.Put( | 1177 sent_hpkp_reports_cache_.Put( |
1176 report_cache_key, true, base::TimeTicks::Now(), | 1178 report_cache_key, true, base::TimeTicks::Now(), |
1177 base::TimeTicks::Now() + | 1179 base::TimeTicks::Now() + |
1178 base::TimeDelta::FromMinutes(kTimeToRememberHPKPReportsMins)); | 1180 base::TimeDelta::FromMinutes(kTimeToRememberReportsMins)); |
1179 | 1181 |
1180 report_sender_->Send(pkp_state.report_uri, "application/json; charset=utf-8", | 1182 report_sender_->Send(pkp_state.report_uri, "application/json; charset=utf-8", |
1181 serialized_report, base::Callback<void()>(), | 1183 serialized_report, base::Callback<void()>(), |
1182 base::Bind(RecordUMAForHPKPReportFailure)); | 1184 base::Bind(RecordUMAForHPKPReportFailure)); |
1183 return PKPStatus::VIOLATED; | 1185 return PKPStatus::VIOLATED; |
1184 } | 1186 } |
1185 | 1187 |
1186 bool TransportSecurityState::GetStaticExpectCTState( | 1188 bool TransportSecurityState::GetStaticExpectCTState( |
1187 const std::string& host, | 1189 const std::string& host, |
1188 ExpectCTState* expect_ct_state) const { | 1190 ExpectCTState* expect_ct_state) const { |
1189 DCHECK(CalledOnValidThread()); | 1191 DCHECK(CalledOnValidThread()); |
1190 | 1192 |
1191 if (!IsBuildTimely()) | 1193 if (!IsBuildTimely()) |
1192 return false; | 1194 return false; |
1193 | 1195 |
1194 PreloadResult result; | 1196 PreloadResult result; |
1195 if (!DecodeHSTSPreload(host, &result)) | 1197 if (!DecodeHSTSPreload(host, &result)) |
1196 return false; | 1198 return false; |
1197 | 1199 |
1198 if (!enable_static_expect_ct_ || !result.expect_ct) | 1200 if (!enable_static_expect_ct_ || !result.expect_ct) |
1199 return false; | 1201 return false; |
1200 | 1202 |
1201 expect_ct_state->domain = host.substr(result.hostname_offset); | 1203 expect_ct_state->domain = host.substr(result.hostname_offset); |
1202 expect_ct_state->report_uri = GURL( | 1204 expect_ct_state->report_uri = GURL( |
1203 g_hsts_source->expect_ct_report_uris[result.expect_ct_report_uri_id]); | 1205 g_hsts_source->expect_ct_report_uris[result.expect_ct_report_uri_id]); |
1204 return true; | 1206 return true; |
1205 } | 1207 } |
1206 | 1208 |
| 1209 void TransportSecurityState::MaybeNotifyExpectCTFailed( |
| 1210 const HostPortPair& host_port_pair, |
| 1211 const GURL& report_uri, |
| 1212 const X509Certificate* validated_certificate_chain, |
| 1213 const X509Certificate* served_certificate_chain, |
| 1214 const SignedCertificateTimestampAndStatusList& |
| 1215 signed_certificate_timestamps) { |
| 1216 // Do not send repeated reports to the same host/port pair within |
| 1217 // |kTimeToRememberReportsMins|. Theoretically, there could be scenarios in |
| 1218 // which the same host/port generates different reports and it would be useful |
| 1219 // to the server operator to receive those different reports, but such |
| 1220 // scenarios are not expected to arise very often in practice. |
| 1221 const std::string report_cache_key(host_port_pair.ToString()); |
| 1222 if (sent_expect_ct_reports_cache_.Get(report_cache_key, |
| 1223 base::TimeTicks::Now())) { |
| 1224 return; |
| 1225 } |
| 1226 sent_expect_ct_reports_cache_.Put( |
| 1227 report_cache_key, true, base::TimeTicks::Now(), |
| 1228 base::TimeTicks::Now() + |
| 1229 base::TimeDelta::FromMinutes(kTimeToRememberReportsMins)); |
| 1230 |
| 1231 expect_ct_reporter_->OnExpectCTFailed( |
| 1232 host_port_pair, report_uri, validated_certificate_chain, |
| 1233 served_certificate_chain, signed_certificate_timestamps); |
| 1234 } |
| 1235 |
1207 bool TransportSecurityState::GetStaticExpectStapleState( | 1236 bool TransportSecurityState::GetStaticExpectStapleState( |
1208 const std::string& host, | 1237 const std::string& host, |
1209 ExpectStapleState* expect_staple_state) const { | 1238 ExpectStapleState* expect_staple_state) const { |
1210 DCHECK(CalledOnValidThread()); | 1239 DCHECK(CalledOnValidThread()); |
1211 | 1240 |
1212 if (!IsBuildTimely()) | 1241 if (!IsBuildTimely()) |
1213 return false; | 1242 return false; |
1214 | 1243 |
1215 PreloadResult result; | 1244 PreloadResult result; |
1216 if (!DecodeHSTSPreload(host, &result)) | 1245 if (!DecodeHSTSPreload(host, &result)) |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1441 return; | 1470 return; |
1442 if (!ssl_info.is_issued_by_known_root) | 1471 if (!ssl_info.is_issued_by_known_root) |
1443 return; | 1472 return; |
1444 if (!ssl_info.ct_compliance_details_available) | 1473 if (!ssl_info.ct_compliance_details_available) |
1445 return; | 1474 return; |
1446 if (ssl_info.ct_cert_policy_compliance == | 1475 if (ssl_info.ct_cert_policy_compliance == |
1447 ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS) | 1476 ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS) |
1448 return; | 1477 return; |
1449 ExpectCTState state; | 1478 ExpectCTState state; |
1450 if (GetStaticExpectCTState(host_port_pair.host(), &state)) { | 1479 if (GetStaticExpectCTState(host_port_pair.host(), &state)) { |
1451 expect_ct_reporter_->OnExpectCTFailed( | 1480 MaybeNotifyExpectCTFailed(host_port_pair, state.report_uri, |
1452 host_port_pair, state.report_uri, ssl_info.cert.get(), | 1481 ssl_info.cert.get(), |
1453 ssl_info.unverified_cert.get(), | 1482 ssl_info.unverified_cert.get(), |
1454 ssl_info.signed_certificate_timestamps); | 1483 ssl_info.signed_certificate_timestamps); |
1455 } | 1484 } |
1456 return; | 1485 return; |
1457 } | 1486 } |
1458 | 1487 |
1459 // Otherwise, see if the site has sent a valid Expect-CT header to dynamically | 1488 // Otherwise, see if the site has sent a valid Expect-CT header to dynamically |
1460 // turn on reporting and/or enforcement. | 1489 // turn on reporting and/or enforcement. |
1461 if (!IsDynamicExpectCTEnabled()) | 1490 if (!IsDynamicExpectCTEnabled()) |
1462 return; | 1491 return; |
1463 base::Time now = base::Time::Now(); | 1492 base::Time now = base::Time::Now(); |
1464 base::TimeDelta max_age; | 1493 base::TimeDelta max_age; |
(...skipping 12 matching lines...) Expand all Loading... |
1477 ExpectCTState state; | 1506 ExpectCTState state; |
1478 // If an Expect-CT header is observed over a non-compliant connection, the | 1507 // If an Expect-CT header is observed over a non-compliant connection, the |
1479 // site owner should be notified about the misconfiguration. If the site was | 1508 // site owner should be notified about the misconfiguration. If the site was |
1480 // already opted in to Expect-CT, this report would have been sent at | 1509 // already opted in to Expect-CT, this report would have been sent at |
1481 // connection setup time. If the host is not already a noted Expect-CT host, | 1510 // connection setup time. If the host is not already a noted Expect-CT host, |
1482 // however, the lack of CT compliance would not have been evaluated/reported | 1511 // however, the lack of CT compliance would not have been evaluated/reported |
1483 // at connection setup time, so it needs to be reported here while | 1512 // at connection setup time, so it needs to be reported here while |
1484 // processing the header. | 1513 // processing the header. |
1485 if (expect_ct_reporter_ && !report_uri.is_empty() && | 1514 if (expect_ct_reporter_ && !report_uri.is_empty() && |
1486 !GetDynamicExpectCTState(host_port_pair.host(), &state)) { | 1515 !GetDynamicExpectCTState(host_port_pair.host(), &state)) { |
1487 expect_ct_reporter_->OnExpectCTFailed( | 1516 MaybeNotifyExpectCTFailed(host_port_pair, report_uri, ssl_info.cert.get(), |
1488 host_port_pair, report_uri, ssl_info.cert.get(), | 1517 ssl_info.unverified_cert.get(), |
1489 ssl_info.unverified_cert.get(), | 1518 ssl_info.signed_certificate_timestamps); |
1490 ssl_info.signed_certificate_timestamps); | |
1491 } | 1519 } |
1492 return; | 1520 return; |
1493 } | 1521 } |
1494 AddExpectCTInternal(host_port_pair.host(), now, now + max_age, enforce, | 1522 AddExpectCTInternal(host_port_pair.host(), now, now + max_age, enforce, |
1495 report_uri); | 1523 report_uri); |
1496 } | 1524 } |
1497 | 1525 |
1498 // static | 1526 // static |
1499 void TransportSecurityState::SetShouldRequireCTForTesting(bool* required) { | 1527 void TransportSecurityState::SetShouldRequireCTForTesting(bool* required) { |
1500 if (!required) { | 1528 if (!required) { |
1501 g_ct_required_for_testing = 0; | 1529 g_ct_required_for_testing = 0; |
1502 return; | 1530 return; |
1503 } | 1531 } |
1504 g_ct_required_for_testing = *required ? 1 : -1; | 1532 g_ct_required_for_testing = *required ? 1 : -1; |
1505 } | 1533 } |
1506 | 1534 |
| 1535 void TransportSecurityState::ClearReportCachesForTesting() { |
| 1536 sent_hpkp_reports_cache_.Clear(); |
| 1537 sent_expect_ct_reports_cache_.Clear(); |
| 1538 } |
| 1539 |
1507 // static | 1540 // static |
1508 bool TransportSecurityState::IsBuildTimely() { | 1541 bool TransportSecurityState::IsBuildTimely() { |
1509 const base::Time build_time = base::GetBuildTime(); | 1542 const base::Time build_time = base::GetBuildTime(); |
1510 // We consider built-in information to be timely for 10 weeks. | 1543 // We consider built-in information to be timely for 10 weeks. |
1511 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; | 1544 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; |
1512 } | 1545 } |
1513 | 1546 |
1514 TransportSecurityState::PKPStatus | 1547 TransportSecurityState::PKPStatus |
1515 TransportSecurityState::CheckPublicKeyPinsImpl( | 1548 TransportSecurityState::CheckPublicKeyPinsImpl( |
1516 const HostPortPair& host_port_pair, | 1549 const HostPortPair& host_port_pair, |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1829 TransportSecurityState::PKPStateIterator::PKPStateIterator( | 1862 TransportSecurityState::PKPStateIterator::PKPStateIterator( |
1830 const TransportSecurityState& state) | 1863 const TransportSecurityState& state) |
1831 : iterator_(state.enabled_pkp_hosts_.begin()), | 1864 : iterator_(state.enabled_pkp_hosts_.begin()), |
1832 end_(state.enabled_pkp_hosts_.end()) { | 1865 end_(state.enabled_pkp_hosts_.end()) { |
1833 } | 1866 } |
1834 | 1867 |
1835 TransportSecurityState::PKPStateIterator::~PKPStateIterator() { | 1868 TransportSecurityState::PKPStateIterator::~PKPStateIterator() { |
1836 } | 1869 } |
1837 | 1870 |
1838 } // namespace | 1871 } // namespace |
OLD | NEW |