summaryrefslogtreecommitdiffstats
path: root/net/socket
diff options
context:
space:
mode:
authorwtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-28 01:18:10 +0000
committerwtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-28 01:18:10 +0000
commit17a60a5a757ff61b996ca0ce0ebc2dc91ec5c9a9 (patch)
tree379f4c97f42050fa4fac1a6c15b02d33fa91c794 /net/socket
parent53a663c3e9be86ebc3368680e6e2e93b20ef4418 (diff)
downloadchromium_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.cc4
-rw-r--r--net/socket/socket_test_util.h3
-rw-r--r--net/socket/ssl_client_socket_mac.cc2
-rw-r--r--net/socket/ssl_client_socket_nss.cc2
-rw-r--r--net/socket/ssl_client_socket_openssl.cc2
-rw-r--r--net/socket/ssl_client_socket_pool_unittest.cc89
-rw-r--r--net/socket/ssl_client_socket_unittest.cc7
-rw-r--r--net/socket/ssl_client_socket_win.cc2
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);