Index: net/http/transport_security_state.cc |
diff --git a/net/http/transport_security_state.cc b/net/http/transport_security_state.cc |
index 2a9bbba73165ea5988e11e5cb2b7b1a2aab4cbf9..5a5257d5e2f3c525981bd684bd242de08581a2bb 100644 |
--- a/net/http/transport_security_state.cc |
+++ b/net/http/transport_security_state.cc |
@@ -1379,59 +1379,64 @@ void TransportSecurityState::ProcessExpectCTHeader( |
const SSLInfo& ssl_info) { |
DCHECK(CalledOnValidThread()); |
- // Records the result of processing an Expect-CT header. This enum is |
- // histogrammed, so do not reorder or remove values. |
- enum ExpectCTHeaderResult { |
- // An Expect-CT header was received, but it had the wrong value. |
- EXPECT_CT_HEADER_BAD_VALUE = 0, |
- // The Expect-CT header was ignored because the build was old. |
- EXPECT_CT_HEADER_BUILD_NOT_TIMELY = 1, |
- // The Expect-CT header was ignored because the certificate did not chain to |
- // a public root. |
- EXPECT_CT_HEADER_PRIVATE_ROOT = 2, |
- // The Expect-CT header was ignored because CT compliance details were |
- // unavailable. |
- EXPECT_CT_HEADER_COMPLIANCE_DETAILS_UNAVAILABLE = 3, |
- // The request satisified the Expect-CT compliance policy, so no action was |
- // taken. |
- EXPECT_CT_HEADER_COMPLIED = 4, |
- // The Expect-CT header was ignored because there was no corresponding |
- // preload list entry. |
- EXPECT_CT_HEADER_NOT_PRELOADED = 5, |
- // The Expect-CT header was processed successfully and passed on to the |
- // delegate to send a report. |
- EXPECT_CT_HEADER_PROCESSED = 6, |
- EXPECT_CT_HEADER_LAST = EXPECT_CT_HEADER_PROCESSED |
- }; |
- |
- ExpectCTHeaderResult result = EXPECT_CT_HEADER_PROCESSED; |
- |
- if (!expect_ct_reporter_) |
+ // If a site sends `Expect-CT: preload` and appears on the preload list, they |
+ // are in the experimental preload-list-only, report-only version of |
+ // Expect-CT. |
+ if (value == "preload") { |
+ if (!expect_ct_reporter_) |
+ return; |
+ if (!IsBuildTimely()) |
+ return; |
+ if (!ssl_info.is_issued_by_known_root) |
+ return; |
+ if (!ssl_info.ct_compliance_details_available) |
+ return; |
+ if (ssl_info.ct_cert_policy_compliance == |
+ ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS) |
+ return; |
+ ExpectCTState state; |
+ if (GetStaticExpectCTState(host_port_pair.host(), &state)) { |
+ expect_ct_reporter_->OnExpectCTFailed(host_port_pair, state.report_uri, |
+ ssl_info); |
+ } |
return; |
- |
- ExpectCTState state; |
- if (value != "preload") { |
- result = EXPECT_CT_HEADER_BAD_VALUE; |
- } else if (!IsBuildTimely()) { |
- result = EXPECT_CT_HEADER_BUILD_NOT_TIMELY; |
- } else if (!ssl_info.is_issued_by_known_root) { |
- result = EXPECT_CT_HEADER_PRIVATE_ROOT; |
- } else if (!ssl_info.ct_compliance_details_available) { |
- result = EXPECT_CT_HEADER_COMPLIANCE_DETAILS_UNAVAILABLE; |
- } else if (ssl_info.ct_cert_policy_compliance == |
- ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS) { |
- result = EXPECT_CT_HEADER_COMPLIED; |
- } else if (!GetStaticExpectCTState(host_port_pair.host(), &state)) { |
- result = EXPECT_CT_HEADER_NOT_PRELOADED; |
} |
- UMA_HISTOGRAM_ENUMERATION("Net.ExpectCTHeaderResult", result, |
- EXPECT_CT_HEADER_LAST + 1); |
- if (result != EXPECT_CT_HEADER_PROCESSED) |
+ // Otherwise, see if the site has sent a valid Expect-CT header to dynamically |
+ // turn on reporting and/or enforcement. |
+ if (!IsDynamicExpectCTEnabled()) |
return; |
- |
- expect_ct_reporter_->OnExpectCTFailed(host_port_pair, state.report_uri, |
- ssl_info); |
+ base::Time now = base::Time::Now(); |
+ base::TimeDelta max_age; |
+ bool enforce; |
+ GURL report_uri; |
+ if (!ParseExpectCTHeader(value, &max_age, &enforce, &report_uri)) |
+ return; |
+ // Do not persist Expect-CT headers if the connection was not chained to a |
+ // public root or did not comply with CT policy. |
+ if (!ssl_info.is_issued_by_known_root) |
+ return; |
+ if (!ssl_info.ct_compliance_details_available) |
+ return; |
+ if (ssl_info.ct_cert_policy_compliance != |
+ ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS) { |
+ ExpectCTState state; |
+ // If an Expect-CT header is observed over a non-compliant connection, the |
+ // site owner should be notified about the misconfiguration. If the site was |
+ // already opted in to Expect-CT, this report would have been sent at |
+ // connection setup time. If the host is not already a noted Expect-CT host, |
+ // however, the lack of CT compliance would not have been evaluated/reported |
+ // at connection setup time, so it needs to be reported here while |
+ // processing the header. |
+ if (expect_ct_reporter_ && !report_uri.is_empty() && |
+ !GetDynamicExpectCTState(host_port_pair.host(), &state)) { |
+ expect_ct_reporter_->OnExpectCTFailed(host_port_pair, report_uri, |
+ ssl_info); |
+ } |
+ return; |
+ } |
+ AddExpectCTInternal(host_port_pair.host(), now, now + max_age, enforce, |
+ report_uri); |
} |
// static |