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

Unified Diff: net/socket/ssl_client_socket_unittest.cc

Issue 2850033002: Check Expect-CT at connection setup (Closed)
Patch Set: fix comment typo Created 3 years, 7 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/socket/ssl_client_socket_impl.cc ('k') | net/spdy/chromium/spdy_session.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/socket/ssl_client_socket_unittest.cc
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc
index 6067721f84f3dc30e3b8125a3729ad2b3227341e..1b62a269ac43268470a903b9216162bfb66216d3 100644
--- a/net/socket/ssl_client_socket_unittest.cc
+++ b/net/socket/ssl_client_socket_unittest.cc
@@ -805,6 +805,50 @@ class AsyncFailingChannelIDStore : public ChannelIDStore {
bool IsEphemeral() override { return true; }
};
+// 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 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;
+ 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_; }
+ 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_;
+ uint32_t num_failures_;
+ const X509Certificate* served_certificate_chain_;
+ const X509Certificate* validated_certificate_chain_;
+ SignedCertificateTimestampAndStatusList signed_certificate_timestamps_;
+};
+
// A mock CTVerifier that records every call to Verify but doesn't verify
// anything.
class MockCTVerifier : public CTVerifier {
@@ -3478,6 +3522,105 @@ TEST_F(SSLClientSocketTest, CTIsRequired) {
EXPECT_TRUE(sock_->IsConnected());
}
+// Test that when CT is required (in this case, by an Expect-CT opt-in), the
+// absence of CT information is a socket error.
+TEST_F(SSLClientSocketTest, CTIsRequiredByExpectCT) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(
+ TransportSecurityState::kDynamicExpectCTFeature);
+
+ SpawnedTestServer::SSLOptions ssl_options;
+ ASSERT_TRUE(StartTestServer(ssl_options));
+ scoped_refptr<X509Certificate> server_cert =
+ spawned_test_server()->GetCertificate();
+
+ // Certificate is trusted and chains to a public root.
+ CertVerifyResult verify_result;
+ verify_result.is_issued_by_known_root = true;
+ verify_result.verified_cert = server_cert;
+ verify_result.public_key_hashes = MakeHashValueVector(0);
+ cert_verifier_->AddResultForCert(server_cert.get(), verify_result, OK);
+
+ // Set up the Expect-CT opt-in.
+ const base::Time current_time(base::Time::Now());
+ const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000);
+ transport_security_state_->AddExpectCT(
+ spawned_test_server()->host_port_pair().host(), expiry,
+ true /* enforce */, GURL("https://example-report.test"));
+ MockExpectCTReporter reporter;
+ transport_security_state_->SetExpectCTReporter(&reporter);
+
+ EXPECT_CALL(*ct_policy_enforcer_,
+ DoesConformToCertPolicy(server_cert.get(), _, _))
+ .WillRepeatedly(
+ Return(ct::CertPolicyCompliance::CERT_POLICY_NOT_ENOUGH_SCTS));
+
+ SSLConfig ssl_config;
+ int rv;
+ ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv));
+ SSLInfo ssl_info;
+ ASSERT_TRUE(sock_->GetSSLInfo(&ssl_info));
+
+ EXPECT_THAT(rv, IsError(ERR_CERTIFICATE_TRANSPARENCY_REQUIRED));
+ EXPECT_TRUE(ssl_info.cert_status &
+ CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED);
+ EXPECT_TRUE(sock_->IsConnected());
+
+ EXPECT_EQ(1u, reporter.num_failures());
+ EXPECT_EQ(GURL("https://example-report.test"), reporter.report_uri());
+ EXPECT_EQ(ssl_info.unverified_cert.get(),
+ reporter.served_certificate_chain());
+ EXPECT_EQ(ssl_info.cert.get(), reporter.validated_certificate_chain());
+ EXPECT_EQ(0u, reporter.signed_certificate_timestamps().size());
+
+ EXPECT_CALL(*ct_policy_enforcer_,
+ DoesConformToCertPolicy(server_cert.get(), _, _))
+ .WillRepeatedly(
+ Return(ct::CertPolicyCompliance::CERT_POLICY_NOT_DIVERSE_SCTS));
+ ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv));
+ ASSERT_TRUE(sock_->GetSSLInfo(&ssl_info));
+
+ EXPECT_THAT(rv, IsError(ERR_CERTIFICATE_TRANSPARENCY_REQUIRED));
+ EXPECT_TRUE(ssl_info.cert_status &
+ CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED);
+ EXPECT_TRUE(sock_->IsConnected());
+
+ EXPECT_EQ(2u, reporter.num_failures());
+ EXPECT_EQ(GURL("https://example-report.test"), reporter.report_uri());
+ EXPECT_EQ(ssl_info.unverified_cert.get(),
+ reporter.served_certificate_chain());
+ EXPECT_EQ(ssl_info.cert.get(), reporter.validated_certificate_chain());
+ EXPECT_EQ(0u, reporter.signed_certificate_timestamps().size());
+
+ // If the connection is CT compliant, then there should be no socket error nor
+ // a report.
+ EXPECT_CALL(*ct_policy_enforcer_,
+ DoesConformToCertPolicy(server_cert.get(), _, _))
+ .WillRepeatedly(
+ Return(ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS));
+ ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv));
+ ASSERT_TRUE(sock_->GetSSLInfo(&ssl_info));
+
+ EXPECT_EQ(net::OK, rv);
+ EXPECT_FALSE(ssl_info.cert_status &
+ CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED);
+ EXPECT_TRUE(sock_->IsConnected());
+ EXPECT_EQ(2u, reporter.num_failures());
+
+ EXPECT_CALL(*ct_policy_enforcer_,
+ DoesConformToCertPolicy(server_cert.get(), _, _))
+ .WillRepeatedly(
+ Return(ct::CertPolicyCompliance::CERT_POLICY_BUILD_NOT_TIMELY));
+ ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv));
+ ASSERT_TRUE(sock_->GetSSLInfo(&ssl_info));
+
+ EXPECT_EQ(net::OK, rv);
+ EXPECT_FALSE(ssl_info.cert_status &
+ CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED);
+ EXPECT_TRUE(sock_->IsConnected());
+ EXPECT_EQ(2u, reporter.num_failures());
+}
+
// When both HPKP and CT are required for a host, and both fail, the more
// serious error is that the HPKP pin validation failed.
TEST_F(SSLClientSocketTest, PKPMoreImportantThanCT) {
« no previous file with comments | « net/socket/ssl_client_socket_impl.cc ('k') | net/spdy/chromium/spdy_session.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698