Index: net/http/transport_security_reporter.cc |
diff --git a/net/http/transport_security_reporter.cc b/net/http/transport_security_reporter.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..9bb15c4a740c8945624e1586a06800921b284315 |
--- /dev/null |
+++ b/net/http/transport_security_reporter.cc |
@@ -0,0 +1,122 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "net/http/transport_security_reporter.h" |
+ |
+#include "base/base64.h" |
+#include "base/json/json_writer.h" |
+#include "base/strings/string_number_conversions.h" |
+#include "base/strings/string_util.h" |
+#include "base/time/time.h" |
+#include "base/values.h" |
+#include "net/ssl/ssl_info.h" |
+#include "net/url_request/url_request_context.h" |
+#include "url/gurl.h" |
+ |
+namespace { |
+ |
+scoped_ptr<base::ListValue> GetPEMEncodedChainAsList( |
+ const net::X509Certificate* cert_chain) { |
+ if (!cert_chain) |
+ return scoped_ptr<base::ListValue>(new base::ListValue()); |
davidben
2015/07/22 21:36:42
You can also write
return make_scoped_ptr(new ba
estark
2015/07/23 00:03:57
Done.
|
+ |
+ scoped_ptr<base::ListValue> result(new base::ListValue()); |
+ std::vector<std::string> pem_encoded_chain; |
+ cert_chain->GetPEMEncodedChain(&pem_encoded_chain); |
+ for (std::string cert : pem_encoded_chain) |
davidben
2015/07/22 21:36:42
std::string -> const std::string&
estark
2015/07/23 00:03:57
Done.
|
+ result->Append(scoped_ptr<base::Value>(new base::StringValue(cert))); |
davidben
2015/07/22 21:36:42
I think make_scoped_ptr will work here too.
estark
2015/07/23 00:03:57
Done.
|
+ |
+ return result.Pass(); |
+} |
+ |
+} // namespace |
+ |
+namespace net { |
+ |
+TransportSecurityReporter::TransportSecurityReporter( |
+ TransportSecurityState* state, |
+ scoped_ptr<CertificateReportSender> report_sender) |
+ : transport_security_state_(state), report_sender_(report_sender.Pass()) { |
+ transport_security_state_->SetReporter(this); |
+} |
+ |
+TransportSecurityReporter::~TransportSecurityReporter() { |
+ transport_security_state_->SetReporter(nullptr); |
+} |
+ |
+bool TransportSecurityReporter::GetHPKPReport( |
+ const std::string& hostname, |
+ const TransportSecurityState::PKPState& pkp_state, |
+ bool is_static_pin, |
+ uint16_t port, |
+ const X509Certificate* served_certificate_chain, |
+ const X509Certificate* validated_certificate_chain, |
+ GURL* report_uri, |
+ std::string* serialized_report) { |
+ // TODO(estark): keep track of reports already sent and rate-limit, |
+ // break loops |
+ if (pkp_state.report_uri.is_empty()) |
+ return false; |
+ |
+ base::DictionaryValue report; |
+ base::Time now = base::Time::Now(); |
+ // TODO(estark): write times in RFC3339 format. |
+ report.SetString("date-time", base::Int64ToString(now.ToInternalValue())); |
davidben
2015/07/22 21:36:42
Here, you can just nab this code:
https://code.goo
estark
2015/07/23 00:03:57
Done. (I just copied and pasted it -- not sure if
|
+ report.SetString("hostname", hostname); |
+ report.SetInteger("port", port); |
+ report.SetString("effective-expiration-date", |
+ base::Int64ToString(pkp_state.expiry.ToInternalValue())); |
+ report.SetBoolean("include-subdomains", pkp_state.include_subdomains); |
+ report.SetString("noted-hostname", pkp_state.domain); |
+ |
+ scoped_ptr<base::ListValue> served_certificate_chain_list = |
+ GetPEMEncodedChainAsList(served_certificate_chain); |
+ scoped_ptr<base::ListValue> validated_certificate_chain_list = |
+ GetPEMEncodedChainAsList(validated_certificate_chain); |
+ report.Set("served-certificate-chain", served_certificate_chain_list.Pass()); |
+ report.Set("validated-certificate-chain", |
+ validated_certificate_chain_list.Pass()); |
+ |
+ scoped_ptr<base::ListValue> knownPinList(new base::ListValue()); |
+ for (const auto& hash_value : pkp_state.spki_hashes) { |
+ std::string known_pin; |
+ |
+ switch (hash_value.tag) { |
+ case HASH_VALUE_SHA1: |
+ known_pin += "pin-sha1="; |
+ break; |
+ case HASH_VALUE_SHA256: |
+ known_pin += "pin-sha256="; |
+ break; |
+ default: |
+ NOTREACHED(); |
davidben
2015/07/22 21:36:43
Probably also want a
return false;
(Or perhaps
estark
2015/07/23 00:03:57
Done (the latter).
|
+ } |
+ |
+ std::string base64_value; |
+ base::Base64Encode( |
+ base::StringPiece(reinterpret_cast<const char*>(hash_value.data()), |
+ hash_value.size()), |
+ &base64_value); |
+ known_pin += "\"" + base64_value + "\""; |
+ |
+ knownPinList->Append( |
+ scoped_ptr<base::Value>(new base::StringValue(known_pin))); |
+ } |
+ |
+ report.Set("known-pins", knownPinList.Pass()); |
+ |
+ if (!base::JSONWriter::Write(report, serialized_report)) { |
+ LOG(ERROR) << "Failed to serialize HPKP violation report."; |
+ return false; |
+ } |
+ |
+ *report_uri = pkp_state.report_uri; |
+ return true; |
+} |
+ |
+void TransportSecurityReporter::SendHPKPReport(const GURL& report_uri, |
+ const std::string& report) { |
+ report_sender_->Send(report_uri, report); |
+} |
+} // namespace net |