summaryrefslogtreecommitdiffstats
path: root/net/http/http_network_transaction.cc
diff options
context:
space:
mode:
authormarkus@chromium.org <markus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-30 21:09:30 +0000
committermarkus@chromium.org <markus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-30 21:09:30 +0000
commit3fd49f9bdbe56a9648cddc015bdb8bac02fe1a7b (patch)
treeee0a2b866a939e678bedf426e858871706c41bff /net/http/http_network_transaction.cc
parentf463787972e54c126d23d263613634d5fd777789 (diff)
downloadchromium_src-3fd49f9bdbe56a9648cddc015bdb8bac02fe1a7b.zip
chromium_src-3fd49f9bdbe56a9648cddc015bdb8bac02fe1a7b.tar.gz
chromium_src-3fd49f9bdbe56a9648cddc015bdb8bac02fe1a7b.tar.bz2
Change the bad-certificate handler for SSL (using NSS) to return an
error. This requires a few additional changes in the rest of the code. In particular, we now have to teach HttpNetworkTransaction about how to restart connections with bad certificates. This was originally intended to be done by ReconnectIgnoringLastError(), but that API turns out be very difficult to implement in the SSLClientSocket. So, instead, we just create a completely new SSLClientSocket. We also have to be careful to store a copy of the certificate from within the bad-certificate handler, as it won't be available by the time GetSSLInfo() is called. And we fix a bug that would cause us to erroneously talk SSL on reconnected TCP sockets, even though we were still supposed to negotiate a proxy tunnel first. Review URL: http://codereview.chromium.org/43115 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@12809 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/http/http_network_transaction.cc')
-rw-r--r--net/http/http_network_transaction.cc84
1 files changed, 44 insertions, 40 deletions
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index c549cb3..7ab3021 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -80,9 +80,13 @@ int HttpNetworkTransaction::Start(const HttpRequestInfo* request_info,
int HttpNetworkTransaction::RestartIgnoringLastError(
CompletionCallback* callback) {
- // TODO(wtc): If the connection is no longer alive, call
- // connection_.socket()->ReconnectIgnoringLastError().
- next_state_ = STATE_WRITE_HEADERS;
+ if (connection_.socket()->IsConnected()) {
+ next_state_ = STATE_WRITE_HEADERS;
+ } else {
+ connection_.set_socket(NULL);
+ connection_.Reset();
+ next_state_ = STATE_INIT_CONNECTION;
+ }
int rv = DoLoop(OK);
if (rv == ERR_IO_PENDING)
user_callback_ = callback;
@@ -249,7 +253,7 @@ LoadState HttpNetworkTransaction::GetLoadState() const {
return LOAD_STATE_RESOLVING_PROXY_FOR_URL;
case STATE_RESOLVE_HOST_COMPLETE:
return LOAD_STATE_RESOLVING_HOST;
- case STATE_CONNECT_COMPLETE:
+ case STATE_TCP_CONNECT_COMPLETE:
return LOAD_STATE_CONNECTING;
case STATE_WRITE_HEADERS_COMPLETE:
case STATE_WRITE_BODY_COMPLETE:
@@ -408,23 +412,23 @@ int HttpNetworkTransaction::DoLoop(int result) {
rv = DoResolveHostComplete(rv);
TRACE_EVENT_END("http.resolve_host", request_, request_->url.spec());
break;
- case STATE_CONNECT:
+ case STATE_TCP_CONNECT:
DCHECK_EQ(OK, rv);
- TRACE_EVENT_BEGIN("http.connect", request_, request_->url.spec());
- rv = DoConnect();
+ TRACE_EVENT_BEGIN("http.tcp_connect", request_, request_->url.spec());
+ rv = DoTCPConnect();
break;
- case STATE_CONNECT_COMPLETE:
- rv = DoConnectComplete(rv);
- TRACE_EVENT_END("http.connect", request_, request_->url.spec());
+ case STATE_TCP_CONNECT_COMPLETE:
+ rv = DoTCPConnectComplete(rv);
+ TRACE_EVENT_END("http.tcp_connect", request_, request_->url.spec());
break;
- case STATE_SSL_CONNECT_OVER_TUNNEL:
+ case STATE_SSL_CONNECT:
DCHECK_EQ(OK, rv);
- TRACE_EVENT_BEGIN("http.ssl_tunnel", request_, request_->url.spec());
- rv = DoSSLConnectOverTunnel();
+ TRACE_EVENT_BEGIN("http.ssl_connect", request_, request_->url.spec());
+ rv = DoSSLConnect();
break;
- case STATE_SSL_CONNECT_OVER_TUNNEL_COMPLETE:
- rv = DoSSLConnectOverTunnelComplete(rv);
- TRACE_EVENT_END("http.ssl_tunnel", request_, request_->url.spec());
+ case STATE_SSL_CONNECT_COMPLETE:
+ rv = DoSSLConnectComplete(rv);
+ TRACE_EVENT_END("http.ssl_connect", request_, request_->url.spec());
break;
case STATE_WRITE_HEADERS:
DCHECK_EQ(OK, rv);
@@ -578,48 +582,42 @@ int HttpNetworkTransaction::DoResolveHostComplete(int result) {
bool ok = (result == OK);
DidFinishDnsResolutionWithStatus(ok, request_->referrer, this);
if (ok) {
- next_state_ = STATE_CONNECT;
+ next_state_ = STATE_TCP_CONNECT;
} else {
result = ReconsiderProxyAfterError(result);
}
return result;
}
-int HttpNetworkTransaction::DoConnect() {
- next_state_ = STATE_CONNECT_COMPLETE;
+int HttpNetworkTransaction::DoTCPConnect() {
+ next_state_ = STATE_TCP_CONNECT_COMPLETE;
DCHECK(!connection_.socket());
ClientSocket* s = socket_factory_->CreateTCPClientSocket(addresses_);
-
- // If we are using a direct SSL connection, then go ahead and create the SSL
- // wrapper socket now. Otherwise, we need to first issue a CONNECT request.
- if (using_ssl_ && !using_tunnel_)
- s = socket_factory_->CreateSSLClientSocket(s, request_->url.host(),
- ssl_config_);
-
connection_.set_socket(s);
return connection_.socket()->Connect(&io_callback_);
}
-int HttpNetworkTransaction::DoConnectComplete(int result) {
- if (IsCertificateError(result))
- result = HandleCertificateError(result);
-
+int HttpNetworkTransaction::DoTCPConnectComplete(int result) {
+ // If we are using a direct SSL connection, then go ahead and establish the
+ // SSL connection now. Otherwise, we need to first issue a CONNECT request.
if (result == OK) {
- next_state_ = STATE_WRITE_HEADERS;
- if (using_tunnel_)
- establishing_tunnel_ = true;
+ if (using_ssl_ && !using_tunnel_) {
+ next_state_ = STATE_SSL_CONNECT;
+ } else {
+ next_state_ = STATE_WRITE_HEADERS;
+ if (using_tunnel_)
+ establishing_tunnel_ = true;
+ }
} else {
- result = HandleSSLHandshakeError(result);
- if (result != OK)
- result = ReconsiderProxyAfterError(result);
+ result = ReconsiderProxyAfterError(result);
}
return result;
}
-int HttpNetworkTransaction::DoSSLConnectOverTunnel() {
- next_state_ = STATE_SSL_CONNECT_OVER_TUNNEL_COMPLETE;
+int HttpNetworkTransaction::DoSSLConnect() {
+ next_state_ = STATE_SSL_CONNECT_COMPLETE;
// Add a SSL socket on top of our existing transport socket.
ClientSocket* s = connection_.release_socket();
@@ -629,7 +627,7 @@ int HttpNetworkTransaction::DoSSLConnectOverTunnel() {
return connection_.socket()->Connect(&io_callback_);
}
-int HttpNetworkTransaction::DoSSLConnectOverTunnelComplete(int result) {
+int HttpNetworkTransaction::DoSSLConnectComplete(int result) {
if (IsCertificateError(result))
result = HandleCertificateError(result);
@@ -1019,7 +1017,7 @@ int HttpNetworkTransaction::DidReadResponseHeaders() {
// The proxy sent extraneous data after the headers.
return ERR_TUNNEL_CONNECTION_FAILED;
}
- next_state_ = STATE_SSL_CONNECT_OVER_TUNNEL;
+ next_state_ = STATE_SSL_CONNECT;
// Reset for the real request and response headers.
request_headers_.clear();
request_headers_bytes_sent_ = 0;
@@ -1150,6 +1148,12 @@ int HttpNetworkTransaction::HandleCertificateError(int error) {
SSLClientSocket* ssl_socket =
reinterpret_cast<SSLClientSocket*>(connection_.socket());
ssl_socket->GetSSLInfo(&response_.ssl_info);
+
+ // Add the bad certificate to the set of allowed certificates in the
+ // SSL info object. This data structure will be consulted after calling
+ // RestartIgnoringLastError(). And the user will be asked interactively
+ // before RestartIgnoringLastError() is ever called.
+ ssl_config_.allowed_bad_certs_.insert(response_.ssl_info.cert);
}
return error;
}