summaryrefslogtreecommitdiffstats
path: root/net/socket_stream/socket_stream.cc
diff options
context:
space:
mode:
authortoyoshim@chromium.org <toyoshim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-17 05:57:36 +0000
committertoyoshim@chromium.org <toyoshim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-17 05:57:36 +0000
commit700317717262a7a81f38c6850e7b1e678ad5b7b7 (patch)
tree8228342c569d48700d9f7e52c2efe61b6bad727c /net/socket_stream/socket_stream.cc
parent530cc37d1b78b56cbe42f2a341ac3282f988e1c4 (diff)
downloadchromium_src-700317717262a7a81f38c6850e7b1e678ad5b7b7.zip
chromium_src-700317717262a7a81f38c6850e7b1e678ad5b7b7.tar.gz
chromium_src-700317717262a7a81f38c6850e7b1e678ad5b7b7.tar.bz2
SSL client authentication support for secure proxy in WebSocket
BUG=83950 TEST=net_unittests Review URL: http://codereview.chromium.org/8276031 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@105769 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/socket_stream/socket_stream.cc')
-rw-r--r--net/socket_stream/socket_stream.cc77
1 files changed, 66 insertions, 11 deletions
diff --git a/net/socket_stream/socket_stream.cc b/net/socket_stream/socket_stream.cc
index 8ea686a..cb8f097 100644
--- a/net/socket_stream/socket_stream.cc
+++ b/net/socket_stream/socket_stream.cc
@@ -21,9 +21,12 @@
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/base/net_util.h"
+#include "net/base/ssl_cert_request_info.h"
#include "net/http/http_auth_handler_factory.h"
+#include "net/http/http_network_session.h"
#include "net/http/http_request_info.h"
#include "net/http/http_response_headers.h"
+#include "net/http/http_transaction_factory.h"
#include "net/http/http_util.h"
#include "net/socket/client_socket_factory.h"
#include "net/socket/socks5_client_socket.h"
@@ -132,8 +135,10 @@ void SocketStream::Connect() {
"The current MessageLoop must exist";
DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) <<
"The current MessageLoop must be TYPE_IO";
- if (context_)
- ssl_config_service()->GetSSLConfig(&ssl_config_);
+ if (context_) {
+ ssl_config_service()->GetSSLConfig(&server_ssl_config_);
+ proxy_ssl_config_ = server_ssl_config_;
+ }
DCHECK_EQ(next_state_, STATE_NONE);
AddRef(); // Released in Finish()
@@ -304,7 +309,8 @@ void SocketStream::Finish(int result) {
Release();
}
-int SocketStream::DidEstablishSSL(int result) {
+int SocketStream::DidEstablishSSL(int result, SSLConfig* ssl_config) {
+ DCHECK(ssl_config);
if (IsCertificateError(result)) {
if (socket_->IsConnectedAndIdle()) {
result = HandleCertificateError(result);
@@ -313,15 +319,15 @@ int SocketStream::DidEstablishSSL(int result) {
// if it returns cert verification error. It didn't perform
// SSLHandshake yet.
// So, we should restart establishing connection with the
- // certificate in allowed bad certificates in |ssl_config_|.
+ // certificate in allowed bad certificates in |ssl_config|.
// See also net/http/http_network_transaction.cc
// HandleCertificateError() and RestartIgnoringLastError().
SSLClientSocket* ssl_socket =
- reinterpret_cast<SSLClientSocket*>(socket_.get());
+ static_cast<SSLClientSocket*>(socket_.get());
SSLInfo ssl_info;
ssl_socket->GetSSLInfo(&ssl_info);
if (ssl_info.cert == NULL ||
- ssl_config_.IsAllowedBadCert(ssl_info.cert, NULL)) {
+ ssl_config->IsAllowedBadCert(ssl_info.cert, NULL)) {
// If we already have the certificate in the set of allowed bad
// certificates, we did try it and failed again, so we should not
// retry again: the connection should fail at last.
@@ -336,7 +342,7 @@ int SocketStream::DidEstablishSSL(int result) {
return result;
}
bad_cert.cert_status = ssl_info.cert_status;
- ssl_config_.allowed_bad_certs.push_back(bad_cert);
+ ssl_config->allowed_bad_certs.push_back(bad_cert);
// Restart connection ignoring the bad certificate.
socket_->Disconnect();
socket_.reset();
@@ -910,7 +916,7 @@ int SocketStream::DoSecureProxyConnect() {
socket_.reset(factory_->CreateSSLClientSocket(
socket_.release(),
proxy_info_.proxy_server().host_port_pair(),
- ssl_config_,
+ proxy_ssl_config_,
NULL /* ssl_host_info */,
ssl_context));
next_state_ = STATE_SECURE_PROXY_CONNECT_COMPLETE;
@@ -920,9 +926,11 @@ int SocketStream::DoSecureProxyConnect() {
int SocketStream::DoSecureProxyConnectComplete(int result) {
DCHECK_EQ(STATE_NONE, next_state_);
- result = DidEstablishSSL(result);
+ result = DidEstablishSSL(result, &proxy_ssl_config_);
if (next_state_ != STATE_NONE)
return result;
+ if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED)
+ return HandleCertificateRequest(result);
if (result == OK)
next_state_ = STATE_WRITE_TUNNEL_HEADERS;
else
@@ -938,7 +946,7 @@ int SocketStream::DoSSLConnect() {
// TODO(agl): look into plumbing SSLHostInfo here.
socket_.reset(factory_->CreateSSLClientSocket(socket_.release(),
HostPortPair::FromURL(url_),
- ssl_config_,
+ server_ssl_config_,
NULL /* ssl_host_info */,
ssl_context));
next_state_ = STATE_SSL_CONNECT_COMPLETE;
@@ -948,7 +956,7 @@ int SocketStream::DoSSLConnect() {
int SocketStream::DoSSLConnectComplete(int result) {
DCHECK_EQ(STATE_NONE, next_state_);
- result = DidEstablishSSL(result);
+ result = DidEstablishSSL(result, &server_ssl_config_);
if (next_state_ != STATE_NONE)
return result;
// TODO(toyoshim): Upgrade to SPDY through TLS NPN extension if possible.
@@ -1088,6 +1096,53 @@ int SocketStream::HandleAuthChallenge(const HttpResponseHeaders* headers) {
return ERR_TUNNEL_CONNECTION_FAILED;
}
+int SocketStream::HandleCertificateRequest(int result) {
+ // TODO(toyoshim): We must support SSL client authentication for not only
+ // secure proxy but also secure server.
+
+ if (proxy_ssl_config_.send_client_cert)
+ // We already have performed SSL client authentication once and failed.
+ return result;
+
+ DCHECK(socket_.get());
+ scoped_refptr<SSLCertRequestInfo> cert_request_info = new SSLCertRequestInfo;
+ SSLClientSocket* ssl_socket =
+ static_cast<SSLClientSocket*>(socket_.get());
+ ssl_socket->GetSSLCertRequestInfo(cert_request_info);
+
+ HttpTransactionFactory* factory = context_->http_transaction_factory();
+ if (!factory)
+ return result;
+ scoped_refptr<HttpNetworkSession> session = factory->GetSession();
+ if (!session.get())
+ return result;
+
+ scoped_refptr<X509Certificate> client_cert;
+ bool found_cached_cert = session->ssl_client_auth_cache()->Lookup(
+ cert_request_info->host_and_port, &client_cert);
+ if (!found_cached_cert)
+ return result;
+ if (!client_cert)
+ return result;
+
+ const std::vector<scoped_refptr<X509Certificate> >& client_certs =
+ cert_request_info->client_certs;
+ bool cert_still_valid = false;
+ for (size_t i = 0; i < client_certs.size(); ++i) {
+ if (client_cert->Equals(client_certs[i])) {
+ cert_still_valid = true;
+ break;
+ }
+ }
+ if (!cert_still_valid)
+ return result;
+
+ proxy_ssl_config_.send_client_cert = true;
+ proxy_ssl_config_.client_cert = client_cert;
+ next_state_ = STATE_TCP_CONNECT;
+ return OK;
+}
+
void SocketStream::DoAuthRequired() {
if (delegate_ && auth_info_.get())
delegate_->OnAuthRequired(this, auth_info_.get());