Chromium Code Reviews| 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 |