diff options
author | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-28 01:18:10 +0000 |
---|---|---|
committer | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-28 01:18:10 +0000 |
commit | 17a60a5a757ff61b996ca0ce0ebc2dc91ec5c9a9 (patch) | |
tree | 379f4c97f42050fa4fac1a6c15b02d33fa91c794 /net/socket | |
parent | 53a663c3e9be86ebc3368680e6e2e93b20ef4418 (diff) | |
download | chromium_src-17a60a5a757ff61b996ca0ce0ebc2dc91ec5c9a9.zip chromium_src-17a60a5a757ff61b996ca0ce0ebc2dc91ec5c9a9.tar.gz chromium_src-17a60a5a757ff61b996ca0ce0ebc2dc91ec5c9a9.tar.bz2 |
Disable SPDY IP pooling for SSL connections with client authentication.
Add a "bool client_cert_sent" member to SSLInfo to extract this info
from SSLClientSocket.
R=rtenneti@chromium.org
BUG=101778
TEST=new unit test
Review URL: http://codereview.chromium.org/8401024
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@107671 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/socket')
-rw-r--r-- | net/socket/socket_test_util.cc | 4 | ||||
-rw-r--r-- | net/socket/socket_test_util.h | 3 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_mac.cc | 2 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_nss.cc | 2 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_openssl.cc | 2 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_pool_unittest.cc | 89 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_unittest.cc | 7 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_win.cc | 2 |
8 files changed, 107 insertions, 4 deletions
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc index b815a9f..8191bbe 100644 --- a/net/socket/socket_test_util.cc +++ b/net/socket/socket_test_util.cc @@ -239,6 +239,7 @@ SSLSocketDataProvider::SSLSocketDataProvider(bool async, int result) : connect(async, result), next_proto_status(SSLClientSocket::kNextProtoUnsupported), was_npn_negotiated(false), + client_cert_sent(false), cert_request_info(NULL) { } @@ -1133,7 +1134,8 @@ base::TimeDelta MockSSLClientSocket::GetConnectTimeMicros() const { void MockSSLClientSocket::GetSSLInfo(net::SSLInfo* ssl_info) { ssl_info->Reset(); - ssl_info->cert = data_->cert_; + ssl_info->cert = data_->cert; + ssl_info->client_cert_sent = data_->client_cert_sent; } void MockSSLClientSocket::GetSSLCertRequestInfo( diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h index 7e69da8..cc90516 100644 --- a/net/socket/socket_test_util.h +++ b/net/socket/socket_test_util.h @@ -264,8 +264,9 @@ struct SSLSocketDataProvider { SSLClientSocket::NextProtoStatus next_proto_status; std::string next_proto; bool was_npn_negotiated; + bool client_cert_sent; net::SSLCertRequestInfo* cert_request_info; - scoped_refptr<X509Certificate> cert_; + scoped_refptr<X509Certificate> cert; }; // A DataProvider where the client must write a request before the reads (e.g. diff --git a/net/socket/ssl_client_socket_mac.cc b/net/socket/ssl_client_socket_mac.cc index ed6ec77..77ba0cf 100644 --- a/net/socket/ssl_client_socket_mac.cc +++ b/net/socket/ssl_client_socket_mac.cc @@ -730,6 +730,8 @@ void SSLClientSocketMac::GetSSLInfo(SSLInfo* ssl_info) { ssl_info->public_key_hashes = server_cert_verify_result_.public_key_hashes; ssl_info->is_issued_by_known_root = server_cert_verify_result_.is_issued_by_known_root; + ssl_info->client_cert_sent = + ssl_config_.send_client_cert && ssl_config_.client_cert; // security info SSLCipherSuite suite; diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc index 81f172d..bee836e 100644 --- a/net/socket/ssl_client_socket_nss.cc +++ b/net/socket/ssl_client_socket_nss.cc @@ -499,6 +499,8 @@ void SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) { } ssl_info->is_issued_by_known_root = server_cert_verify_result_->is_issued_by_known_root; + ssl_info->client_cert_sent = + ssl_config_.send_client_cert && ssl_config_.client_cert; PRUint16 cipher_suite = SSLConnectionStatusToCipherSuite(ssl_connection_status_); diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc index eeea188..fa7f2a1 100644 --- a/net/socket/ssl_client_socket_openssl.cc +++ b/net/socket/ssl_client_socket_openssl.cc @@ -561,6 +561,8 @@ void SSLClientSocketOpenSSL::GetSSLInfo(SSLInfo* ssl_info) { server_cert_verify_result_.is_issued_by_known_root; ssl_info->public_key_hashes = server_cert_verify_result_.public_key_hashes; + ssl_info->client_cert_sent = + ssl_config_.send_client_cert && ssl_config_.client_cert; const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl_); CHECK(cipher); diff --git a/net/socket/ssl_client_socket_pool_unittest.cc b/net/socket/ssl_client_socket_pool_unittest.cc index ce2ca40..d10b2e0 100644 --- a/net/socket/ssl_client_socket_pool_unittest.cc +++ b/net/socket/ssl_client_socket_pool_unittest.cc @@ -690,7 +690,7 @@ TEST_F(SSLClientSocketPoolTest, IPPooling) { StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); socket_factory_.AddSocketDataProvider(&data); SSLSocketDataProvider ssl(true, OK); - ssl.cert_ = X509Certificate::CreateFromBytes( + ssl.cert = X509Certificate::CreateFromBytes( reinterpret_cast<const char*>(webkit_der), sizeof(webkit_der)); ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated; ssl.next_proto = "spdy/2"; @@ -719,7 +719,7 @@ TEST_F(SSLClientSocketPoolTest, IPPooling) { EXPECT_EQ(SSLClientSocket::NextProtoFromString(proto), SSLClientSocket::kProtoSPDY2); - // TODO(rtenneti): MockClientSocket::GetPeerAddress return's 0 as the port + // TODO(rtenneti): MockClientSocket::GetPeerAddress returns 0 as the port // number. Fix it to return port 80 and then use GetPeerAddress to AddAlias. const addrinfo* address = test_hosts[0].addresses.head(); SpdySessionPoolPeer pool_peer(session_->spdy_session_pool()); @@ -738,6 +738,91 @@ TEST_F(SSLClientSocketPoolTest, IPPooling) { session_->spdy_session_pool()->CloseAllSessions(); } +// Verifies that an SSL connection with client authentication disables SPDY IP +// pooling. +TEST_F(SSLClientSocketPoolTest, IPPoolingClientCert) { + const int kTestPort = 80; + struct TestHosts { + std::string name; + std::string iplist; + HostPortProxyPair pair; + AddressList addresses; + } test_hosts[] = { + { "www.webkit.org", "192.0.2.33,192.168.0.1,192.168.0.5" }, + { "js.webkit.org", "192.168.0.4,192.168.0.1,192.0.2.33" }, + }; + + TestOldCompletionCallback callback; + int rv; + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_hosts); i++) { + host_resolver_.rules()->AddIPLiteralRule(test_hosts[i].name, + test_hosts[i].iplist, ""); + + // This test requires that the HostResolver cache be populated. Normal + // code would have done this already, but we do it manually. + HostResolver::RequestInfo info(HostPortPair(test_hosts[i].name, kTestPort)); + rv = host_resolver_.Resolve(info, &test_hosts[i].addresses, &callback, + NULL, BoundNetLog()); + EXPECT_EQ(OK, callback.GetResult(rv)); + + // Setup a HostPortProxyPair + test_hosts[i].pair = HostPortProxyPair( + HostPortPair(test_hosts[i].name, kTestPort), ProxyServer::Direct()); + } + + MockRead reads[] = { + MockRead(true, ERR_IO_PENDING), + }; + StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); + socket_factory_.AddSocketDataProvider(&data); + SSLSocketDataProvider ssl(true, OK); + ssl.cert = X509Certificate::CreateFromBytes( + reinterpret_cast<const char*>(webkit_der), sizeof(webkit_der)); + ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated; + ssl.next_proto = "spdy/2"; + ssl.client_cert_sent = true; + socket_factory_.AddSSLSocketDataProvider(&ssl); + + CreatePool(true /* tcp pool */, false, false); + scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT, + true); + + scoped_ptr<ClientSocketHandle> handle(new ClientSocketHandle()); + rv = handle->Init( + "a", params, MEDIUM, &callback, pool_.get(), BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, rv); + EXPECT_FALSE(handle->is_initialized()); + EXPECT_FALSE(handle->socket()); + + EXPECT_EQ(OK, callback.WaitForResult()); + EXPECT_TRUE(handle->is_initialized()); + EXPECT_TRUE(handle->socket()); + + SSLClientSocket* ssl_socket = static_cast<SSLClientSocket*>(handle->socket()); + EXPECT_TRUE(ssl_socket->was_npn_negotiated()); + std::string proto; + ssl_socket->GetNextProto(&proto); + EXPECT_EQ(SSLClientSocket::NextProtoFromString(proto), + SSLClientSocket::kProtoSPDY2); + + // TODO(rtenneti): MockClientSocket::GetPeerAddress returns 0 as the port + // number. Fix it to return port 80 and then use GetPeerAddress to AddAlias. + const addrinfo* address = test_hosts[0].addresses.head(); + SpdySessionPoolPeer pool_peer(session_->spdy_session_pool()); + pool_peer.AddAlias(address, test_hosts[0].pair); + + scoped_refptr<SpdySession> spdy_session; + rv = session_->spdy_session_pool()->GetSpdySessionFromSocket( + test_hosts[0].pair, handle.release(), BoundNetLog(), 0, + &spdy_session, true); + EXPECT_EQ(0, rv); + + EXPECT_TRUE(session_->spdy_session_pool()->HasSession(test_hosts[0].pair)); + EXPECT_FALSE(session_->spdy_session_pool()->HasSession(test_hosts[1].pair)); + + session_->spdy_session_pool()->CloseAllSessions(); +} + // It would be nice to also test the timeouts in SSLClientSocketPool. } // namespace diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc index ca659b0..88af817 100644 --- a/net/socket/ssl_client_socket_unittest.cc +++ b/net/socket/ssl_client_socket_unittest.cc @@ -300,6 +300,13 @@ TEST_F(SSLClientSocketTest, ConnectClientAuthSendNullCert) { log.GetEntries(&entries); EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1)); + // We responded to the server's certificate request with a Certificate + // message with no client certificate in it. ssl_info.client_cert_sent + // should be false in this case. + net::SSLInfo ssl_info; + sock->GetSSLInfo(&ssl_info); + EXPECT_FALSE(ssl_info.client_cert_sent); + sock->Disconnect(); EXPECT_FALSE(sock->IsConnected()); } diff --git a/net/socket/ssl_client_socket_win.cc b/net/socket/ssl_client_socket_win.cc index 3baeffb..13fd101 100644 --- a/net/socket/ssl_client_socket_win.cc +++ b/net/socket/ssl_client_socket_win.cc @@ -436,6 +436,8 @@ void SSLClientSocketWin::GetSSLInfo(SSLInfo* ssl_info) { ssl_info->public_key_hashes = server_cert_verify_result_.public_key_hashes; ssl_info->is_issued_by_known_root = server_cert_verify_result_.is_issued_by_known_root; + ssl_info->client_cert_sent = + ssl_config_.send_client_cert && ssl_config_.client_cert; SecPkgContext_ConnectionInfo connection_info; SECURITY_STATUS status = QueryContextAttributes( &ctxt_, SECPKG_ATTR_CONNECTION_INFO, &connection_info); |