Index: net/http/transport_security_state.cc |
diff --git a/net/http/transport_security_state.cc b/net/http/transport_security_state.cc |
index fc698b8e7a506d2969b9ffa739d6876b6d29e400..3e8d1b175f373ddd3c19a19fe27e5544cd8b3fb1 100644 |
--- a/net/http/transport_security_state.cc |
+++ b/net/http/transport_security_state.cc |
@@ -637,6 +637,80 @@ bool DecodeHSTSPreload(const std::string& hostname, PreloadResult* out) { |
return found; |
} |
+// Serializes an OCSPVerifyResult::ResponseStatus to a string enum, suitable for |
+// the |response-status| field in an Expect-Staple report. |
+std::string SerializeExpectStapleResponseStatus( |
+ OCSPVerifyResult::ResponseStatus status) { |
+ switch (status) { |
+ case OCSPVerifyResult::MISSING: |
+ return "MISSING"; |
+ case OCSPVerifyResult::PROVIDED: |
+ return "PROVIDED"; |
+ case OCSPVerifyResult::ERROR_RESPONSE: |
+ return "ERROR_RESPONSE"; |
+ case OCSPVerifyResult::BAD_PRODUCED_AT: |
+ return "BAD_PRODUCED_AT"; |
+ case OCSPVerifyResult::NO_MATCHING_RESPONSE: |
+ return "NO_MATCHING_RESPONSE"; |
+ case OCSPVerifyResult::INVALID_DATE: |
+ return "INVALID_DATE"; |
+ case OCSPVerifyResult::PARSE_RESPONSE_ERROR: |
+ return "PARSE_RESPONSE_ERROR"; |
+ case OCSPVerifyResult::PARSE_RESPONSE_DATA_ERROR: |
+ return "PARSE_RESPONSE_DATA_ERROR"; |
+ } |
+ return std::string(); |
+} |
+ |
+// Serializes an OCSPRevocationStatus to a string enum, suitable for the |
+// |cert-status| field in an Expect-Staple report. |
+std::string SerializeExpectStapleRevocationStatus( |
+ const OCSPRevocationStatus& status) { |
+ switch (status) { |
+ case OCSPRevocationStatus::GOOD: |
+ return "GOOD"; |
+ case OCSPRevocationStatus::REVOKED: |
+ return "REVOKED"; |
+ case OCSPRevocationStatus::UNKNOWN: |
+ return "UNKNOWN"; |
+ } |
+ return std::string(); |
+} |
+ |
+bool SerializeExpectStapleReport(const HostPortPair& host_port_pair, |
+ const SSLInfo& ssl_info, |
+ const std::string& ocsp_response, |
+ std::string* out_serialized_report) { |
+ base::DictionaryValue report; |
+ report.SetString("date-time", TimeToISO8601(base::Time::Now())); |
+ report.SetString("hostname", host_port_pair.host()); |
+ report.SetInteger("port", host_port_pair.port()); |
+ report.SetString("response-status", |
+ SerializeExpectStapleResponseStatus( |
+ ssl_info.ocsp_result.response_status)); |
+ |
+ if (!ocsp_response.empty()) { |
+ std::string encoded_ocsp_response; |
+ base::Base64Encode(ocsp_response, &encoded_ocsp_response); |
+ report.SetString("ocsp-response", encoded_ocsp_response); |
+ } |
+ if (ssl_info.ocsp_result.response_status == OCSPVerifyResult::PROVIDED) { |
+ report.SetString("cert-status", |
+ SerializeExpectStapleRevocationStatus( |
+ ssl_info.ocsp_result.revocation_status)); |
+ } |
+ if (ssl_info.is_issued_by_known_root) { |
+ report.Set("served-certificate-chain", |
+ GetPEMEncodedChainAsList(ssl_info.unverified_cert.get())); |
+ report.Set("validated-certificate-chain", |
+ GetPEMEncodedChainAsList(ssl_info.cert.get())); |
+ } |
+ |
+ if (!base::JSONWriter::Write(report, out_serialized_report)) |
+ return false; |
+ return true; |
+} |
+ |
} // namespace |
TransportSecurityState::TransportSecurityState() |
@@ -713,6 +787,35 @@ TransportSecurityState::PKPStatus TransportSecurityState::CheckPublicKeyPins( |
return pin_validity; |
} |
+void TransportSecurityState::CheckExpectStaple( |
+ const HostPortPair& host_port_pair, |
+ const SSLInfo& ssl_info, |
+ const std::string& ocsp_response) { |
+ DCHECK(CalledOnValidThread()); |
+ if (!enable_static_expect_staple_ || !report_sender_) |
+ return; |
+ |
+ // Determine if the host is on the Expect-Staple preload list. If the build is |
+ // not timely (i.e. the preload list is not fresh), this will fail and return |
+ // false. |
+ ExpectStapleState expect_staple_state; |
+ if (!GetStaticExpectStapleState(host_port_pair.host(), &expect_staple_state)) |
+ return; |
+ |
+ // No report needed if a stapled OCSP response was provided. |
+ if (ssl_info.ocsp_result.response_status == OCSPVerifyResult::PROVIDED && |
+ ssl_info.ocsp_result.revocation_status == OCSPRevocationStatus::GOOD) { |
+ return; |
+ } |
+ |
+ std::string serialized_report; |
+ if (!SerializeExpectStapleReport(host_port_pair, ssl_info, ocsp_response, |
+ &serialized_report)) { |
+ return; |
+ } |
+ report_sender_->Send(expect_staple_state.report_uri, serialized_report); |
+} |
+ |
bool TransportSecurityState::HasPublicKeyPins(const std::string& host) { |
PKPState dynamic_state; |
if (GetDynamicPKPState(host, &dynamic_state)) |