Chromium Code Reviews| 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 b0530783057032e98d9bea7a36d83126af4a310b..2da0913a5a0efdf6b97b90845577c5cbccd22117 100644 |
| --- a/net/socket/ssl_client_socket_unittest.cc |
| +++ b/net/socket/ssl_client_socket_unittest.cc |
| @@ -708,6 +708,12 @@ class MockCTPolicyEnforcer : public CTPolicyEnforcer { |
| const BoundNetLog&)); |
| }; |
| +class MockRequireCTDelegate : public TransportSecurityState::RequireCTDelegate { |
| + public: |
| + MOCK_METHOD1(IsCTRequiredForHost, |
| + CTRequirementLevel(const std::string& host)); |
| +}; |
| + |
| class SSLClientSocketTest : public PlatformTest { |
| public: |
| SSLClientSocketTest() |
| @@ -3353,4 +3359,99 @@ TEST_F(SSLClientSocketTest, PKPEnforced) { |
| EXPECT_FALSE(ssl_info.pkp_bypassed); |
| } |
| +// Test that when CT is required (in this case, by the delegate), the |
| +// absence of CT information is a socket error. |
| +TEST_F(SSLClientSocketTest, CTIsRequired) { |
| + 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 CT |
| + MockRequireCTDelegate require_ct_delegate; |
| + transport_security_state_->SetRequireCTDelegate(&require_ct_delegate); |
| + EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(_)) |
| + .WillRepeatedly(Return(TransportSecurityState::RequireCTDelegate:: |
| + CTRequirementLevel::NOT_REQUIRED)); |
|
davidben
2016/06/23 19:51:43
Is this line needed?
Ryan Sleevi
2016/06/23 21:38:31
Same comment as from other; sets up a default expe
|
| + EXPECT_CALL( |
| + require_ct_delegate, |
| + IsCTRequiredForHost(spawned_test_server()->host_port_pair().host())) |
| + .WillRepeatedly(Return(TransportSecurityState::RequireCTDelegate:: |
| + CTRequirementLevel::REQUIRED)); |
| + 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_EQ(ERR_CERTIFICATE_TRANSPARENCY_REQUIRED, rv); |
| + EXPECT_TRUE(ssl_info.cert_status & |
| + CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED); |
| + EXPECT_TRUE(sock_->IsConnected()); |
| +} |
| + |
| +// 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) { |
| + SpawnedTestServer::SSLOptions ssl_options; |
| + ASSERT_TRUE(StartTestServer(ssl_options)); |
| + scoped_refptr<X509Certificate> server_cert = |
| + spawned_test_server()->GetCertificate(); |
| + |
| + // Certificate is trusted, but chains to a public root that doesn't match the |
| + // pin hashes. |
| + 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 HPKP. |
| + HashValueVector expected_hashes = MakeHashValueVector(1); |
| + context_.transport_security_state->AddHPKP( |
| + spawned_test_server()->host_port_pair().host(), |
| + base::Time::Now() + base::TimeDelta::FromSeconds(10000), true, |
| + expected_hashes, GURL()); |
| + |
| + // Set up CT. |
| + MockRequireCTDelegate require_ct_delegate; |
| + transport_security_state_->SetRequireCTDelegate(&require_ct_delegate); |
| + EXPECT_CALL(require_ct_delegate, IsCTRequiredForHost(_)) |
| + .WillRepeatedly(Return(TransportSecurityState::RequireCTDelegate:: |
| + CTRequirementLevel::NOT_REQUIRED)); |
|
davidben
2016/06/23 19:51:43
Ditto.
|
| + EXPECT_CALL( |
| + require_ct_delegate, |
| + IsCTRequiredForHost(spawned_test_server()->host_port_pair().host())) |
| + .WillRepeatedly(Return(TransportSecurityState::RequireCTDelegate:: |
| + CTRequirementLevel::REQUIRED)); |
| + 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_EQ(ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN, rv); |
| + EXPECT_TRUE(ssl_info.cert_status & CERT_STATUS_PINNED_KEY_MISSING); |
| + EXPECT_TRUE(ssl_info.cert_status & |
| + CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED); |
| + EXPECT_TRUE(sock_->IsConnected()); |
| +} |
| + |
| } // namespace net |