| Index: net/http/transport_security_state_unittest.cc
|
| diff --git a/net/http/transport_security_state_unittest.cc b/net/http/transport_security_state_unittest.cc
|
| index 75c7c751904df00fa823ac82646c9a4ef42b22ea..c31f0951ac16307617e9495fa78ea80e1cb14d4b 100644
|
| --- a/net/http/transport_security_state_unittest.cc
|
| +++ b/net/http/transport_security_state_unittest.cc
|
| @@ -23,6 +23,7 @@
|
| #include "net/cert/asn1_util.h"
|
| #include "net/cert/cert_verifier.h"
|
| #include "net/cert/cert_verify_result.h"
|
| +#include "net/cert/ct_policy_status.h"
|
| #include "net/cert/test_root_certs.h"
|
| #include "net/cert/x509_cert_types.h"
|
| #include "net/cert/x509_certificate.h"
|
| @@ -46,6 +47,8 @@ const char kHost[] = "example.test";
|
| const char kSubdomain[] = "foo.example.test";
|
| const uint16_t kPort = 443;
|
| const char kReportUri[] = "http://report-example.test/test";
|
| +const char kExpectCTStaticHostname[] = "preloaded-expect-ct.badssl.com";
|
| +const char kExpectCTStaticReportURI[] = "https://report.badssl.com/expect-ct";
|
|
|
| // kGoodPath is blog.torproject.org.
|
| const char* const kGoodPath[] = {
|
| @@ -100,6 +103,34 @@ class MockCertificateReportSender
|
| std::string latest_report_;
|
| };
|
|
|
| +// A mock ExpectCTReporter that remembers the latest violation that was
|
| +// reported and the number of violations reported.
|
| +class MockExpectCTReporter : public TransportSecurityState::ExpectCTReporter {
|
| + public:
|
| + MockExpectCTReporter() : num_failures_(0) {}
|
| + ~MockExpectCTReporter() override {}
|
| +
|
| + void OnExpectCTFailed(const HostPortPair& host_port_pair,
|
| + const GURL& report_uri,
|
| + const net::SSLInfo& ssl_info) override {
|
| + num_failures_++;
|
| + host_port_pair_ = host_port_pair;
|
| + report_uri_ = report_uri;
|
| + ssl_info_ = ssl_info;
|
| + }
|
| +
|
| + const HostPortPair& host_port_pair() { return host_port_pair_; }
|
| + const GURL& report_uri() { return report_uri_; }
|
| + const SSLInfo& ssl_info() { return ssl_info_; }
|
| + uint32_t num_failures() { return num_failures_; }
|
| +
|
| + private:
|
| + HostPortPair host_port_pair_;
|
| + GURL report_uri_;
|
| + SSLInfo ssl_info_;
|
| + uint32_t num_failures_;
|
| +};
|
| +
|
| void CompareCertificateChainWithList(
|
| const scoped_refptr<X509Certificate>& cert_chain,
|
| const base::ListValue* cert_list) {
|
| @@ -210,6 +241,12 @@ class TransportSecurityStateTest : public testing::Test {
|
| TransportSecurityState::PKPState* pkp_result) {
|
| return state->GetStaticDomainState(host, sts_result, pkp_result);
|
| }
|
| +
|
| + bool GetExpectCTState(TransportSecurityState* state,
|
| + const std::string& host,
|
| + TransportSecurityState::ExpectCTState* result) {
|
| + return state->GetStaticExpectCTState(host, result);
|
| + }
|
| };
|
|
|
| TEST_F(TransportSecurityStateTest, DomainNameOddities) {
|
| @@ -1553,16 +1590,152 @@ TEST_F(TransportSecurityStateTest, HPKPReportRateLimiting) {
|
|
|
| // Tests that static (preloaded) expect CT state is read correctly.
|
| TEST_F(TransportSecurityStateTest, PreloadedExpectCT) {
|
| - const char kHostname[] = "preloaded-expect-ct.badssl.com";
|
| TransportSecurityState state;
|
| TransportSecurityStateTest::EnableStaticExpectCT(&state);
|
| TransportSecurityState::ExpectCTState expect_ct_state;
|
| - EXPECT_TRUE(state.GetStaticExpectCTState(kHostname, &expect_ct_state));
|
| - EXPECT_EQ(kHostname, expect_ct_state.domain);
|
| - EXPECT_EQ(GURL("https://report.badssl.com/expect-ct"),
|
| - expect_ct_state.report_uri);
|
| - EXPECT_FALSE(state.GetStaticExpectCTState("pinning-test.badssl.com",
|
| - &expect_ct_state));
|
| + EXPECT_TRUE(
|
| + GetExpectCTState(&state, kExpectCTStaticHostname, &expect_ct_state));
|
| + EXPECT_EQ(kExpectCTStaticHostname, expect_ct_state.domain);
|
| + EXPECT_EQ(GURL(kExpectCTStaticReportURI), expect_ct_state.report_uri);
|
| + EXPECT_FALSE(
|
| + GetExpectCTState(&state, "pinning-test.badssl.com", &expect_ct_state));
|
| +}
|
| +
|
| +// Tests that the Expect CT reporter is not notified for invalid or absent
|
| +// header values.
|
| +TEST_F(TransportSecurityStateTest, InvalidExpectCTHeader) {
|
| + HostPortPair host_port(kExpectCTStaticHostname, 443);
|
| + SSLInfo ssl_info;
|
| + ssl_info.ct_compliance_details_available = true;
|
| + ssl_info.ct_cert_policy_compliance =
|
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS;
|
| + ssl_info.is_issued_by_known_root = true;
|
| +
|
| + TransportSecurityState state;
|
| + TransportSecurityStateTest::EnableStaticExpectCT(&state);
|
| + MockExpectCTReporter reporter;
|
| + state.SetExpectCTReporter(&reporter);
|
| + state.ProcessExpectCTHeader("", host_port, ssl_info);
|
| + EXPECT_EQ(0u, reporter.num_failures());
|
| +
|
| + state.ProcessExpectCTHeader("blah blah", host_port, ssl_info);
|
| + EXPECT_EQ(0u, reporter.num_failures());
|
| +
|
| + state.ProcessExpectCTHeader("preload", host_port, ssl_info);
|
| + EXPECT_EQ(1u, reporter.num_failures());
|
| +}
|
| +
|
| +// Tests that the Expect CT reporter is only notified about certificates
|
| +// chaining to public roots.
|
| +TEST_F(TransportSecurityStateTest, ExpectCTNonPublicRoot) {
|
| + HostPortPair host_port(kExpectCTStaticHostname, 443);
|
| + SSLInfo ssl_info;
|
| + ssl_info.ct_compliance_details_available = true;
|
| + ssl_info.ct_cert_policy_compliance =
|
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS;
|
| + ssl_info.is_issued_by_known_root = false;
|
| +
|
| + TransportSecurityState state;
|
| + TransportSecurityStateTest::EnableStaticExpectCT(&state);
|
| + MockExpectCTReporter reporter;
|
| + state.SetExpectCTReporter(&reporter);
|
| + state.ProcessExpectCTHeader("preload", host_port, ssl_info);
|
| + EXPECT_EQ(0u, reporter.num_failures());
|
| +
|
| + ssl_info.is_issued_by_known_root = true;
|
| + state.ProcessExpectCTHeader("preload", host_port, ssl_info);
|
| + EXPECT_EQ(1u, reporter.num_failures());
|
| +}
|
| +
|
| +// Tests that the Expect CT reporter is not notified when compliance
|
| +// details aren't available.
|
| +TEST_F(TransportSecurityStateTest, ExpectCTComplianceNotAvailable) {
|
| + HostPortPair host_port(kExpectCTStaticHostname, 443);
|
| + SSLInfo ssl_info;
|
| + ssl_info.ct_compliance_details_available = false;
|
| + ssl_info.ct_cert_policy_compliance =
|
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS;
|
| + ssl_info.is_issued_by_known_root = true;
|
| +
|
| + TransportSecurityState state;
|
| + TransportSecurityStateTest::EnableStaticExpectCT(&state);
|
| + MockExpectCTReporter reporter;
|
| + state.SetExpectCTReporter(&reporter);
|
| + state.ProcessExpectCTHeader("preload", host_port, ssl_info);
|
| + EXPECT_EQ(0u, reporter.num_failures());
|
| +
|
| + ssl_info.ct_compliance_details_available = true;
|
| + state.ProcessExpectCTHeader("preload", host_port, ssl_info);
|
| + EXPECT_EQ(1u, reporter.num_failures());
|
| +}
|
| +
|
| +// Tests that the Expect CT reporter is not notified about compliant
|
| +// connections.
|
| +TEST_F(TransportSecurityStateTest, ExpectCTCompliantCert) {
|
| + HostPortPair host_port(kExpectCTStaticHostname, 443);
|
| + SSLInfo ssl_info;
|
| + ssl_info.ct_compliance_details_available = true;
|
| + ssl_info.ct_cert_policy_compliance =
|
| + ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS;
|
| + ssl_info.is_issued_by_known_root = true;
|
| +
|
| + TransportSecurityState state;
|
| + TransportSecurityStateTest::EnableStaticExpectCT(&state);
|
| + MockExpectCTReporter reporter;
|
| + state.SetExpectCTReporter(&reporter);
|
| + state.ProcessExpectCTHeader("preload", host_port, ssl_info);
|
| + EXPECT_EQ(0u, reporter.num_failures());
|
| +
|
| + ssl_info.ct_cert_policy_compliance =
|
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_DIVERSE_SCTS;
|
| + state.ProcessExpectCTHeader("preload", host_port, ssl_info);
|
| + EXPECT_EQ(1u, reporter.num_failures());
|
| +}
|
| +
|
| +// Tests that the Expect CT reporter is not notified for a site that
|
| +// isn't preloaded.
|
| +TEST_F(TransportSecurityStateTest, ExpectCTNotPreloaded) {
|
| + HostPortPair host_port("not-expect-ct-preloaded.test", 443);
|
| + SSLInfo ssl_info;
|
| + ssl_info.ct_compliance_details_available = true;
|
| + ssl_info.ct_cert_policy_compliance =
|
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_DIVERSE_SCTS;
|
| + ssl_info.is_issued_by_known_root = true;
|
| +
|
| + TransportSecurityState state;
|
| + TransportSecurityStateTest::EnableStaticExpectCT(&state);
|
| + MockExpectCTReporter reporter;
|
| + state.SetExpectCTReporter(&reporter);
|
| + state.ProcessExpectCTHeader("preload", host_port, ssl_info);
|
| + EXPECT_EQ(0u, reporter.num_failures());
|
| +
|
| + host_port.set_host(kExpectCTStaticHostname);
|
| + state.ProcessExpectCTHeader("preload", host_port, ssl_info);
|
| + EXPECT_EQ(1u, reporter.num_failures());
|
| +}
|
| +
|
| +// Tests that the Expect CT reporter is notified for noncompliant
|
| +// connections.
|
| +TEST_F(TransportSecurityStateTest, ExpectCTReporter) {
|
| + HostPortPair host_port(kExpectCTStaticHostname, 443);
|
| + SSLInfo ssl_info;
|
| + ssl_info.ct_compliance_details_available = true;
|
| + ssl_info.ct_cert_policy_compliance =
|
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_DIVERSE_SCTS;
|
| + ssl_info.is_issued_by_known_root = true;
|
| +
|
| + TransportSecurityState state;
|
| + TransportSecurityStateTest::EnableStaticExpectCT(&state);
|
| + MockExpectCTReporter reporter;
|
| + state.SetExpectCTReporter(&reporter);
|
| + state.ProcessExpectCTHeader("preload", host_port, ssl_info);
|
| + EXPECT_EQ(1u, reporter.num_failures());
|
| + EXPECT_TRUE(reporter.ssl_info().ct_compliance_details_available);
|
| + EXPECT_EQ(ssl_info.ct_cert_policy_compliance,
|
| + reporter.ssl_info().ct_cert_policy_compliance);
|
| + EXPECT_EQ(host_port.host(), reporter.host_port_pair().host());
|
| + EXPECT_EQ(host_port.port(), reporter.host_port_pair().port());
|
| + EXPECT_EQ(GURL(kExpectCTStaticReportURI), reporter.report_uri());
|
| }
|
|
|
| } // namespace net
|
|
|