Chromium Code Reviews| 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 3da8d39c86bde4421c227f93d5e8a6f9bff0b644..7ac6a63931ab16bb7468bf2923de7d3b54f3d9ed 100644 |
| --- a/net/http/transport_security_state_unittest.cc |
| +++ b/net/http/transport_security_state_unittest.cc |
| @@ -93,6 +93,26 @@ const char* const kBadPath[] = { |
| nullptr, |
| }; |
| +// Constructs a SignedCertificateTimestampAndStatus with the given information |
| +// and appends it to |sct_list|. |
| +void MakeTestSCTAndStatus(ct::SignedCertificateTimestamp::Origin origin, |
| + const std::string& log_id, |
| + const std::string& extensions, |
| + const std::string& signature_data, |
| + const base::Time& timestamp, |
| + ct::SCTVerifyStatus status, |
| + SignedCertificateTimestampAndStatusList* sct_list) { |
| + scoped_refptr<net::ct::SignedCertificateTimestamp> sct( |
| + new net::ct::SignedCertificateTimestamp()); |
| + sct->version = net::ct::SignedCertificateTimestamp::V1; |
| + sct->log_id = log_id; |
| + sct->extensions = extensions; |
| + sct->timestamp = timestamp; |
| + sct->signature.signature_data = signature_data; |
| + sct->origin = origin; |
| + sct_list->push_back(net::SignedCertificateTimestampAndStatus(sct, status)); |
| +} |
| + |
| // A mock ReportSenderInterface that just remembers the latest report |
| // URI and report to be sent. |
| class MockCertificateReportSender |
| @@ -161,23 +181,39 @@ class MockExpectCTReporter : public TransportSecurityState::ExpectCTReporter { |
| void OnExpectCTFailed(const HostPortPair& host_port_pair, |
| const GURL& report_uri, |
| - const net::SSLInfo& ssl_info) override { |
| + const X509Certificate* validated_certificate_chain, |
| + const X509Certificate* served_certificate_chain, |
| + const SignedCertificateTimestampAndStatusList& |
| + signed_certificate_timestamps) override { |
| num_failures_++; |
| host_port_pair_ = host_port_pair; |
| report_uri_ = report_uri; |
| - ssl_info_ = ssl_info; |
| + served_certificate_chain_ = served_certificate_chain; |
| + validated_certificate_chain_ = validated_certificate_chain; |
| + signed_certificate_timestamps_ = signed_certificate_timestamps; |
| } |
| 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_; } |
| + const X509Certificate* served_certificate_chain() { |
| + return served_certificate_chain_; |
| + } |
| + const X509Certificate* validated_certificate_chain() { |
| + return validated_certificate_chain_; |
| + } |
| + const SignedCertificateTimestampAndStatusList& |
| + signed_certificate_timestamps() { |
| + return signed_certificate_timestamps_; |
| + } |
| private: |
| HostPortPair host_port_pair_; |
| GURL report_uri_; |
| - SSLInfo ssl_info_; |
| uint32_t num_failures_; |
| + const X509Certificate* served_certificate_chain_; |
| + const X509Certificate* validated_certificate_chain_; |
| + SignedCertificateTimestampAndStatusList signed_certificate_timestamps_; |
| }; |
| class MockRequireCTDelegate : public TransportSecurityState::RequireCTDelegate { |
| @@ -2026,6 +2062,18 @@ TEST_F(TransportSecurityStateTest, ExpectCTReporter) { |
| ssl_info.ct_cert_policy_compliance = |
| ct::CertPolicyCompliance::CERT_POLICY_NOT_DIVERSE_SCTS; |
| ssl_info.is_issued_by_known_root = true; |
| + 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); |
| + ssl_info.unverified_cert = cert1; |
| + ssl_info.cert = cert2; |
| + MakeTestSCTAndStatus(ct::SignedCertificateTimestamp::SCT_EMBEDDED, "test_log", |
| + std::string(), std::string(), base::Time::Now(), |
| + ct::SCT_STATUS_INVALID_SIGNATURE, |
| + &ssl_info.signed_certificate_timestamps); |
| TransportSecurityState state; |
| TransportSecurityStateTest::EnableStaticExpectCT(&state); |
| @@ -2033,12 +2081,17 @@ TEST_F(TransportSecurityStateTest, ExpectCTReporter) { |
| 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()); |
| + EXPECT_EQ(cert1.get(), reporter.served_certificate_chain()); |
| + EXPECT_EQ(cert2.get(), reporter.validated_certificate_chain()); |
| + EXPECT_EQ(ssl_info.signed_certificate_timestamps.size(), |
| + reporter.signed_certificate_timestamps().size()); |
| + EXPECT_EQ(ssl_info.signed_certificate_timestamps[0].status, |
| + reporter.signed_certificate_timestamps()[0].status); |
| + EXPECT_EQ(ssl_info.signed_certificate_timestamps[0].sct, |
| + reporter.signed_certificate_timestamps()[0].sct); |
| } |
| // Simple test for the HSTS preload process. The trie (generated from |
| @@ -2508,51 +2561,108 @@ TEST_F(TransportSecurityStateTest, RequireCTConsultsDelegate) { |
| { |
| TransportSecurityState state; |
| - bool original_status = |
| - state.ShouldRequireCT("www.example.com", cert.get(), hashes); |
| + bool original_status = state.CheckCTRequirements( |
| + HostPortPair("www.example.com", 443), true, hashes, cert.get(), |
| + cert.get(), SignedCertificateTimestampAndStatusList(), |
| + TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS); |
| MockRequireCTDelegate always_require_delegate; |
| EXPECT_CALL(always_require_delegate, IsCTRequiredForHost(_)) |
| .WillRepeatedly(Return(CTRequirementLevel::REQUIRED)); |
| state.SetRequireCTDelegate(&always_require_delegate); |
| - EXPECT_TRUE(state.ShouldRequireCT("www.example.com", cert.get(), hashes)); |
| + EXPECT_FALSE(state.CheckCTRequirements( |
| + HostPortPair("www.example.com", 443), true, hashes, cert.get(), |
| + cert.get(), SignedCertificateTimestampAndStatusList(), |
| + TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS)); |
| + EXPECT_FALSE(state.CheckCTRequirements( |
| + HostPortPair("www.example.com", 443), true, hashes, cert.get(), |
| + cert.get(), SignedCertificateTimestampAndStatusList(), |
| + TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_DIVERSE_SCTS)); |
|
estark
2017/05/04 01:18:30
Now that the CertPolicyCompliance testing is in Tr
|
| + EXPECT_TRUE(state.CheckCTRequirements( |
| + HostPortPair("www.example.com", 443), true, hashes, cert.get(), |
| + cert.get(), SignedCertificateTimestampAndStatusList(), |
| + TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS)); |
| + EXPECT_TRUE(state.CheckCTRequirements( |
| + HostPortPair("www.example.com", 443), true, hashes, cert.get(), |
| + cert.get(), SignedCertificateTimestampAndStatusList(), |
| + TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_BUILD_NOT_TIMELY)); |
| state.SetRequireCTDelegate(nullptr); |
| - EXPECT_EQ(original_status, |
| - state.ShouldRequireCT("www.example.com", cert.get(), hashes)); |
| + EXPECT_EQ( |
| + original_status, |
| + state.CheckCTRequirements( |
| + HostPortPair("www.example.com", 443), true, hashes, cert.get(), |
| + cert.get(), SignedCertificateTimestampAndStatusList(), |
| + TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS)); |
| } |
| { |
| TransportSecurityState state; |
| - bool original_status = |
| - state.ShouldRequireCT("www.example.com", cert.get(), hashes); |
| + bool original_status = state.CheckCTRequirements( |
| + HostPortPair("www.example.com", 443), true, hashes, cert.get(), |
| + cert.get(), SignedCertificateTimestampAndStatusList(), |
| + TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS); |
| MockRequireCTDelegate never_require_delegate; |
| EXPECT_CALL(never_require_delegate, IsCTRequiredForHost(_)) |
| .WillRepeatedly(Return(CTRequirementLevel::NOT_REQUIRED)); |
| state.SetRequireCTDelegate(&never_require_delegate); |
| - EXPECT_FALSE(state.ShouldRequireCT("www.example.com", cert.get(), hashes)); |
| + EXPECT_TRUE(state.CheckCTRequirements( |
| + HostPortPair("www.example.com", 443), true, hashes, cert.get(), |
| + cert.get(), SignedCertificateTimestampAndStatusList(), |
| + TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS)); |
| + EXPECT_TRUE(state.CheckCTRequirements( |
| + HostPortPair("www.example.com", 443), true, hashes, cert.get(), |
| + cert.get(), SignedCertificateTimestampAndStatusList(), |
| + TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_DIVERSE_SCTS)); |
| state.SetRequireCTDelegate(nullptr); |
| - EXPECT_EQ(original_status, |
| - state.ShouldRequireCT("www.example.com", cert.get(), hashes)); |
| + EXPECT_EQ( |
| + original_status, |
| + state.CheckCTRequirements( |
| + HostPortPair("www.example.com", 443), true, hashes, cert.get(), |
| + cert.get(), SignedCertificateTimestampAndStatusList(), |
| + TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS)); |
| } |
| { |
| TransportSecurityState state; |
| - bool original_status = |
| - state.ShouldRequireCT("www.example.com", cert.get(), hashes); |
| + bool original_status = state.CheckCTRequirements( |
| + HostPortPair("www.example.com", 443), true, hashes, cert.get(), |
| + cert.get(), SignedCertificateTimestampAndStatusList(), |
| + TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS); |
| MockRequireCTDelegate default_require_ct_delegate; |
| EXPECT_CALL(default_require_ct_delegate, IsCTRequiredForHost(_)) |
| .WillRepeatedly(Return(CTRequirementLevel::DEFAULT)); |
| state.SetRequireCTDelegate(&default_require_ct_delegate); |
| - EXPECT_EQ(original_status, |
| - state.ShouldRequireCT("www.example.com", cert.get(), hashes)); |
| + EXPECT_EQ( |
| + original_status, |
| + state.CheckCTRequirements( |
| + HostPortPair("www.example.com", 443), true, hashes, cert.get(), |
| + cert.get(), SignedCertificateTimestampAndStatusList(), |
| + TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS)); |
| state.SetRequireCTDelegate(nullptr); |
| - EXPECT_EQ(original_status, |
| - state.ShouldRequireCT("www.example.com", cert.get(), hashes)); |
| + EXPECT_EQ( |
| + original_status, |
| + state.CheckCTRequirements( |
| + HostPortPair("www.example.com", 443), true, hashes, cert.get(), |
| + cert.get(), SignedCertificateTimestampAndStatusList(), |
| + TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS)); |
| } |
| } |
| @@ -2584,29 +2694,64 @@ TEST_F(TransportSecurityStateTest, RequireCTForSymantec) { |
| // Certificates issued by Symantec prior to 1 June 2016 should not |
| // be required to be disclosed via CT. |
| - EXPECT_FALSE( |
| - state.ShouldRequireCT("www.example.com", before_cert.get(), hashes)); |
| + EXPECT_TRUE(state.CheckCTRequirements( |
| + HostPortPair("www.example.com", 443), true, hashes, before_cert.get(), |
| + before_cert.get(), SignedCertificateTimestampAndStatusList(), |
| + TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS)); |
| // ... but certificates issued after 1 June 2016 are required to be... |
| - EXPECT_TRUE( |
| - state.ShouldRequireCT("www.example.com", after_cert.get(), hashes)); |
| + EXPECT_FALSE(state.CheckCTRequirements( |
| + HostPortPair("www.example.com", 443), true, hashes, after_cert.get(), |
| + after_cert.get(), SignedCertificateTimestampAndStatusList(), |
| + TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS)); |
| + EXPECT_FALSE(state.CheckCTRequirements( |
| + HostPortPair("www.example.com", 443), true, hashes, after_cert.get(), |
| + after_cert.get(), SignedCertificateTimestampAndStatusList(), |
| + TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_DIVERSE_SCTS)); |
| + EXPECT_TRUE(state.CheckCTRequirements( |
| + HostPortPair("www.example.com", 443), true, hashes, after_cert.get(), |
| + after_cert.get(), SignedCertificateTimestampAndStatusList(), |
| + TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_BUILD_NOT_TIMELY)); |
| + EXPECT_TRUE(state.CheckCTRequirements( |
| + HostPortPair("www.example.com", 443), true, hashes, after_cert.get(), |
| + after_cert.get(), SignedCertificateTimestampAndStatusList(), |
| + TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS)); |
| // ... unless they were issued by an excluded intermediate. |
| hashes.push_back(HashValue(google_hash_value)); |
| - EXPECT_FALSE( |
| - state.ShouldRequireCT("www.example.com", before_cert.get(), hashes)); |
| - EXPECT_FALSE( |
| - state.ShouldRequireCT("www.example.com", after_cert.get(), hashes)); |
| + EXPECT_TRUE(state.CheckCTRequirements( |
| + HostPortPair("www.example.com", 443), true, hashes, before_cert.get(), |
| + before_cert.get(), SignedCertificateTimestampAndStatusList(), |
| + TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS)); |
| + EXPECT_TRUE(state.CheckCTRequirements( |
| + HostPortPair("www.example.com", 443), true, hashes, after_cert.get(), |
| + after_cert.get(), SignedCertificateTimestampAndStatusList(), |
| + TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS)); |
| // And other certificates should remain unaffected. |
| SHA256HashValue unrelated_hash_value = {{0x01, 0x02}}; |
| HashValueVector unrelated_hashes; |
| unrelated_hashes.push_back(HashValue(unrelated_hash_value)); |
| - EXPECT_FALSE(state.ShouldRequireCT("www.example.com", before_cert.get(), |
| - unrelated_hashes)); |
| - EXPECT_FALSE(state.ShouldRequireCT("www.example.com", after_cert.get(), |
| - unrelated_hashes)); |
| + EXPECT_TRUE(state.CheckCTRequirements( |
| + HostPortPair("www.example.com", 443), true, unrelated_hashes, |
| + before_cert.get(), before_cert.get(), |
| + SignedCertificateTimestampAndStatusList(), |
| + TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS)); |
| + EXPECT_TRUE(state.CheckCTRequirements( |
| + HostPortPair("www.example.com", 443), true, unrelated_hashes, |
| + after_cert.get(), after_cert.get(), |
| + SignedCertificateTimestampAndStatusList(), |
| + TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS)); |
| // And the emergency field trial should disable the requirement, if |
| // necessary. |
| @@ -2617,10 +2762,16 @@ TEST_F(TransportSecurityStateTest, RequireCTForSymantec) { |
| base::FieldTrialList::CreateFieldTrial("EnforceCTForProblematicRoots", |
| "disabled"); |
| - EXPECT_FALSE( |
| - state.ShouldRequireCT("www.example.com", before_cert.get(), hashes)); |
| - EXPECT_FALSE( |
| - state.ShouldRequireCT("www.example.com", after_cert.get(), hashes)); |
| + EXPECT_TRUE(state.CheckCTRequirements( |
| + HostPortPair("www.example.com", 443), true, hashes, before_cert.get(), |
| + before_cert.get(), SignedCertificateTimestampAndStatusList(), |
| + TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS)); |
| + EXPECT_TRUE(state.CheckCTRequirements( |
| + HostPortPair("www.example.com", 443), true, hashes, after_cert.get(), |
| + after_cert.get(), SignedCertificateTimestampAndStatusList(), |
| + TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS)); |
| } |
| // Tests that dynamic Expect-CT state is cleared from ClearDynamicData(). |
| @@ -2784,13 +2935,26 @@ TEST_F(TransportSecurityStateTest, DynamicExpectCTNoComplianceDetails) { |
| // Tests that Expect-CT reports are sent when an Expect-CT header is received |
| // over a non-compliant connection. |
| -TEST_F(TransportSecurityStateTest, DynamicExpectCTNonCompliant) { |
| +TEST_F(TransportSecurityStateTest, |
| + DynamicExpectCTHeaderProcessingNonCompliant) { |
| const char kHeader[] = "max-age=123,enforce,report-uri=\"http://foo.test\""; |
| SSLInfo ssl; |
| ssl.is_issued_by_known_root = true; |
| ssl.ct_compliance_details_available = true; |
| ssl.ct_cert_policy_compliance = |
| ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS; |
| + 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); |
| + ssl.unverified_cert = cert1; |
| + ssl.cert = cert2; |
| + MakeTestSCTAndStatus(ct::SignedCertificateTimestamp::SCT_EMBEDDED, "test_log", |
| + std::string(), std::string(), base::Time::Now(), |
| + ct::SCT_STATUS_INVALID_SIGNATURE, |
| + &ssl.signed_certificate_timestamps); |
| base::test::ScopedFeatureList feature_list; |
| feature_list.InitAndEnableFeature( |
| @@ -2803,6 +2967,174 @@ TEST_F(TransportSecurityStateTest, DynamicExpectCTNonCompliant) { |
| EXPECT_FALSE(state.GetDynamicExpectCTState("example.test", &expect_ct_state)); |
| EXPECT_EQ(1u, reporter.num_failures()); |
| EXPECT_EQ("example.test", reporter.host_port_pair().host()); |
| + EXPECT_EQ(cert1.get(), reporter.served_certificate_chain()); |
| + EXPECT_EQ(cert2.get(), reporter.validated_certificate_chain()); |
| + EXPECT_EQ(ssl.signed_certificate_timestamps.size(), |
| + reporter.signed_certificate_timestamps().size()); |
| + EXPECT_EQ(ssl.signed_certificate_timestamps[0].status, |
| + reporter.signed_certificate_timestamps()[0].status); |
| + EXPECT_EQ(ssl.signed_certificate_timestamps[0].sct, |
| + reporter.signed_certificate_timestamps()[0].sct); |
| +} |
| + |
| +// Tests that CheckCTRequirements() returns false if a connection to a host |
| +// violates an Expect-CT header, and that it reports violations. |
| +TEST_F(TransportSecurityStateTest, CheckCTRequirementsWithExpectCT) { |
| + const base::Time current_time(base::Time::Now()); |
| + const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); |
| + 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); |
| + SignedCertificateTimestampAndStatusList sct_list; |
| + MakeTestSCTAndStatus(ct::SignedCertificateTimestamp::SCT_EMBEDDED, "test_log", |
| + std::string(), std::string(), base::Time::Now(), |
| + ct::SCT_STATUS_INVALID_SIGNATURE, &sct_list); |
| + |
| + base::test::ScopedFeatureList feature_list; |
| + feature_list.InitAndEnableFeature( |
| + TransportSecurityState::kDynamicExpectCTFeature); |
| + |
| + TransportSecurityState state; |
| + MockExpectCTReporter reporter; |
| + state.SetExpectCTReporter(&reporter); |
| + state.AddExpectCT("example.test", expiry, true /* enforce */, |
| + GURL("https://example-report.test")); |
| + state.AddExpectCT("example-report-only.test", expiry, false /* enforce */, |
| + GURL("https://example-report.test")); |
| + state.AddExpectCT("example-enforce-only.test", expiry, true /* enforce */, |
| + GURL()); |
| + |
| + // Test that a connection to an unrelated host is not affected. |
| + EXPECT_TRUE(state.CheckCTRequirements( |
| + HostPortPair("example2.test", 443), true, HashValueVector(), cert1.get(), |
| + cert2.get(), sct_list, TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS)); |
| + EXPECT_TRUE(state.CheckCTRequirements( |
| + HostPortPair("example2.test", 443), true, HashValueVector(), cert1.get(), |
| + cert2.get(), sct_list, TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_DIVERSE_SCTS)); |
| + EXPECT_EQ(0u, reporter.num_failures()); |
| + |
| + // A connection to an Expect-CT host should be closed and reported. |
| + EXPECT_FALSE(state.CheckCTRequirements( |
| + HostPortPair("example.test", 443), true, HashValueVector(), cert1.get(), |
| + cert2.get(), sct_list, TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS)); |
| + EXPECT_EQ(1u, reporter.num_failures()); |
| + EXPECT_EQ("example.test", reporter.host_port_pair().host()); |
| + EXPECT_EQ(443, reporter.host_port_pair().port()); |
| + EXPECT_EQ(cert1.get(), reporter.validated_certificate_chain()); |
| + EXPECT_EQ(cert2.get(), reporter.served_certificate_chain()); |
| + EXPECT_EQ(sct_list.size(), reporter.signed_certificate_timestamps().size()); |
| + EXPECT_EQ(sct_list[0].status, |
| + reporter.signed_certificate_timestamps()[0].status); |
| + EXPECT_EQ(sct_list[0].sct, reporter.signed_certificate_timestamps()[0].sct); |
| + |
| + // A compliant connection to an Expect-CT host should not be closed or |
| + // reported. |
| + EXPECT_TRUE(state.CheckCTRequirements( |
| + HostPortPair("example.test", 443), true, HashValueVector(), cert1.get(), |
| + cert2.get(), sct_list, TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS)); |
| + EXPECT_EQ(1u, reporter.num_failures()); |
| + EXPECT_TRUE(state.CheckCTRequirements( |
| + HostPortPair("example.test", 443), true, HashValueVector(), cert1.get(), |
| + cert2.get(), sct_list, TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_BUILD_NOT_TIMELY)); |
| + EXPECT_EQ(1u, reporter.num_failures()); |
| + |
| + // A connection to a report-only host should be reported only. |
| + EXPECT_TRUE(state.CheckCTRequirements( |
| + HostPortPair("example-report-only.test", 443), true, HashValueVector(), |
| + cert1.get(), cert2.get(), sct_list, |
| + TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_DIVERSE_SCTS)); |
| + EXPECT_EQ(2u, reporter.num_failures()); |
| + EXPECT_EQ("example-report-only.test", reporter.host_port_pair().host()); |
| + EXPECT_EQ(443, reporter.host_port_pair().port()); |
| + EXPECT_EQ(cert1.get(), reporter.validated_certificate_chain()); |
| + EXPECT_EQ(cert2.get(), reporter.served_certificate_chain()); |
| + EXPECT_EQ(sct_list.size(), reporter.signed_certificate_timestamps().size()); |
| + EXPECT_EQ(sct_list[0].status, |
| + reporter.signed_certificate_timestamps()[0].status); |
| + EXPECT_EQ(sct_list[0].sct, reporter.signed_certificate_timestamps()[0].sct); |
| + |
| + // A connection to an enforce-only host should be closed but not reported. |
| + EXPECT_FALSE(state.CheckCTRequirements( |
| + HostPortPair("example-enforce-only.test", 443), true, HashValueVector(), |
| + cert1.get(), cert2.get(), sct_list, |
| + TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_DIVERSE_SCTS)); |
| + EXPECT_EQ(2u, reporter.num_failures()); |
| + |
| + // A connection with a private root should be neither enforced nor reported. |
| + EXPECT_TRUE(state.CheckCTRequirements( |
| + HostPortPair("example.test", 443), false, HashValueVector(), cert1.get(), |
| + cert2.get(), sct_list, TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS)); |
| + EXPECT_EQ(2u, reporter.num_failures()); |
| + |
| + // A connection with DISABLE_EXPECT_CT_REPORTS should not send a report. |
| + EXPECT_FALSE(state.CheckCTRequirements( |
| + HostPortPair("example.test", 443), true, HashValueVector(), cert1.get(), |
| + cert2.get(), sct_list, TransportSecurityState::DISABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS)); |
| + EXPECT_EQ(2u, reporter.num_failures()); |
| +} |
| + |
| +// Tests that for a host that requires CT by delegate and is also |
| +// Expect-CT-enabled, CheckCTRequirements() sends reports. |
| +TEST_F(TransportSecurityStateTest, CheckCTRequirementsWithExpectCTAndDelegate) { |
| + using ::testing::_; |
| + using ::testing::Return; |
| + using CTRequirementLevel = |
| + TransportSecurityState::RequireCTDelegate::CTRequirementLevel; |
| + |
| + const base::Time current_time(base::Time::Now()); |
| + const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); |
| + 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); |
| + SignedCertificateTimestampAndStatusList sct_list; |
| + MakeTestSCTAndStatus(ct::SignedCertificateTimestamp::SCT_EMBEDDED, "test_log", |
| + std::string(), std::string(), base::Time::Now(), |
| + ct::SCT_STATUS_INVALID_SIGNATURE, &sct_list); |
| + |
| + base::test::ScopedFeatureList feature_list; |
| + feature_list.InitAndEnableFeature( |
| + TransportSecurityState::kDynamicExpectCTFeature); |
| + |
| + TransportSecurityState state; |
| + MockExpectCTReporter reporter; |
| + state.SetExpectCTReporter(&reporter); |
| + state.AddExpectCT("example.test", expiry, false /* enforce */, |
| + GURL("https://example-report.test")); |
| + |
| + // A connection to an Expect-CT host, which also requires CT by the delegate, |
| + // should be closed and reported. |
| + MockRequireCTDelegate always_require_delegate; |
| + EXPECT_CALL(always_require_delegate, IsCTRequiredForHost(_)) |
| + .WillRepeatedly(Return(CTRequirementLevel::REQUIRED)); |
| + state.SetRequireCTDelegate(&always_require_delegate); |
| + EXPECT_FALSE(state.CheckCTRequirements( |
| + HostPortPair("example.test", 443), true, HashValueVector(), cert1.get(), |
| + cert2.get(), sct_list, TransportSecurityState::ENABLE_EXPECT_CT_REPORTS, |
| + ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS)); |
| + EXPECT_EQ(1u, reporter.num_failures()); |
| + EXPECT_EQ("example.test", reporter.host_port_pair().host()); |
| + EXPECT_EQ(443, reporter.host_port_pair().port()); |
| + EXPECT_EQ(cert1.get(), reporter.validated_certificate_chain()); |
| + EXPECT_EQ(cert2.get(), reporter.served_certificate_chain()); |
| + EXPECT_EQ(sct_list.size(), reporter.signed_certificate_timestamps().size()); |
| + EXPECT_EQ(sct_list[0].status, |
| + reporter.signed_certificate_timestamps()[0].status); |
| + EXPECT_EQ(sct_list[0].sct, reporter.signed_certificate_timestamps()[0].sct); |
| } |
| } // namespace net |