Allow preloaded pins to contain report URIs; remove special-case reporting
This CL processes report URIs in preloaded pins and removes special-case code
for reporting pin violations on Google properties
(FraudulentCertificateReporter and its implementation
ChromeFraudulentCertificateReporter), in favor of a preloaded report
URI.
BUG=445793
Review URL: https://codereview.chromium.org/1267383002
Cr-Original-Commit-Position: refs/heads/master@{#342967}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: db949c345a8c561f45a2351daa06dc9c85671e88
diff --git a/http/transport_security_state.cc b/http/transport_security_state.cc
index 4db4696..724235b 100644
--- a/http/transport_security_state.cc
+++ b/http/transport_security_state.cc
@@ -1032,6 +1032,9 @@
return false;
const Pinset *pinset = &kPinsets[result.pinset_id];
+ if (pinset->report_uri != kNoReportURI)
+ pkp_state->report_uri = GURL(pinset->report_uri);
+
if (pinset->accepted_pins) {
const char* const* sha1_hash = pinset->accepted_pins;
while (*sha1_hash) {
diff --git a/http/transport_security_state_static.h b/http/transport_security_state_static.h
index 0a06a03..40ba72e 100644
--- a/http/transport_security_state_static.h
+++ b/http/transport_security_state_static.h
@@ -551,6 +551,7 @@
kSPKIHash_GeoTrustGlobal,
NULL,
};
+static const char kGoogleReportURI[] = "http://clients3.google.com/cert_upload_json";
static const char* const kTorAcceptableCerts[] = {
kSPKIHash_RapidSSL,
kSPKIHash_DigiCertEVRoot,
@@ -674,7 +675,7 @@
static const struct Pinset kPinsets[] = {
{kTestAcceptableCerts, kNoRejectedPublicKeys, kNoReportURI},
- {kGoogleAcceptableCerts, kNoRejectedPublicKeys, kNoReportURI},
+ {kGoogleAcceptableCerts, kNoRejectedPublicKeys, kGoogleReportURI},
{kTorAcceptableCerts, kNoRejectedPublicKeys, kNoReportURI},
{kTwitterComAcceptableCerts, kNoRejectedPublicKeys, kNoReportURI},
{kTwitterCDNAcceptableCerts, kNoRejectedPublicKeys, kNoReportURI},
diff --git a/http/transport_security_state_static.json b/http/transport_security_state_static.json
index 96e9a56..7add3a8 100644
--- a/http/transport_security_state_static.json
+++ b/http/transport_security_state_static.json
@@ -13,6 +13,8 @@
// static_spki_hashes: (list of strings) the set of allowed SPKIs hashes
// bad_static_spki_hashes: (optional list of strings) the set of forbidden
// SPKIs hashes
+// report_uri: (optional string) the URI to send violation reports to;
+// reports will be in the format defined in RFC 7469
//
// For a given pinset, a certificate is accepted if at least one of the
// "static_spki_hashes" SPKIs is found in the chain and none of the
@@ -41,7 +43,8 @@
"GoogleBackup2048",
"GoogleG2",
"GeoTrustGlobal"
- ]
+ ],
+ "report_uri": "http://clients3.google.com/cert_upload_json"
},
{
"name": "tor",
diff --git a/http/transport_security_state_unittest.cc b/http/transport_security_state_unittest.cc
index 4c63c06..66bbdc4 100644
--- a/http/transport_security_state_unittest.cc
+++ b/http/transport_security_state_unittest.cc
@@ -1414,4 +1414,57 @@
state.ProcessHPKPReportOnlyHeader(header, host_port_pair, ssl_info));
}
+// Tests that pinning violations on preloaded pins trigger reports when
+// the preloaded pin contains a report URI.
+TEST_F(TransportSecurityStateTest, PreloadedPKPReportUri) {
+ const char kPreloadedPinDomain[] = "www.google.com";
+ const uint16_t kPort = 443;
+ HostPortPair host_port_pair(kPreloadedPinDomain, kPort);
+
+ TransportSecurityState state;
+ MockCertificateReportSender mock_report_sender;
+ state.SetReportSender(&mock_report_sender);
+
+ ASSERT_TRUE(
+ TransportSecurityState::IsGooglePinnedProperty(kPreloadedPinDomain));
+ EnableStaticPins(&state);
+
+ TransportSecurityState::PKPState pkp_state;
+ TransportSecurityState::STSState unused_sts_state;
+ ASSERT_TRUE(state.GetStaticDomainState(kPreloadedPinDomain, &unused_sts_state,
+ &pkp_state));
+
+ GURL report_uri = pkp_state.report_uri;
+ ASSERT_TRUE(report_uri.is_valid());
+ ASSERT_FALSE(report_uri.is_empty());
+
+ // Two dummy certs to use as the server-sent and validated chains. The
+ // contents don't matter, as long as they are not the real google.com
+ // certs in the pins.
+ scoped_refptr<X509Certificate> cert1 =
+ ImportCertFromFile(GetTestCertsDirectory(), "test_mail_google_com.pem");
+ scoped_refptr<X509Certificate> cert2 =
+ ImportCertFromFile(GetTestCertsDirectory(), "expired_cert.pem");
+ ASSERT_TRUE(cert1);
+ ASSERT_TRUE(cert2);
+
+ HashValueVector bad_hashes;
+ for (size_t i = 0; kBadPath[i]; i++)
+ EXPECT_TRUE(AddHash(kBadPath[i], &bad_hashes));
+
+ // Trigger a violation and check that it sends a report.
+ std::string failure_log;
+ EXPECT_FALSE(state.CheckPublicKeyPins(
+ host_port_pair, true, bad_hashes, cert1.get(), cert2.get(),
+ TransportSecurityState::ENABLE_PIN_REPORTS, &failure_log));
+
+ EXPECT_EQ(report_uri, mock_report_sender.latest_report_uri());
+
+ std::string report = mock_report_sender.latest_report();
+ ASSERT_FALSE(report.empty());
+ ASSERT_NO_FATAL_FAILURE(CheckHPKPReport(
+ report, host_port_pair, pkp_state.include_subdomains, pkp_state.domain,
+ cert1.get(), cert2.get(), pkp_state.spki_hashes));
+}
+
} // namespace net
diff --git a/net.gypi b/net.gypi
index 3fabe95..4e5b41f 100644
--- a/net.gypi
+++ b/net.gypi
@@ -1184,7 +1184,6 @@
'url_request/data_protocol_handler.h',
'url_request/file_protocol_handler.cc',
'url_request/file_protocol_handler.h',
- 'url_request/fraudulent_certificate_reporter.h',
'url_request/ftp_protocol_handler.cc',
'url_request/ftp_protocol_handler.h',
'url_request/http_user_agent_settings.h',
diff --git a/url_request/certificate_report_sender.cc b/url_request/certificate_report_sender.cc
index fd5d11c..0ff637b 100644
--- a/url_request/certificate_report_sender.cc
+++ b/url_request/certificate_report_sender.cc
@@ -28,7 +28,15 @@
void CertificateReportSender::Send(const GURL& report_uri,
const std::string& report) {
scoped_ptr<URLRequest> url_request =
- CreateURLRequest(request_context_, report_uri);
+ request_context_->CreateRequest(report_uri, DEFAULT_PRIORITY, this);
+
+ int load_flags =
+ LOAD_BYPASS_CACHE | LOAD_DISABLE_CACHE | LOAD_DO_NOT_SEND_AUTH_DATA;
+ if (cookies_preference_ != SEND_COOKIES) {
+ load_flags |= LOAD_DO_NOT_SEND_COOKIES | LOAD_DO_NOT_SAVE_COOKIES;
+ }
+ url_request->SetLoadFlags(load_flags);
+
url_request->set_method("POST");
scoped_ptr<UploadElementReader> reader(
@@ -56,19 +64,4 @@
NOTREACHED();
}
-scoped_ptr<URLRequest> CertificateReportSender::CreateURLRequest(
- URLRequestContext* context,
- const GURL& report_uri) {
- scoped_ptr<URLRequest> request =
- context->CreateRequest(report_uri, DEFAULT_PRIORITY, this);
- int load_flags =
- LOAD_BYPASS_CACHE | LOAD_DISABLE_CACHE | LOAD_DO_NOT_SEND_AUTH_DATA;
- if (cookies_preference_ != SEND_COOKIES) {
- load_flags =
- load_flags | LOAD_DO_NOT_SEND_COOKIES | LOAD_DO_NOT_SAVE_COOKIES;
- }
- request->SetLoadFlags(load_flags);
- return request.Pass();
-}
-
} // namespace net
diff --git a/url_request/certificate_report_sender.h b/url_request/certificate_report_sender.h
index dac8a57..0f247c3 100644
--- a/url_request/certificate_report_sender.h
+++ b/url_request/certificate_report_sender.h
@@ -49,15 +49,6 @@
void OnReadCompleted(URLRequest* request, int bytes_read) override;
private:
- // Creates a URLRequest with which to send a certificate report to the
- // server.
- //
- // TODO(estark): inline this into Send() once
- // ChromeFraudulentCertificateReporter goes away.
- virtual scoped_ptr<URLRequest> CreateURLRequest(
- net::URLRequestContext* context,
- const GURL& report_uri);
-
net::URLRequestContext* const request_context_;
CookiesPreference cookies_preference_;
diff --git a/url_request/fraudulent_certificate_reporter.h b/url_request/fraudulent_certificate_reporter.h
deleted file mode 100644
index 8d5d60a..0000000
--- a/url_request/fraudulent_certificate_reporter.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2011 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.
-
-#ifndef NET_URL_REQUEST_FRAUDULENT_CERTIFICATE_REPORTER_H_
-#define NET_URL_REQUEST_FRAUDULENT_CERTIFICATE_REPORTER_H_
-
-#include <string>
-
-namespace net {
-
-class SSLInfo;
-
-// FraudulentCertificateReporter is an interface for asynchronously
-// reporting certificate chains that fail the certificate pinning
-// check.
-class FraudulentCertificateReporter {
- public:
- virtual ~FraudulentCertificateReporter() {}
-
- // Sends a report to the report collection server containing the |ssl_info|
- // associated with a connection to |hostname|.
- virtual void SendReport(const std::string& hostname,
- const SSLInfo& ssl_info) = 0;
-};
-
-} // namespace net
-
-#endif // NET_URL_REQUEST_FRAUDULENT_CERTIFICATE_REPORTER_H_
-
diff --git a/url_request/url_request_context.cc b/url_request/url_request_context.cc
index fa0db79..b83cf02 100644
--- a/url_request/url_request_context.cc
+++ b/url_request/url_request_context.cc
@@ -21,7 +21,6 @@
host_resolver_(nullptr),
cert_verifier_(nullptr),
channel_id_service_(nullptr),
- fraudulent_certificate_reporter_(nullptr),
http_auth_handler_factory_(nullptr),
proxy_service_(nullptr),
network_delegate_(nullptr),
@@ -47,7 +46,6 @@
set_host_resolver(other->host_resolver_);
set_cert_verifier(other->cert_verifier_);
set_channel_id_service(other->channel_id_service_);
- set_fraudulent_certificate_reporter(other->fraudulent_certificate_reporter_);
set_http_auth_handler_factory(other->http_auth_handler_factory_);
set_proxy_service(other->proxy_service_);
set_ssl_config_service(other->ssl_config_service_.get());
diff --git a/url_request/url_request_context.h b/url_request/url_request_context.h
index a50225c..b9f1276 100644
--- a/url_request/url_request_context.h
+++ b/url_request/url_request_context.h
@@ -31,7 +31,6 @@
class ChannelIDService;
class CookieStore;
class CTVerifier;
-class FraudulentCertificateReporter;
class HostResolver;
class HttpAuthHandlerFactory;
class HttpTransactionFactory;
@@ -99,14 +98,6 @@
channel_id_service_ = channel_id_service;
}
- FraudulentCertificateReporter* fraudulent_certificate_reporter() const {
- return fraudulent_certificate_reporter_;
- }
- void set_fraudulent_certificate_reporter(
- FraudulentCertificateReporter* fraudulent_certificate_reporter) {
- fraudulent_certificate_reporter_ = fraudulent_certificate_reporter;
- }
-
// Get the proxy service for this context.
ProxyService* proxy_service() const { return proxy_service_; }
void set_proxy_service(ProxyService* proxy_service) {
@@ -239,7 +230,6 @@
HostResolver* host_resolver_;
CertVerifier* cert_verifier_;
ChannelIDService* channel_id_service_;
- FraudulentCertificateReporter* fraudulent_certificate_reporter_;
HttpAuthHandlerFactory* http_auth_handler_factory_;
ProxyService* proxy_service_;
scoped_refptr<SSLConfigService> ssl_config_service_;
diff --git a/url_request/url_request_context_storage.cc b/url_request/url_request_context_storage.cc
index e1452be..b334632 100644
--- a/url_request/url_request_context_storage.cc
+++ b/url_request/url_request_context_storage.cc
@@ -17,7 +17,6 @@
#include "net/log/net_log.h"
#include "net/proxy/proxy_service.h"
#include "net/ssl/channel_id_service.h"
-#include "net/url_request/fraudulent_certificate_reporter.h"
#include "net/url_request/http_user_agent_settings.h"
#include "net/url_request/url_request_backoff_manager.h"
#include "net/url_request/url_request_context.h"
@@ -55,13 +54,6 @@
channel_id_service_ = channel_id_service.Pass();
}
-void URLRequestContextStorage::set_fraudulent_certificate_reporter(
- FraudulentCertificateReporter* fraudulent_certificate_reporter) {
- context_->set_fraudulent_certificate_reporter(
- fraudulent_certificate_reporter);
- fraudulent_certificate_reporter_.reset(fraudulent_certificate_reporter);
-}
-
void URLRequestContextStorage::set_http_auth_handler_factory(
HttpAuthHandlerFactory* http_auth_handler_factory) {
context_->set_http_auth_handler_factory(http_auth_handler_factory);
diff --git a/url_request/url_request_context_storage.h b/url_request/url_request_context_storage.h
index a37e30a..fd3c4a2 100644
--- a/url_request/url_request_context_storage.h
+++ b/url_request/url_request_context_storage.h
@@ -15,7 +15,6 @@
class CertVerifier;
class ChannelIDService;
class CookieStore;
-class FraudulentCertificateReporter;
class FtpTransactionFactory;
class HostResolver;
class HttpAuthHandlerFactory;
@@ -50,8 +49,6 @@
void set_host_resolver(scoped_ptr<HostResolver> host_resolver);
void set_cert_verifier(CertVerifier* cert_verifier);
void set_channel_id_service(scoped_ptr<ChannelIDService> channel_id_service);
- void set_fraudulent_certificate_reporter(
- FraudulentCertificateReporter* fraudulent_certificate_reporter);
void set_http_auth_handler_factory(
HttpAuthHandlerFactory* http_auth_handler_factory);
void set_proxy_service(ProxyService* proxy_service);
@@ -83,7 +80,6 @@
scoped_ptr<CertVerifier> cert_verifier_;
// The ChannelIDService must outlive the HttpTransactionFactory.
scoped_ptr<ChannelIDService> channel_id_service_;
- scoped_ptr<FraudulentCertificateReporter> fraudulent_certificate_reporter_;
scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory_;
scoped_ptr<ProxyService> proxy_service_;
// TODO(willchan): Remove refcounting on these members.
diff --git a/url_request/url_request_http_job.cc b/url_request/url_request_http_job.cc
index 2e55ca5..0a6632e 100644
--- a/url_request/url_request_http_job.cc
+++ b/url_request/url_request_http_job.cc
@@ -42,7 +42,6 @@
#include "net/proxy/proxy_info.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "net/ssl/ssl_config_service.h"
-#include "net/url_request/fraudulent_certificate_reporter.h"
#include "net/url_request/http_user_agent_settings.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_backoff_manager.h"
@@ -919,18 +918,6 @@
const URLRequestContext* context = request_->context();
- if (result == ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN &&
- transaction_->GetResponseInfo() != NULL) {
- FraudulentCertificateReporter* reporter =
- context->fraudulent_certificate_reporter();
- if (reporter != NULL) {
- const SSLInfo& ssl_info = transaction_->GetResponseInfo()->ssl_info;
- const std::string& host = request_->url().host();
-
- reporter->SendReport(host, ssl_info);
- }
- }
-
if (result == OK) {
if (transaction_ && transaction_->GetResponseInfo()) {
SetProxyServer(transaction_->GetResponseInfo()->proxy_server);