Fix crash bug in new SSLClientSocketPool.
We also need to push additional error state out of the SSLClientSocketPool on a ERR_SSL_CLIENT_AUTH_CERT_NEEDED error.
BUG=49197
TEST=no crash when visiting https://foafssl.org/srv/idp?authreqissuer=http://foaf.me/index.php
Review URL: http://codereview.chromium.org/2827053
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@52693 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index 7f9b696..fb5f8012 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -866,7 +866,7 @@
if (result == ERR_PROXY_AUTH_REQUESTED) {
DCHECK(!ssl_started);
const HttpResponseInfo& tunnel_auth_response =
- connection_->tunnel_auth_response_info();
+ connection_->ssl_error_response_info();
response_.headers = tunnel_auth_response.headers;
response_.auth_challenge = tunnel_auth_response.auth_challenge;
@@ -924,8 +924,11 @@
}
}
- if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED)
+ if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
+ response_.cert_request_info =
+ connection_->ssl_error_response_info().cert_request_info;
return HandleCertificateRequest(result);
+ }
if (result < 0)
return HandleSSLHandshakeError(result);
@@ -1055,6 +1058,10 @@
<< " during SSL renegotiation";
result = ERR_CERT_ERROR_IN_SSL_RENEGOTIATION;
} else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
+ response_.cert_request_info = new SSLCertRequestInfo;
+ SSLClientSocket* ssl_socket =
+ static_cast<SSLClientSocket*>(connection_->socket());
+ ssl_socket->GetSSLCertRequestInfo(response_.cert_request_info);
result = HandleCertificateRequest(result);
if (result == OK)
return result;
@@ -1498,24 +1505,10 @@
}
int HttpNetworkTransaction::HandleCertificateRequest(int error) {
- // Assert that the socket did not send a client certificate.
- // Note: If we got a reused socket, it was created with some other
- // transaction's ssl_config_, so we need to disable this assertion. We can
- // get a certificate request on a reused socket when the server requested
- // renegotiation (rehandshake).
- // TODO(wtc): add a GetSSLParams method to SSLClientSocket so we can query
- // the SSL parameters it was created with and get rid of the reused_socket_
- // test.
- DCHECK(reused_socket_ || !ssl_config_.send_client_cert);
-
- response_.cert_request_info = new SSLCertRequestInfo;
- SSLClientSocket* ssl_socket =
- static_cast<SSLClientSocket*>(connection_->socket());
- ssl_socket->GetSSLCertRequestInfo(response_.cert_request_info);
-
// Close the connection while the user is selecting a certificate to send
// to the server.
- connection_->socket()->Disconnect();
+ if (connection_->socket())
+ connection_->socket()->Disconnect();
connection_->Reset();
// If the user selected one of the certificate in client_certs for this
diff --git a/net/socket/client_socket_handle.cc b/net/socket/client_socket_handle.cc
index 7093e14..de2fd94c 100644
--- a/net/socket/client_socket_handle.cc
+++ b/net/socket/client_socket_handle.cc
@@ -58,7 +58,7 @@
void ClientSocketHandle::ResetErrorState() {
is_ssl_error_ = false;
- tunnel_auth_response_info_ = HttpResponseInfo();
+ ssl_error_response_info_ = HttpResponseInfo();
}
LoadState ClientSocketHandle::GetLoadState() const {
diff --git a/net/socket/client_socket_handle.h b/net/socket/client_socket_handle.h
index b8e6cc34..7fdf784 100644
--- a/net/socket/client_socket_handle.h
+++ b/net/socket/client_socket_handle.h
@@ -104,27 +104,28 @@
void set_socket(ClientSocket* s) { socket_.reset(s); }
void set_idle_time(base::TimeDelta idle_time) { idle_time_ = idle_time; }
void set_pool_id(int id) { pool_id_ = id; }
- void set_tunnel_auth_response_info(
- const scoped_refptr<HttpResponseHeaders>& headers,
- const scoped_refptr<AuthChallengeInfo>& auth_challenge) {
- tunnel_auth_response_info_.headers = headers;
- tunnel_auth_response_info_.auth_challenge = auth_challenge;
- }
void set_is_ssl_error(bool is_ssl_error) { is_ssl_error_ = is_ssl_error; }
+ void set_ssl_error_response_info(const HttpResponseInfo& ssl_error_state) {
+ ssl_error_response_info_ = ssl_error_state;
+ }
+
+ // Only valid if there is no |socket_|.
+ bool is_ssl_error() const {
+ DCHECK(socket_.get() == NULL);
+ return is_ssl_error_;
+ }
+ // On an ERR_PROXY_AUTH_REQUESTED error, the |headers| and |auth_challenge|
+ // fields are filled in. On an ERR_SSL_CLIENT_AUTH_CERT_NEEDED error,
+ // the |cert_request_info| field is set.
+ const HttpResponseInfo& ssl_error_response_info() const {
+ return ssl_error_response_info_;
+ }
// These may only be used if is_initialized() is true.
const std::string& group_name() const { return group_name_; }
int id() const { return pool_id_; }
ClientSocket* socket() { return socket_.get(); }
ClientSocket* release_socket() { return socket_.release(); }
- const HttpResponseInfo& tunnel_auth_response_info() const {
- return tunnel_auth_response_info_;
- }
- // Only valid if there is no |socket_|.
- bool is_ssl_error() const {
- DCHECK(socket_.get() == NULL);
- return is_ssl_error_;
- }
bool is_reused() const { return is_reused_; }
base::TimeDelta idle_time() const { return idle_time_; }
SocketReuseType reuse_type() const {
@@ -176,7 +177,7 @@
base::TimeDelta idle_time_;
int pool_id_; // See ClientSocketPool::ReleaseSocket() for an explanation.
bool is_ssl_error_;
- HttpResponseInfo tunnel_auth_response_info_;
+ HttpResponseInfo ssl_error_response_info_;
base::TimeTicks init_time_;
base::TimeDelta setup_time_;
diff --git a/net/socket/client_socket_pool_base_unittest.cc b/net/socket/client_socket_pool_base_unittest.cc
index 9686794..55f1949 100644
--- a/net/socket/client_socket_pool_base_unittest.cc
+++ b/net/socket/client_socket_pool_base_unittest.cc
@@ -155,8 +155,9 @@
if (store_additional_error_state_) {
// Set all of the additional error state fields in some way.
handle->set_is_ssl_error(true);
- scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(""));
- handle->set_tunnel_auth_response_info(headers, NULL);
+ HttpResponseInfo info;
+ info.headers = new HttpResponseHeaders("");
+ handle->set_ssl_error_response_info(info);
}
}
@@ -626,14 +627,15 @@
TestSocketRequest req(&request_order_, &completion_count_);
// Set the additional error state members to ensure that they get cleared.
req.handle()->set_is_ssl_error(true);
- scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(""));
- req.handle()->set_tunnel_auth_response_info(headers, NULL);
+ HttpResponseInfo info;
+ info.headers = new HttpResponseHeaders("");
+ req.handle()->set_ssl_error_response_info(info);
EXPECT_EQ(ERR_CONNECTION_FAILED, req.handle()->Init("a", params_,
kDefaultPriority, &req,
pool_, log.bound()));
EXPECT_FALSE(req.handle()->socket());
EXPECT_FALSE(req.handle()->is_ssl_error());
- EXPECT_TRUE(req.handle()->tunnel_auth_response_info().headers.get() == NULL);
+ EXPECT_TRUE(req.handle()->ssl_error_response_info().headers.get() == NULL);
EXPECT_EQ(3u, log.entries().size());
EXPECT_TRUE(LogContainsBeginEvent(
@@ -1386,14 +1388,15 @@
CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
// Set the additional error state members to ensure that they get cleared.
req.handle()->set_is_ssl_error(true);
- scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(""));
- req.handle()->set_tunnel_auth_response_info(headers, NULL);
+ HttpResponseInfo info;
+ info.headers = new HttpResponseHeaders("");
+ req.handle()->set_ssl_error_response_info(info);
EXPECT_EQ(ERR_IO_PENDING, req.handle()->Init("a", params_, kDefaultPriority,
&req, pool_, log.bound()));
EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", req.handle()));
EXPECT_EQ(ERR_CONNECTION_FAILED, req.WaitForResult());
EXPECT_FALSE(req.handle()->is_ssl_error());
- EXPECT_TRUE(req.handle()->tunnel_auth_response_info().headers.get() == NULL);
+ EXPECT_TRUE(req.handle()->ssl_error_response_info().headers.get() == NULL);
EXPECT_EQ(3u, log.entries().size());
EXPECT_TRUE(LogContainsBeginEvent(
@@ -1598,7 +1601,7 @@
EXPECT_FALSE(req.handle()->is_initialized());
EXPECT_FALSE(req.handle()->socket());
EXPECT_TRUE(req.handle()->is_ssl_error());
- EXPECT_FALSE(req.handle()->tunnel_auth_response_info().headers.get() == NULL);
+ EXPECT_FALSE(req.handle()->ssl_error_response_info().headers.get() == NULL);
req.handle()->Reset();
}
@@ -1615,7 +1618,7 @@
EXPECT_FALSE(req.handle()->is_initialized());
EXPECT_FALSE(req.handle()->socket());
EXPECT_TRUE(req.handle()->is_ssl_error());
- EXPECT_FALSE(req.handle()->tunnel_auth_response_info().headers.get() == NULL);
+ EXPECT_FALSE(req.handle()->ssl_error_response_info().headers.get() == NULL);
req.handle()->Reset();
}
@@ -1861,7 +1864,7 @@
EXPECT_FALSE(req.handle()->is_initialized());
EXPECT_FALSE(req.handle()->socket());
EXPECT_TRUE(req.handle()->is_ssl_error());
- EXPECT_FALSE(req.handle()->tunnel_auth_response_info().headers.get() == NULL);
+ EXPECT_FALSE(req.handle()->ssl_error_response_info().headers.get() == NULL);
}
// http://crbug.com/44724 regression test.
diff --git a/net/socket/ssl_client_socket_pool.cc b/net/socket/ssl_client_socket_pool.cc
index cfe3df49..d7f18e9 100644
--- a/net/socket/ssl_client_socket_pool.cc
+++ b/net/socket/ssl_client_socket_pool.cc
@@ -229,15 +229,11 @@
return OK;
}
- if (result == ERR_PROXY_AUTH_REQUESTED) {
- // Extract the information needed to prompt for the proxy authentication.
- // so that when ClientSocketPoolBaseHelper calls |GetAdditionalErrorState|,
- // we can easily set the state.
- const HttpResponseInfo* tunnel_response = tunnel_socket->GetResponseInfo();
-
- http_auth_response_headers_ = tunnel_response->headers;
- http_auth_auth_challenge_ = tunnel_response->auth_challenge;
- }
+ // Extract the information needed to prompt for the proxy authentication.
+ // so that when ClientSocketPoolBaseHelper calls |GetAdditionalErrorState|,
+ // we can easily set the state.
+ if (result == ERR_PROXY_AUTH_REQUESTED)
+ error_response_info_ = *tunnel_socket->GetResponseInfo();
if (result < 0)
return result;
@@ -255,9 +251,7 @@
}
void SSLConnectJob::GetAdditionalErrorState(ClientSocketHandle * handle) {
- if (http_auth_response_headers_.get() != NULL)
- handle->set_tunnel_auth_response_info(http_auth_response_headers_,
- http_auth_auth_challenge_);
+ handle->set_ssl_error_response_info(error_response_info_);
if (!ssl_connect_start_time_.is_null())
handle->set_is_ssl_error(true);
}
@@ -313,8 +307,13 @@
base::TimeDelta::FromMinutes(10),
100);
}
- if (result == OK || IsCertificateError(result))
+
+ if (result == OK || IsCertificateError(result)) {
set_socket(ssl_socket_.release());
+ } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
+ error_response_info_.cert_request_info = new SSLCertRequestInfo;
+ ssl_socket_->GetSSLCertRequestInfo(error_response_info_.cert_request_info);
+ }
return result;
}
diff --git a/net/socket/ssl_client_socket_pool.h b/net/socket/ssl_client_socket_pool.h
index 48bba9c..fd5bbb3f 100644
--- a/net/socket/ssl_client_socket_pool.h
+++ b/net/socket/ssl_client_socket_pool.h
@@ -141,8 +141,7 @@
// The time the DoSSLConnect() method was called.
base::TimeTicks ssl_connect_start_time_;
- scoped_refptr<HttpResponseHeaders> http_auth_response_headers_;
- scoped_refptr<AuthChallengeInfo> http_auth_auth_challenge_;
+ HttpResponseInfo error_response_info_;
DISALLOW_COPY_AND_ASSIGN(SSLConnectJob);
};
diff --git a/net/socket/ssl_client_socket_pool_unittest.cc b/net/socket/ssl_client_socket_pool_unittest.cc
index 30ff5da..ca864c9a 100644
--- a/net/socket/ssl_client_socket_pool_unittest.cc
+++ b/net/socket/ssl_client_socket_pool_unittest.cc
@@ -585,7 +585,7 @@
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
EXPECT_FALSE(handle.is_ssl_error());
- const HttpResponseInfo& tunnel_info = handle.tunnel_auth_response_info();
+ const HttpResponseInfo& tunnel_info = handle.ssl_error_response_info();
EXPECT_EQ(tunnel_info.headers->response_code(), 407);
}
@@ -633,7 +633,7 @@
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
EXPECT_FALSE(handle.is_ssl_error());
- const HttpResponseInfo& tunnel_info = handle.tunnel_auth_response_info();
+ const HttpResponseInfo& tunnel_info = handle.ssl_error_response_info();
EXPECT_EQ(tunnel_info.headers->response_code(), 407);
params->http_proxy_params()->auth_controller()->ResetAuth(std::wstring(),
@@ -698,7 +698,7 @@
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
EXPECT_FALSE(handle.is_ssl_error());
- const HttpResponseInfo& tunnel_info = handle.tunnel_auth_response_info();
+ const HttpResponseInfo& tunnel_info = handle.ssl_error_response_info();
EXPECT_EQ(tunnel_info.headers->response_code(), 407);
params->http_proxy_params()->auth_controller()->ResetAuth(std::wstring(),