Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(237)

Side by Side Diff: net/socket_stream/socket_stream.cc

Issue 8276031: SSL client authentication support for secure proxy in WebSocket (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: use separated ssl_info Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/socket_stream/socket_stream.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 // 4 //
5 // TODO(ukai): code is similar with http_network_transaction.cc. We should 5 // TODO(ukai): code is similar with http_network_transaction.cc. We should
6 // think about ways to share code, if possible. 6 // think about ways to share code, if possible.
7 7
8 #include "net/socket_stream/socket_stream.h" 8 #include "net/socket_stream/socket_stream.h"
9 9
10 #include <set> 10 #include <set>
11 #include <string> 11 #include <string>
12 12
13 #include "base/compiler_specific.h" 13 #include "base/compiler_specific.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/message_loop.h" 15 #include "base/message_loop.h"
16 #include "base/string_util.h" 16 #include "base/string_util.h"
17 #include "base/stringprintf.h" 17 #include "base/stringprintf.h"
18 #include "base/utf_string_conversions.h" 18 #include "base/utf_string_conversions.h"
19 #include "net/base/auth.h" 19 #include "net/base/auth.h"
20 #include "net/base/host_resolver.h" 20 #include "net/base/host_resolver.h"
21 #include "net/base/io_buffer.h" 21 #include "net/base/io_buffer.h"
22 #include "net/base/net_errors.h" 22 #include "net/base/net_errors.h"
23 #include "net/base/net_util.h" 23 #include "net/base/net_util.h"
24 #include "net/base/ssl_cert_request_info.h"
24 #include "net/http/http_auth_handler_factory.h" 25 #include "net/http/http_auth_handler_factory.h"
26 #include "net/http/http_network_session.h"
25 #include "net/http/http_request_info.h" 27 #include "net/http/http_request_info.h"
26 #include "net/http/http_response_headers.h" 28 #include "net/http/http_response_headers.h"
29 #include "net/http/http_transaction_factory.h"
27 #include "net/http/http_util.h" 30 #include "net/http/http_util.h"
28 #include "net/socket/client_socket_factory.h" 31 #include "net/socket/client_socket_factory.h"
29 #include "net/socket/socks5_client_socket.h" 32 #include "net/socket/socks5_client_socket.h"
30 #include "net/socket/socks_client_socket.h" 33 #include "net/socket/socks_client_socket.h"
31 #include "net/socket/ssl_client_socket.h" 34 #include "net/socket/ssl_client_socket.h"
32 #include "net/socket/tcp_client_socket.h" 35 #include "net/socket/tcp_client_socket.h"
33 #include "net/socket_stream/socket_stream_metrics.h" 36 #include "net/socket_stream/socket_stream_metrics.h"
34 #include "net/url_request/url_request.h" 37 #include "net/url_request/url_request.h"
35 38
36 static const int kMaxPendingSendAllowed = 32768; // 32 kilobytes. 39 static const int kMaxPendingSendAllowed = 32768; // 32 kilobytes.
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 origin_bound_cert_service_ = context_->origin_bound_cert_service(); 128 origin_bound_cert_service_ = context_->origin_bound_cert_service();
126 http_auth_handler_factory_ = context_->http_auth_handler_factory(); 129 http_auth_handler_factory_ = context_->http_auth_handler_factory();
127 } 130 }
128 } 131 }
129 132
130 void SocketStream::Connect() { 133 void SocketStream::Connect() {
131 DCHECK(MessageLoop::current()) << 134 DCHECK(MessageLoop::current()) <<
132 "The current MessageLoop must exist"; 135 "The current MessageLoop must exist";
133 DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) << 136 DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()) <<
134 "The current MessageLoop must be TYPE_IO"; 137 "The current MessageLoop must be TYPE_IO";
135 if (context_) 138 if (context_) {
136 ssl_config_service()->GetSSLConfig(&ssl_config_); 139 ssl_config_service()->GetSSLConfig(&server_ssl_config_);
140 proxy_ssl_config_ = server_ssl_config_;
141 }
137 DCHECK_EQ(next_state_, STATE_NONE); 142 DCHECK_EQ(next_state_, STATE_NONE);
138 143
139 AddRef(); // Released in Finish() 144 AddRef(); // Released in Finish()
140 // Open a connection asynchronously, so that delegate won't be called 145 // Open a connection asynchronously, so that delegate won't be called
141 // back before returning Connect(). 146 // back before returning Connect().
142 next_state_ = STATE_RESOLVE_PROXY; 147 next_state_ = STATE_RESOLVE_PROXY;
143 net_log_.BeginEvent( 148 net_log_.BeginEvent(
144 NetLog::TYPE_SOCKET_STREAM_CONNECT, 149 NetLog::TYPE_SOCKET_STREAM_CONNECT,
145 make_scoped_refptr( 150 make_scoped_refptr(
146 new NetLogStringParameter("url", url_.possibly_invalid_spec()))); 151 new NetLogStringParameter("url", url_.possibly_invalid_spec())));
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 Delegate* delegate = delegate_; 302 Delegate* delegate = delegate_;
298 delegate_ = NULL; 303 delegate_ = NULL;
299 if (delegate) { 304 if (delegate) {
300 delegate->OnError(this, result); 305 delegate->OnError(this, result);
301 if (result != ERR_PROTOCOL_SWITCHED) 306 if (result != ERR_PROTOCOL_SWITCHED)
302 delegate->OnClose(this); 307 delegate->OnClose(this);
303 } 308 }
304 Release(); 309 Release();
305 } 310 }
306 311
307 int SocketStream::DidEstablishSSL(int result) { 312 int SocketStream::DidEstablishSSL(int result, SSLConfig* ssl_config) {
313 DCHECK(ssl_config);
308 if (IsCertificateError(result)) { 314 if (IsCertificateError(result)) {
309 if (socket_->IsConnectedAndIdle()) { 315 if (socket_->IsConnectedAndIdle()) {
310 result = HandleCertificateError(result); 316 result = HandleCertificateError(result);
311 } else { 317 } else {
312 // SSLClientSocket for Mac will report socket is not connected, 318 // SSLClientSocket for Mac will report socket is not connected,
313 // if it returns cert verification error. It didn't perform 319 // if it returns cert verification error. It didn't perform
314 // SSLHandshake yet. 320 // SSLHandshake yet.
315 // So, we should restart establishing connection with the 321 // So, we should restart establishing connection with the
316 // certificate in allowed bad certificates in |ssl_config_|. 322 // certificate in allowed bad certificates in |ssl_config|.
317 // See also net/http/http_network_transaction.cc 323 // See also net/http/http_network_transaction.cc
318 // HandleCertificateError() and RestartIgnoringLastError(). 324 // HandleCertificateError() and RestartIgnoringLastError().
319 SSLClientSocket* ssl_socket = 325 SSLClientSocket* ssl_socket =
320 reinterpret_cast<SSLClientSocket*>(socket_.get()); 326 static_cast<SSLClientSocket*>(socket_.get());
321 SSLInfo ssl_info; 327 SSLInfo ssl_info;
322 ssl_socket->GetSSLInfo(&ssl_info); 328 ssl_socket->GetSSLInfo(&ssl_info);
323 if (ssl_info.cert == NULL || 329 if (ssl_info.cert == NULL ||
324 ssl_config_.IsAllowedBadCert(ssl_info.cert, NULL)) { 330 ssl_config->IsAllowedBadCert(ssl_info.cert, NULL)) {
325 // If we already have the certificate in the set of allowed bad 331 // If we already have the certificate in the set of allowed bad
326 // certificates, we did try it and failed again, so we should not 332 // certificates, we did try it and failed again, so we should not
327 // retry again: the connection should fail at last. 333 // retry again: the connection should fail at last.
328 next_state_ = STATE_CLOSE; 334 next_state_ = STATE_CLOSE;
329 return result; 335 return result;
330 } 336 }
331 // Add the bad certificate to the set of allowed certificates in the 337 // Add the bad certificate to the set of allowed certificates in the
332 // SSL config object. 338 // SSL config object.
333 SSLConfig::CertAndStatus bad_cert; 339 SSLConfig::CertAndStatus bad_cert;
334 if (!ssl_info.cert->GetDEREncoded(&bad_cert.der_cert)) { 340 if (!ssl_info.cert->GetDEREncoded(&bad_cert.der_cert)) {
335 next_state_ = STATE_CLOSE; 341 next_state_ = STATE_CLOSE;
336 return result; 342 return result;
337 } 343 }
338 bad_cert.cert_status = ssl_info.cert_status; 344 bad_cert.cert_status = ssl_info.cert_status;
339 ssl_config_.allowed_bad_certs.push_back(bad_cert); 345 ssl_config->allowed_bad_certs.push_back(bad_cert);
340 // Restart connection ignoring the bad certificate. 346 // Restart connection ignoring the bad certificate.
341 socket_->Disconnect(); 347 socket_->Disconnect();
342 socket_.reset(); 348 socket_.reset();
343 next_state_ = STATE_TCP_CONNECT; 349 next_state_ = STATE_TCP_CONNECT;
344 return OK; 350 return OK;
345 } 351 }
346 } 352 }
347 return result; 353 return result;
348 } 354 }
349 355
(...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after
903 909
904 int SocketStream::DoSecureProxyConnect() { 910 int SocketStream::DoSecureProxyConnect() {
905 DCHECK(factory_); 911 DCHECK(factory_);
906 SSLClientSocketContext ssl_context; 912 SSLClientSocketContext ssl_context;
907 ssl_context.cert_verifier = cert_verifier_; 913 ssl_context.cert_verifier = cert_verifier_;
908 ssl_context.origin_bound_cert_service = origin_bound_cert_service_; 914 ssl_context.origin_bound_cert_service = origin_bound_cert_service_;
909 // TODO(agl): look into plumbing SSLHostInfo here. 915 // TODO(agl): look into plumbing SSLHostInfo here.
910 socket_.reset(factory_->CreateSSLClientSocket( 916 socket_.reset(factory_->CreateSSLClientSocket(
911 socket_.release(), 917 socket_.release(),
912 proxy_info_.proxy_server().host_port_pair(), 918 proxy_info_.proxy_server().host_port_pair(),
913 ssl_config_, 919 proxy_ssl_config_,
914 NULL /* ssl_host_info */, 920 NULL /* ssl_host_info */,
915 ssl_context)); 921 ssl_context));
916 next_state_ = STATE_SECURE_PROXY_CONNECT_COMPLETE; 922 next_state_ = STATE_SECURE_PROXY_CONNECT_COMPLETE;
917 metrics_->OnCountConnectionType(SocketStreamMetrics::SECURE_PROXY_CONNECTION); 923 metrics_->OnCountConnectionType(SocketStreamMetrics::SECURE_PROXY_CONNECTION);
918 return socket_->Connect(&io_callback_); 924 return socket_->Connect(&io_callback_);
919 } 925 }
920 926
921 int SocketStream::DoSecureProxyConnectComplete(int result) { 927 int SocketStream::DoSecureProxyConnectComplete(int result) {
922 DCHECK_EQ(STATE_NONE, next_state_); 928 DCHECK_EQ(STATE_NONE, next_state_);
923 result = DidEstablishSSL(result); 929 result = DidEstablishSSL(result, &proxy_ssl_config_);
924 if (next_state_ != STATE_NONE) 930 if (next_state_ != STATE_NONE)
925 return result; 931 return result;
932 if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED)
933 return HandleCertificateRequest(result);
926 if (result == OK) 934 if (result == OK)
927 next_state_ = STATE_WRITE_TUNNEL_HEADERS; 935 next_state_ = STATE_WRITE_TUNNEL_HEADERS;
928 else 936 else
929 next_state_ = STATE_CLOSE; 937 next_state_ = STATE_CLOSE;
930 return result; 938 return result;
931 } 939 }
932 940
933 int SocketStream::DoSSLConnect() { 941 int SocketStream::DoSSLConnect() {
934 DCHECK(factory_); 942 DCHECK(factory_);
935 SSLClientSocketContext ssl_context; 943 SSLClientSocketContext ssl_context;
936 ssl_context.cert_verifier = cert_verifier_; 944 ssl_context.cert_verifier = cert_verifier_;
937 ssl_context.origin_bound_cert_service = origin_bound_cert_service_; 945 ssl_context.origin_bound_cert_service = origin_bound_cert_service_;
938 // TODO(agl): look into plumbing SSLHostInfo here. 946 // TODO(agl): look into plumbing SSLHostInfo here.
939 socket_.reset(factory_->CreateSSLClientSocket(socket_.release(), 947 socket_.reset(factory_->CreateSSLClientSocket(socket_.release(),
940 HostPortPair::FromURL(url_), 948 HostPortPair::FromURL(url_),
941 ssl_config_, 949 server_ssl_config_,
942 NULL /* ssl_host_info */, 950 NULL /* ssl_host_info */,
943 ssl_context)); 951 ssl_context));
944 next_state_ = STATE_SSL_CONNECT_COMPLETE; 952 next_state_ = STATE_SSL_CONNECT_COMPLETE;
945 metrics_->OnCountConnectionType(SocketStreamMetrics::SSL_CONNECTION); 953 metrics_->OnCountConnectionType(SocketStreamMetrics::SSL_CONNECTION);
946 return socket_->Connect(&io_callback_); 954 return socket_->Connect(&io_callback_);
947 } 955 }
948 956
949 int SocketStream::DoSSLConnectComplete(int result) { 957 int SocketStream::DoSSLConnectComplete(int result) {
950 DCHECK_EQ(STATE_NONE, next_state_); 958 DCHECK_EQ(STATE_NONE, next_state_);
951 result = DidEstablishSSL(result); 959 result = DidEstablishSSL(result, &server_ssl_config_);
952 if (next_state_ != STATE_NONE) 960 if (next_state_ != STATE_NONE)
953 return result; 961 return result;
954 // TODO(toyoshim): Upgrade to SPDY through TLS NPN extension if possible. 962 // TODO(toyoshim): Upgrade to SPDY through TLS NPN extension if possible.
955 // If we use HTTPS and this is the first connection to the SPDY server, 963 // If we use HTTPS and this is the first connection to the SPDY server,
956 // we should take care of TLS NPN extension here. 964 // we should take care of TLS NPN extension here.
957 965
958 if (result == OK) 966 if (result == OK)
959 result = DidEstablishConnection(); 967 result = DidEstablishConnection();
960 else 968 else
961 next_state_ = STATE_CLOSE; 969 next_state_ = STATE_CLOSE;
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
1081 auth_identity_.password = entry->password(); 1089 auth_identity_.password = entry->password();
1082 // Restart with auth info. 1090 // Restart with auth info.
1083 } 1091 }
1084 return ERR_PROXY_AUTH_UNSUPPORTED; 1092 return ERR_PROXY_AUTH_UNSUPPORTED;
1085 } else { 1093 } else {
1086 auth_identity_.invalid = false; 1094 auth_identity_.invalid = false;
1087 } 1095 }
1088 return ERR_TUNNEL_CONNECTION_FAILED; 1096 return ERR_TUNNEL_CONNECTION_FAILED;
1089 } 1097 }
1090 1098
1099 int SocketStream::HandleCertificateRequest(int result) {
1100 // TODO(toyoshim): We must support SSL client authentication for not only
1101 // secure proxy but also secure server.
1102
1103 if (proxy_ssl_config_.send_client_cert)
1104 // We already have performed SSL client authentication once and failed.
1105 return result;
1106
1107 DCHECK(socket_.get());
1108 scoped_refptr<SSLCertRequestInfo> cert_request_info = new SSLCertRequestInfo;
1109 SSLClientSocket* ssl_socket =
1110 static_cast<SSLClientSocket*>(socket_.get());
1111 ssl_socket->GetSSLCertRequestInfo(cert_request_info);
1112
1113 HttpTransactionFactory* factory = context_->http_transaction_factory();
1114 if (!factory)
1115 return result;
1116 scoped_refptr<HttpNetworkSession> session = factory->GetSession();
1117 if (!session.get())
1118 return result;
1119
1120 scoped_refptr<X509Certificate> client_cert;
1121 bool found_cached_cert = session->ssl_client_auth_cache()->Lookup(
1122 cert_request_info->host_and_port, &client_cert);
1123 if (!found_cached_cert)
1124 return result;
1125 if (!client_cert)
1126 return result;
1127
1128 const std::vector<scoped_refptr<X509Certificate> >& client_certs =
1129 cert_request_info->client_certs;
1130 bool cert_still_valid = false;
1131 for (size_t i = 0; i < client_certs.size(); ++i) {
1132 if (client_cert->Equals(client_certs[i])) {
1133 cert_still_valid = true;
1134 break;
1135 }
1136 }
1137 if (!cert_still_valid)
1138 return result;
1139
1140 proxy_ssl_config_.send_client_cert = true;
1141 proxy_ssl_config_.client_cert = client_cert;
1142 next_state_ = STATE_TCP_CONNECT;
1143 return OK;
1144 }
1145
1091 void SocketStream::DoAuthRequired() { 1146 void SocketStream::DoAuthRequired() {
1092 if (delegate_ && auth_info_.get()) 1147 if (delegate_ && auth_info_.get())
1093 delegate_->OnAuthRequired(this, auth_info_.get()); 1148 delegate_->OnAuthRequired(this, auth_info_.get());
1094 else 1149 else
1095 DoLoop(ERR_UNEXPECTED); 1150 DoLoop(ERR_UNEXPECTED);
1096 } 1151 }
1097 1152
1098 void SocketStream::DoRestartWithAuth() { 1153 void SocketStream::DoRestartWithAuth() {
1099 DCHECK_EQ(next_state_, STATE_AUTH_REQUIRED); 1154 DCHECK_EQ(next_state_, STATE_AUTH_REQUIRED);
1100 auth_cache_.Add(ProxyAuthOrigin(), 1155 auth_cache_.Add(ProxyAuthOrigin(),
(...skipping 30 matching lines...) Expand all
1131 1186
1132 SSLConfigService* SocketStream::ssl_config_service() const { 1187 SSLConfigService* SocketStream::ssl_config_service() const {
1133 return context_->ssl_config_service(); 1188 return context_->ssl_config_service();
1134 } 1189 }
1135 1190
1136 ProxyService* SocketStream::proxy_service() const { 1191 ProxyService* SocketStream::proxy_service() const {
1137 return context_->proxy_service(); 1192 return context_->proxy_service();
1138 } 1193 }
1139 1194
1140 } // namespace net 1195 } // namespace net
OLDNEW
« no previous file with comments | « net/socket_stream/socket_stream.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698