Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(878)

Unified Diff: net/url_request/url_request_unittest.cc

Issue 1270043004: Add URLRequest unit tests for HPKP violation reports (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: GetLocalCertificatesDir() Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/test/spawned_test_server/base_test_server.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/url_request/url_request_unittest.cc
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index ecff043877c54d88952a34bbccdcfb1eb4b96ee5..214900aeae9ec1f78377b4d03e63bb92f5a5ddc0 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -20,6 +20,7 @@
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/format_macros.h"
+#include "base/json/json_reader.h"
#include "base/location.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
@@ -35,6 +36,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/test/histogram_tester.h"
#include "base/thread_task_runner_handle.h"
+#include "base/values.h"
#include "net/base/chunked_upload_data_stream.h"
#include "net/base/elements_upload_data_stream.h"
#include "net/base/load_flags.h"
@@ -618,6 +620,27 @@ class TestURLRequestContextWithProxy : public TestURLRequestContext {
~TestURLRequestContextWithProxy() override {}
};
+// A mock ReportSender that just remembers the latest report
+// URI and report to be sent.
+class MockCertificateReportSender
+ : public TransportSecurityState::ReportSender {
+ public:
+ MockCertificateReportSender() {}
+ ~MockCertificateReportSender() override {}
+
+ void Send(const GURL& report_uri, const std::string& report) override {
+ latest_report_uri_ = report_uri;
+ latest_report_ = report;
+ }
+
+ const GURL& latest_report_uri() { return latest_report_uri_; }
+ const std::string& latest_report() { return latest_report_; }
+
+ private:
+ GURL latest_report_uri_;
+ std::string latest_report_;
+};
+
} // namespace
// Inherit PlatformTest since we require the autorelease pool on Mac OS X.
@@ -5361,13 +5384,26 @@ TEST_F(URLRequestTestHTTP, STSNotProcessedOnIP) {
// PKPState present because header rejected).
#if defined(OS_ANDROID)
#define MAYBE_ProcessPKP DISABLED_ProcessPKP
+#define MAYBE_ProcessPKPAndSendReport DISABLED_ProcessPKPAndSendReport
+#define MAYBE_ProcessPKPReportOnly DISABLED_ProcessPKPReportOnly
+#define MAYBE_ProcessPKPReportOnlyWithNoViolation \
+ DISABLED_ProcessPKPReportOnlyWithNoViolation
#else
#define MAYBE_ProcessPKP ProcessPKP
+#define MAYBE_ProcessPKPAndSendReport ProcessPKPAndSendReport
+#define MAYBE_ProcessPKPReportOnly ProcessPKPReportOnly
+#define MAYBE_ProcessPKPReportOnlyWithNoViolation \
+ ProcessPKPReportOnlyWithNoViolation
#endif
+namespace {
+const char kHPKPReportUri[] = "https://hpkp-report.test";
+} // namespace
+
// Tests that enabling HPKP on a domain does not affect the HSTS
// validity/expiration.
TEST_F(URLRequestTestHTTP, MAYBE_ProcessPKP) {
+ GURL report_uri(kHPKPReportUri);
SpawnedTestServer::SSLOptions ssl_options(
SpawnedTestServer::SSLOptions::CERT_COMMON_NAME_IS_DOMAIN);
SpawnedTestServer https_test_server(SpawnedTestServer::TYPE_HTTPS,
@@ -5397,9 +5433,188 @@ TEST_F(URLRequestTestHTTP, MAYBE_ProcessPKP) {
EXPECT_FALSE(sts_state.include_subdomains);
EXPECT_FALSE(pkp_state.include_subdomains);
EXPECT_TRUE(pkp_state.HasPublicKeyPins());
+ EXPECT_EQ(report_uri, pkp_state.report_uri);
EXPECT_NE(sts_state.expiry, pkp_state.expiry);
}
+// Tests that reports get sent on HPKP violations when a report-uri is set.
+TEST_F(URLRequestTestHTTP, MAYBE_ProcessPKPAndSendReport) {
+ GURL report_uri(kHPKPReportUri);
+ SpawnedTestServer::SSLOptions ssl_options(
+ SpawnedTestServer::SSLOptions::CERT_COMMON_NAME_IS_DOMAIN);
+ SpawnedTestServer https_test_server(SpawnedTestServer::TYPE_HTTPS,
+ ssl_options,
+ base::FilePath(kTestFilePath));
+
+ ASSERT_TRUE(https_test_server.Start());
+
+ std::string test_server_hostname = https_test_server.GetURL("").host();
+
+ // Set up a pin for |test_server_hostname|.
+ TransportSecurityState security_state;
+ const base::Time current_time(base::Time::Now());
+ const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000);
+ HashValueVector hashes;
+ HashValue hash1;
+ HashValue hash2;
+ // The values here don't matter, as long as they are different from
+ // the mocked CertVerifyResult below.
+ ASSERT_TRUE(hash1.FromString("sha1/111111111111111111111111111="));
+ ASSERT_TRUE(hash2.FromString("sha1/222222222222222222222222222="));
+ hashes.push_back(hash1);
+ hashes.push_back(hash2);
+ security_state.AddHPKP(test_server_hostname, expiry,
+ false, /* include subdomains */
+ hashes, report_uri);
+
+ MockCertificateReportSender mock_report_sender;
+ security_state.SetReportSender(&mock_report_sender);
+
+ // Set up a MockCertVerifier to trigger a violation of the previously
+ // set pin.
+ scoped_refptr<X509Certificate> cert = https_test_server.GetCertificate();
+ ASSERT_TRUE(cert);
+
+ MockCertVerifier cert_verifier;
+ CertVerifyResult verify_result;
+ verify_result.verified_cert = cert;
+ verify_result.is_issued_by_known_root = true;
+ HashValue hash3;
+ ASSERT_TRUE(hash3.FromString("sha1/333333333333333333333333333="));
+ verify_result.public_key_hashes.push_back(hash3);
+ cert_verifier.AddResultForCert(cert.get(), verify_result, OK);
+
+ TestNetworkDelegate network_delegate;
+ TestURLRequestContext context(true);
+ context.set_transport_security_state(&security_state);
+ context.set_network_delegate(&network_delegate);
+ context.set_cert_verifier(&cert_verifier);
+ context.Init();
+
+ // Now send a request to trigger the violation.
+ TestDelegate d;
+ scoped_ptr<URLRequest> violating_request(context.CreateRequest(
+ https_test_server.GetURL("files/simple.html"), DEFAULT_PRIORITY, &d));
+ violating_request->Start();
+ base::RunLoop().Run();
+
+ // Check that a report was sent.
+ EXPECT_EQ(report_uri, mock_report_sender.latest_report_uri());
+ ASSERT_FALSE(mock_report_sender.latest_report().empty());
+ scoped_ptr<base::Value> value(
+ base::JSONReader::Read(mock_report_sender.latest_report()));
+ ASSERT_TRUE(value);
+ ASSERT_TRUE(value->IsType(base::Value::TYPE_DICTIONARY));
+ base::DictionaryValue* report_dict;
+ ASSERT_TRUE(value->GetAsDictionary(&report_dict));
+ std::string report_hostname;
+ EXPECT_TRUE(report_dict->GetString("hostname", &report_hostname));
+ EXPECT_EQ(test_server_hostname, report_hostname);
+}
+
+// Tests that reports get sent on requests with
+// Public-Key-Pins-Report-Only headers.
+TEST_F(URLRequestTestHTTP, MAYBE_ProcessPKPReportOnly) {
+ GURL report_uri(kHPKPReportUri);
+ SpawnedTestServer::SSLOptions ssl_options(
+ SpawnedTestServer::SSLOptions::CERT_COMMON_NAME_IS_DOMAIN);
+ SpawnedTestServer https_test_server(SpawnedTestServer::TYPE_HTTPS,
+ ssl_options,
+ base::FilePath(kTestFilePath));
+
+ ASSERT_TRUE(https_test_server.Start());
+
+ std::string test_server_hostname = https_test_server.GetURL("").host();
+
+ TransportSecurityState security_state;
+ MockCertificateReportSender mock_report_sender;
+ security_state.SetReportSender(&mock_report_sender);
+
+ // Set up a MockCertVerifier to violate the pin in the Report-Only
+ // header.
+ scoped_refptr<X509Certificate> cert = https_test_server.GetCertificate();
+ ASSERT_TRUE(cert);
+
+ MockCertVerifier cert_verifier;
+ CertVerifyResult verify_result;
+ verify_result.verified_cert = cert;
+ verify_result.is_issued_by_known_root = true;
+ HashValue hash;
+ // This value doesn't matter, as long as it is different from the pins
+ // for the request to hpkp-headers-report-only.html.
+ ASSERT_TRUE(hash.FromString("sha1/111111111111111111111111111="));
+ verify_result.public_key_hashes.push_back(hash);
+ cert_verifier.AddResultForCert(cert.get(), verify_result, OK);
+
+ TestNetworkDelegate network_delegate;
+ TestURLRequestContext context(true);
+ context.set_transport_security_state(&security_state);
+ context.set_network_delegate(&network_delegate);
+ context.set_cert_verifier(&cert_verifier);
+ context.Init();
+
+ // Now send a request to trigger the violation.
+ TestDelegate d;
+ scoped_ptr<URLRequest> violating_request(context.CreateRequest(
+ https_test_server.GetURL("files/hpkp-headers-report-only.html"),
+ DEFAULT_PRIORITY, &d));
+ violating_request->Start();
+ base::RunLoop().Run();
+
+ // Check that a report was sent.
+ EXPECT_EQ(report_uri, mock_report_sender.latest_report_uri());
+ ASSERT_FALSE(mock_report_sender.latest_report().empty());
+ scoped_ptr<base::Value> value(
+ base::JSONReader::Read(mock_report_sender.latest_report()));
+ ASSERT_TRUE(value);
+ ASSERT_TRUE(value->IsType(base::Value::TYPE_DICTIONARY));
+ base::DictionaryValue* report_dict;
+ ASSERT_TRUE(value->GetAsDictionary(&report_dict));
+ std::string report_hostname;
+ EXPECT_TRUE(report_dict->GetString("hostname", &report_hostname));
+ EXPECT_EQ(test_server_hostname, report_hostname);
+}
+
+// Tests that reports do not get sent on requests with
+// Public-Key-Pins-Report-Only headers that don't have pin violations.
+TEST_F(URLRequestTestHTTP, MAYBE_ProcessPKPReportOnlyWithNoViolation) {
+ GURL report_uri(kHPKPReportUri);
+ SpawnedTestServer::SSLOptions ssl_options(
+ SpawnedTestServer::SSLOptions::CERT_COMMON_NAME_IS_DOMAIN);
+ SpawnedTestServer https_test_server(SpawnedTestServer::TYPE_HTTPS,
+ ssl_options,
+ base::FilePath(kTestFilePath));
+
+ ASSERT_TRUE(https_test_server.Start());
+
+ std::string test_server_hostname = https_test_server.GetURL("").host();
+
+ TransportSecurityState security_state;
+ MockCertificateReportSender mock_report_sender;
+ security_state.SetReportSender(&mock_report_sender);
+
+ TestNetworkDelegate network_delegate;
+ MockCertVerifier mock_cert_verifier;
+ TestURLRequestContext context(true);
+ context.set_transport_security_state(&security_state);
+ context.set_network_delegate(&network_delegate);
+ context.set_cert_verifier(&mock_cert_verifier);
+ mock_cert_verifier.set_default_result(OK);
+ context.Init();
+
+ // Now send a request that does not trigger the violation.
+ TestDelegate d;
+ scoped_ptr<URLRequest> request(context.CreateRequest(
+ https_test_server.GetURL("files/hpkp-headers-report-only.html"),
+ DEFAULT_PRIORITY, &d));
+ request->Start();
+ base::RunLoop().Run();
+
+ // Check that a report was not sent.
+ EXPECT_EQ(GURL(), mock_report_sender.latest_report_uri());
+ EXPECT_EQ(std::string(), mock_report_sender.latest_report());
+}
+
TEST_F(URLRequestTestHTTP, PKPNotProcessedOnIP) {
SpawnedTestServer https_test_server(SpawnedTestServer::TYPE_HTTPS,
SpawnedTestServer::SSLOptions(),
« no previous file with comments | « net/test/spawned_test_server/base_test_server.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698