blob: f9a405854b34e018d2aad8af16b0ebb0ba23a646 [file] [log] [blame]
[email protected]e34400c32012-01-24 02:49:331// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]e60e47a2010-07-14 03:37:182// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/socket/ssl_client_socket_pool.h"
6
dchengc7eeda422015-12-26 03:56:487#include <utility>
8
[email protected]6ecf2b92011-12-15 01:14:529#include "base/bind.h"
10#include "base/bind_helpers.h"
[email protected]c63248d42011-02-18 17:54:3911#include "base/metrics/field_trial.h"
asvitkinec3c93722015-06-17 14:48:3712#include "base/metrics/histogram_macros.h"
[email protected]92a31242013-06-28 18:08:0813#include "base/metrics/sparse_histogram.h"
pkasting379234c2015-04-08 04:42:1214#include "base/profiler/scoped_tracker.h"
[email protected]ba00b492010-09-08 14:53:3815#include "base/values.h"
[email protected]4f4de7e62010-11-12 19:55:2716#include "net/base/host_port_pair.h"
[email protected]536fd0b2013-03-14 17:41:5717#include "net/base/net_errors.h"
[email protected]33b511c2010-08-11 00:04:4318#include "net/http/http_proxy_client_socket.h"
19#include "net/http/http_proxy_client_socket_pool.h"
[email protected]e60e47a2010-07-14 03:37:1820#include "net/socket/client_socket_factory.h"
21#include "net/socket/client_socket_handle.h"
[email protected]33b511c2010-08-11 00:04:4322#include "net/socket/socks_client_socket_pool.h"
23#include "net/socket/ssl_client_socket.h"
[email protected]ab739042011-04-07 15:22:2824#include "net/socket/transport_client_socket_pool.h"
[email protected]536fd0b2013-03-14 17:41:5725#include "net/ssl/ssl_cert_request_info.h"
sigbjorn66456a22015-09-18 10:45:1426#include "net/ssl/ssl_cipher_suite_names.h"
[email protected]92a31242013-06-28 18:08:0827#include "net/ssl/ssl_connection_status_flags.h"
28#include "net/ssl/ssl_info.h"
[email protected]e60e47a2010-07-14 03:37:1829
30namespace net {
31
32SSLSocketParams::SSLSocketParams(
[email protected]ea79ba92013-08-15 21:56:2033 const scoped_refptr<TransportSocketParams>& direct_params,
34 const scoped_refptr<SOCKSSocketParams>& socks_proxy_params,
[email protected]2431756e2010-09-29 20:26:1335 const scoped_refptr<HttpProxySocketParams>& http_proxy_params,
[email protected]4f4de7e62010-11-12 19:55:2736 const HostPortPair& host_and_port,
[email protected]e60e47a2010-07-14 03:37:1837 const SSLConfig& ssl_config,
[email protected]5e5021a2013-07-17 05:23:3638 PrivacyMode privacy_mode,
[email protected]e60e47a2010-07-14 03:37:1839 int load_flags,
bncb076baf2015-06-05 00:01:1240 bool expect_spdy)
[email protected]ea79ba92013-08-15 21:56:2041 : direct_params_(direct_params),
42 socks_proxy_params_(socks_proxy_params),
[email protected]e60e47a2010-07-14 03:37:1843 http_proxy_params_(http_proxy_params),
[email protected]4f4de7e62010-11-12 19:55:2744 host_and_port_(host_and_port),
[email protected]e60e47a2010-07-14 03:37:1845 ssl_config_(ssl_config),
[email protected]5e5021a2013-07-17 05:23:3646 privacy_mode_(privacy_mode),
[email protected]e60e47a2010-07-14 03:37:1847 load_flags_(load_flags),
bncb076baf2015-06-05 00:01:1248 expect_spdy_(expect_spdy),
[email protected]0e14e87d2011-06-21 21:24:1949 ignore_limits_(false) {
dcheng707f8602014-09-04 00:13:5250 if (direct_params_.get()) {
51 DCHECK(!socks_proxy_params_.get());
52 DCHECK(!http_proxy_params_.get());
[email protected]ea79ba92013-08-15 21:56:2053 ignore_limits_ = direct_params_->ignore_limits();
dcheng707f8602014-09-04 00:13:5254 } else if (socks_proxy_params_.get()) {
55 DCHECK(!http_proxy_params_.get());
[email protected]ea79ba92013-08-15 21:56:2056 ignore_limits_ = socks_proxy_params_->ignore_limits();
57 } else {
dcheng707f8602014-09-04 00:13:5258 DCHECK(http_proxy_params_.get());
[email protected]ea79ba92013-08-15 21:56:2059 ignore_limits_ = http_proxy_params_->ignore_limits();
[email protected]e60e47a2010-07-14 03:37:1860 }
61}
62
63SSLSocketParams::~SSLSocketParams() {}
64
[email protected]ea79ba92013-08-15 21:56:2065SSLSocketParams::ConnectionType SSLSocketParams::GetConnectionType() const {
dcheng707f8602014-09-04 00:13:5266 if (direct_params_.get()) {
67 DCHECK(!socks_proxy_params_.get());
68 DCHECK(!http_proxy_params_.get());
[email protected]ea79ba92013-08-15 21:56:2069 return DIRECT;
70 }
71
dcheng707f8602014-09-04 00:13:5272 if (socks_proxy_params_.get()) {
73 DCHECK(!http_proxy_params_.get());
[email protected]ea79ba92013-08-15 21:56:2074 return SOCKS_PROXY;
75 }
76
dcheng707f8602014-09-04 00:13:5277 DCHECK(http_proxy_params_.get());
[email protected]ea79ba92013-08-15 21:56:2078 return HTTP_PROXY;
79}
80
81const scoped_refptr<TransportSocketParams>&
82SSLSocketParams::GetDirectConnectionParams() const {
83 DCHECK_EQ(GetConnectionType(), DIRECT);
84 return direct_params_;
85}
86
87const scoped_refptr<SOCKSSocketParams>&
88SSLSocketParams::GetSocksProxyConnectionParams() const {
89 DCHECK_EQ(GetConnectionType(), SOCKS_PROXY);
90 return socks_proxy_params_;
91}
92
93const scoped_refptr<HttpProxySocketParams>&
94SSLSocketParams::GetHttpProxyConnectionParams() const {
95 DCHECK_EQ(GetConnectionType(), HTTP_PROXY);
96 return http_proxy_params_;
97}
98
[email protected]e60e47a2010-07-14 03:37:1899// Timeout for the SSL handshake portion of the connect.
100static const int kSSLHandshakeTimeoutInSeconds = 30;
101
[email protected]feb79bcd2011-07-21 16:55:17102SSLConnectJob::SSLConnectJob(const std::string& group_name,
[email protected]3f6007ab2013-08-22 19:45:39103 RequestPriority priority,
[email protected]feb79bcd2011-07-21 16:55:17104 const scoped_refptr<SSLSocketParams>& params,
105 const base::TimeDelta& timeout_duration,
106 TransportClientSocketPool* transport_pool,
107 SOCKSClientSocketPool* socks_pool,
108 HttpProxyClientSocketPool* http_proxy_pool,
109 ClientSocketFactory* client_socket_factory,
[email protected]feb79bcd2011-07-21 16:55:17110 const SSLClientSocketContext& context,
111 Delegate* delegate,
112 NetLog* net_log)
[email protected]5e5021a2013-07-17 05:23:36113 : ConnectJob(group_name,
114 timeout_duration,
[email protected]3f6007ab2013-08-22 19:45:39115 priority,
[email protected]5e5021a2013-07-17 05:23:36116 delegate,
[email protected]e60e47a2010-07-14 03:37:18117 BoundNetLog::Make(net_log, NetLog::SOURCE_CONNECT_JOB)),
118 params_(params),
[email protected]ab739042011-04-07 15:22:28119 transport_pool_(transport_pool),
[email protected]e60e47a2010-07-14 03:37:18120 socks_pool_(socks_pool),
[email protected]2431756e2010-09-29 20:26:13121 http_proxy_pool_(http_proxy_pool),
[email protected]e60e47a2010-07-14 03:37:18122 client_socket_factory_(client_socket_factory),
[email protected]5e5021a2013-07-17 05:23:36123 context_(context.cert_verifier,
[email protected]6b8a3c742014-07-25 00:25:35124 context.channel_id_service,
[email protected]5e5021a2013-07-17 05:23:36125 context.transport_security_state,
[email protected]284303b62013-11-28 15:11:54126 context.cert_transparency_verifier,
estark6f9b3d82016-01-12 21:37:05127 context.ct_policy_enforcer,
[email protected]314b03992014-04-01 01:28:53128 (params->privacy_mode() == PRIVACY_MODE_ENABLED
[email protected]5e5021a2013-07-17 05:23:36129 ? "pm/" + context.ssl_session_cache_shard
130 : context.ssl_session_cache_shard)),
rsleevif020edc2015-03-16 19:31:24131 callback_(
132 base::Bind(&SSLConnectJob::OnIOComplete, base::Unretained(this))) {
[email protected]8e458552014-08-05 00:02:15133}
[email protected]e60e47a2010-07-14 03:37:18134
[email protected]8e458552014-08-05 00:02:15135SSLConnectJob::~SSLConnectJob() {
[email protected]8e458552014-08-05 00:02:15136}
[email protected]e60e47a2010-07-14 03:37:18137
138LoadState SSLConnectJob::GetLoadState() const {
139 switch (next_state_) {
[email protected]135e2262010-07-17 00:32:04140 case STATE_TUNNEL_CONNECT_COMPLETE:
141 if (transport_socket_handle_->socket())
142 return LOAD_STATE_ESTABLISHING_PROXY_TUNNEL;
143 // else, fall through.
[email protected]ab739042011-04-07 15:22:28144 case STATE_TRANSPORT_CONNECT:
145 case STATE_TRANSPORT_CONNECT_COMPLETE:
[email protected]e60e47a2010-07-14 03:37:18146 case STATE_SOCKS_CONNECT:
147 case STATE_SOCKS_CONNECT_COMPLETE:
148 case STATE_TUNNEL_CONNECT:
[email protected]e60e47a2010-07-14 03:37:18149 return transport_socket_handle_->GetLoadState();
150 case STATE_SSL_CONNECT:
151 case STATE_SSL_CONNECT_COMPLETE:
152 return LOAD_STATE_SSL_HANDSHAKE;
153 default:
154 NOTREACHED();
155 return LOAD_STATE_IDLE;
156 }
157}
158
[email protected]83039bb2011-12-09 18:43:55159void SSLConnectJob::GetAdditionalErrorState(ClientSocketHandle* handle) {
[email protected]ad74a592011-01-21 18:40:55160 // Headers in |error_response_info_| indicate a proxy tunnel setup
161 // problem. See DoTunnelConnectComplete.
[email protected]90499482013-06-01 00:39:50162 if (error_response_info_.headers.get()) {
[email protected]ad74a592011-01-21 18:40:55163 handle->set_pending_http_proxy_connection(
164 transport_socket_handle_.release());
[email protected]e60e47a2010-07-14 03:37:18165 }
[email protected]ad74a592011-01-21 18:40:55166 handle->set_ssl_error_response_info(error_response_info_);
[email protected]034df0f32013-01-07 23:17:48167 if (!connect_timing_.ssl_start.is_null())
[email protected]ad74a592011-01-21 18:40:55168 handle->set_is_ssl_error(true);
davidbenf2eaaf92015-05-15 22:18:42169 if (ssl_socket_)
170 handle->set_ssl_failure_state(ssl_socket_->GetSSLFailureState());
ttuttle1f2d7e92015-04-28 16:17:47171
172 handle->set_connection_attempts(connection_attempts_);
[email protected]e60e47a2010-07-14 03:37:18173}
174
175void SSLConnectJob::OnIOComplete(int result) {
176 int rv = DoLoop(result);
177 if (rv != ERR_IO_PENDING)
178 NotifyDelegateOfCompletion(rv); // Deletes |this|.
179}
180
181int SSLConnectJob::DoLoop(int result) {
182 DCHECK_NE(next_state_, STATE_NONE);
183
184 int rv = result;
185 do {
186 State state = next_state_;
187 next_state_ = STATE_NONE;
188 switch (state) {
[email protected]ab739042011-04-07 15:22:28189 case STATE_TRANSPORT_CONNECT:
[email protected]e60e47a2010-07-14 03:37:18190 DCHECK_EQ(OK, rv);
[email protected]ab739042011-04-07 15:22:28191 rv = DoTransportConnect();
[email protected]e60e47a2010-07-14 03:37:18192 break;
[email protected]ab739042011-04-07 15:22:28193 case STATE_TRANSPORT_CONNECT_COMPLETE:
194 rv = DoTransportConnectComplete(rv);
[email protected]e60e47a2010-07-14 03:37:18195 break;
196 case STATE_SOCKS_CONNECT:
197 DCHECK_EQ(OK, rv);
198 rv = DoSOCKSConnect();
199 break;
200 case STATE_SOCKS_CONNECT_COMPLETE:
201 rv = DoSOCKSConnectComplete(rv);
202 break;
203 case STATE_TUNNEL_CONNECT:
204 DCHECK_EQ(OK, rv);
205 rv = DoTunnelConnect();
206 break;
207 case STATE_TUNNEL_CONNECT_COMPLETE:
208 rv = DoTunnelConnectComplete(rv);
209 break;
210 case STATE_SSL_CONNECT:
211 DCHECK_EQ(OK, rv);
212 rv = DoSSLConnect();
213 break;
214 case STATE_SSL_CONNECT_COMPLETE:
215 rv = DoSSLConnectComplete(rv);
216 break;
217 default:
218 NOTREACHED() << "bad state";
219 rv = ERR_FAILED;
220 break;
221 }
222 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
223
224 return rv;
225}
226
[email protected]ab739042011-04-07 15:22:28227int SSLConnectJob::DoTransportConnect() {
228 DCHECK(transport_pool_);
[email protected]899c3e92010-08-28 15:53:50229
[email protected]ab739042011-04-07 15:22:28230 next_state_ = STATE_TRANSPORT_CONNECT_COMPLETE;
[email protected]e60e47a2010-07-14 03:37:18231 transport_socket_handle_.reset(new ClientSocketHandle());
[email protected]ea79ba92013-08-15 21:56:20232 scoped_refptr<TransportSocketParams> direct_params =
233 params_->GetDirectConnectionParams();
rsleevif020edc2015-03-16 19:31:24234 return transport_socket_handle_->Init(group_name(), direct_params, priority(),
235 callback_, transport_pool_, net_log());
[email protected]e60e47a2010-07-14 03:37:18236}
237
[email protected]ab739042011-04-07 15:22:28238int SSLConnectJob::DoTransportConnectComplete(int result) {
ttuttle1f2d7e92015-04-28 16:17:47239 connection_attempts_ = transport_socket_handle_->connection_attempts();
240 if (result == OK) {
rsleevif020edc2015-03-16 19:31:24241 next_state_ = STATE_SSL_CONNECT;
ttuttle1f2d7e92015-04-28 16:17:47242 transport_socket_handle_->socket()->GetPeerAddress(&server_address_);
243 }
[email protected]e60e47a2010-07-14 03:37:18244
245 return result;
246}
247
248int SSLConnectJob::DoSOCKSConnect() {
[email protected]2431756e2010-09-29 20:26:13249 DCHECK(socks_pool_);
[email protected]e60e47a2010-07-14 03:37:18250 next_state_ = STATE_SOCKS_CONNECT_COMPLETE;
251 transport_socket_handle_.reset(new ClientSocketHandle());
[email protected]ea79ba92013-08-15 21:56:20252 scoped_refptr<SOCKSSocketParams> socks_proxy_params =
253 params_->GetSocksProxyConnectionParams();
rsleevif020edc2015-03-16 19:31:24254 return transport_socket_handle_->Init(group_name(), socks_proxy_params,
255 priority(), callback_, socks_pool_,
[email protected]5109c1952013-08-20 18:44:10256 net_log());
[email protected]e60e47a2010-07-14 03:37:18257}
258
259int SSLConnectJob::DoSOCKSConnectComplete(int result) {
260 if (result == OK)
rsleevif020edc2015-03-16 19:31:24261 next_state_ = STATE_SSL_CONNECT;
[email protected]e60e47a2010-07-14 03:37:18262
263 return result;
264}
265
266int SSLConnectJob::DoTunnelConnect() {
[email protected]2431756e2010-09-29 20:26:13267 DCHECK(http_proxy_pool_);
[email protected]e60e47a2010-07-14 03:37:18268 next_state_ = STATE_TUNNEL_CONNECT_COMPLETE;
[email protected]394816e92010-08-03 07:38:59269
[email protected]e60e47a2010-07-14 03:37:18270 transport_socket_handle_.reset(new ClientSocketHandle());
271 scoped_refptr<HttpProxySocketParams> http_proxy_params =
[email protected]ea79ba92013-08-15 21:56:20272 params_->GetHttpProxyConnectionParams();
rsleevif020edc2015-03-16 19:31:24273 return transport_socket_handle_->Init(group_name(), http_proxy_params,
274 priority(), callback_, http_proxy_pool_,
[email protected]5109c1952013-08-20 18:44:10275 net_log());
[email protected]e60e47a2010-07-14 03:37:18276}
277
278int SSLConnectJob::DoTunnelConnectComplete(int result) {
[email protected]4f4de7e62010-11-12 19:55:27279 // Extract the information needed to prompt for appropriate proxy
280 // authentication so that when ClientSocketPoolBaseHelper calls
281 // |GetAdditionalErrorState|, we can easily set the state.
282 if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
283 error_response_info_ = transport_socket_handle_->ssl_error_response_info();
[email protected]511f6f52010-12-17 03:58:29284 } else if (result == ERR_PROXY_AUTH_REQUESTED ||
285 result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) {
[email protected]3268023f2011-05-05 00:08:10286 StreamSocket* socket = transport_socket_handle_->socket();
pcc684f44b2015-01-30 18:59:23287 ProxyClientSocket* tunnel_socket = static_cast<ProxyClientSocket*>(socket);
[email protected]511f6f52010-12-17 03:58:29288 error_response_info_ = *tunnel_socket->GetConnectResponseInfo();
[email protected]4f4de7e62010-11-12 19:55:27289 }
[email protected]e60e47a2010-07-14 03:37:18290 if (result < 0)
291 return result;
rsleevif020edc2015-03-16 19:31:24292
293 next_state_ = STATE_SSL_CONNECT;
[email protected]e60e47a2010-07-14 03:37:18294 return result;
295}
296
rsleevif020edc2015-03-16 19:31:24297int SSLConnectJob::DoSSLConnect() {
pkasting93ba27f62015-02-28 02:53:46298 // TODO(pkasting): Remove ScopedTracker below once crbug.com/462815 is fixed.
pkasting58e029b2015-02-21 05:17:28299 tracked_objects::ScopedTracker tracking_profile(
rsleevif020edc2015-03-16 19:31:24300 FROM_HERE_WITH_EXPLICIT_FUNCTION("462815 SSLConnectJob::DoSSLConnect"));
301
302 next_state_ = STATE_SSL_CONNECT_COMPLETE;
[email protected]8e458552014-08-05 00:02:15303
[email protected]e60e47a2010-07-14 03:37:18304 // Reset the timeout to just the time allowed for the SSL handshake.
305 ResetTimer(base::TimeDelta::FromSeconds(kSSLHandshakeTimeoutInSeconds));
[email protected]034df0f32013-01-07 23:17:48306
307 // If the handle has a fresh socket, get its connect start and DNS times.
308 // This should always be the case.
309 const LoadTimingInfo::ConnectTiming& socket_connect_timing =
310 transport_socket_handle_->connect_timing();
311 if (!transport_socket_handle_->is_reused() &&
312 !socket_connect_timing.connect_start.is_null()) {
313 // Overwriting |connect_start| serves two purposes - it adjusts timing so
314 // |connect_start| doesn't include dns times, and it adjusts the time so
315 // as not to include time spent waiting for an idle socket.
316 connect_timing_.connect_start = socket_connect_timing.connect_start;
317 connect_timing_.dns_start = socket_connect_timing.dns_start;
318 connect_timing_.dns_end = socket_connect_timing.dns_end;
319 }
320
rsleevif020edc2015-03-16 19:31:24321 connect_timing_.ssl_start = base::TimeTicks::Now();
322
[email protected]18ccfdb2013-08-15 00:13:44323 ssl_socket_ = client_socket_factory_->CreateSSLClientSocket(
dchengc7eeda422015-12-26 03:56:48324 std::move(transport_socket_handle_), params_->host_and_port(),
325 params_->ssl_config(), context_);
rsleevif020edc2015-03-16 19:31:24326 return ssl_socket_->Connect(callback_);
[email protected]e60e47a2010-07-14 03:37:18327}
328
329int SSLConnectJob::DoSSLConnectComplete(int result) {
rvargas1270c002015-04-03 08:11:09330 // TODO(rvargas): Remove ScopedTracker below once crbug.com/462784 is fixed.
331 tracked_objects::ScopedTracker tracking_profile(
332 FROM_HERE_WITH_EXPLICIT_FUNCTION(
333 "462784 SSLConnectJob::DoSSLConnectComplete"));
334
[email protected]034df0f32013-01-07 23:17:48335 connect_timing_.ssl_end = base::TimeTicks::Now();
336
ttuttle1f2d7e92015-04-28 16:17:47337 if (result != OK && !server_address_.address().empty()) {
338 connection_attempts_.push_back(ConnectionAttempt(server_address_, result));
339 server_address_ = IPEndPoint();
340 }
341
davidben6974bf72015-04-27 17:52:48342 // If we want SPDY over ALPN/NPN, make sure it succeeded.
bncb076baf2015-06-05 00:01:12343 if (params_->expect_spdy() &&
davidben6974bf72015-04-27 17:52:48344 !NextProtoIsSPDY(ssl_socket_->GetNegotiatedProtocol())) {
[email protected]e60e47a2010-07-14 03:37:18345 return ERR_NPN_NEGOTIATION_FAILED;
davidben6974bf72015-04-27 17:52:48346 }
[email protected]e60e47a2010-07-14 03:37:18347
348 if (result == OK ||
349 ssl_socket_->IgnoreCertError(result, params_->load_flags())) {
[email protected]034df0f32013-01-07 23:17:48350 DCHECK(!connect_timing_.ssl_start.is_null());
[email protected]e60e47a2010-07-14 03:37:18351 base::TimeDelta connect_duration =
[email protected]034df0f32013-01-07 23:17:48352 connect_timing_.ssl_end - connect_timing_.ssl_start;
bncb076baf2015-06-05 00:01:12353 if (params_->expect_spdy()) {
[email protected]847276962013-03-08 23:53:17354 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SpdyConnectionLatency_2",
[email protected]e60e47a2010-07-14 03:37:18355 connect_duration,
356 base::TimeDelta::FromMilliseconds(1),
[email protected]847276962013-03-08 23:53:17357 base::TimeDelta::FromMinutes(1),
[email protected]e60e47a2010-07-14 03:37:18358 100);
[email protected]f906bfe2011-06-09 16:35:24359 }
360
[email protected]847276962013-03-08 23:53:17361 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_2",
[email protected]f906bfe2011-06-09 16:35:24362 connect_duration,
363 base::TimeDelta::FromMilliseconds(1),
[email protected]847276962013-03-08 23:53:17364 base::TimeDelta::FromMinutes(1),
[email protected]f906bfe2011-06-09 16:35:24365 100);
366
[email protected]b076d6c2011-06-29 14:47:51367 SSLInfo ssl_info;
davidbend3f15152015-02-20 23:43:09368 bool has_ssl_info = ssl_socket_->GetSSLInfo(&ssl_info);
369 DCHECK(has_ssl_info);
[email protected]b076d6c2011-06-29 14:47:51370
davidben9ff250e02015-02-19 23:06:51371 UMA_HISTOGRAM_ENUMERATION("Net.SSLVersion", SSLConnectionStatusToVersion(
372 ssl_info.connection_status),
373 SSL_CONNECTION_VERSION_MAX);
374
Avi Drissman13fc8932015-12-20 04:40:46375 uint16_t cipher_suite =
sigbjorn66456a22015-09-18 10:45:14376 SSLConnectionStatusToCipherSuite(ssl_info.connection_status);
377 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSL_CipherSuite", cipher_suite);
378
379 const char *str, *cipher_str, *mac_str;
380 bool is_aead;
381 SSLCipherSuiteToStrings(&str, &cipher_str, &mac_str, &is_aead,
382 cipher_suite);
383 // UMA_HISTOGRAM_... macros cache the Histogram instance and thus only work
384 // if the histogram name is constant, so don't generate it dynamically.
385 if (strcmp(str, "RSA") == 0) {
386 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSL_KeyExchange.RSA",
387 ssl_info.key_exchange_info);
388 } else if (strncmp(str, "DHE_", 4) == 0) {
389 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSL_KeyExchange.DHE",
390 ssl_info.key_exchange_info);
391 } else if (strncmp(str, "ECDHE_", 6) == 0) {
392 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSL_KeyExchange.ECDHE",
393 ssl_info.key_exchange_info);
394 } else {
395 NOTREACHED();
396 }
[email protected]92a31242013-06-28 18:08:08397
[email protected]b076d6c2011-06-29 14:47:51398 if (ssl_info.handshake_type == SSLInfo::HANDSHAKE_RESUME) {
399 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Resume_Handshake",
400 connect_duration,
401 base::TimeDelta::FromMilliseconds(1),
402 base::TimeDelta::FromMinutes(1),
403 100);
404 } else if (ssl_info.handshake_type == SSLInfo::HANDSHAKE_FULL) {
405 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Full_Handshake",
406 connect_duration,
407 base::TimeDelta::FromMilliseconds(1),
408 base::TimeDelta::FromMinutes(1),
409 100);
410 }
411
[email protected]f906bfe2011-06-09 16:35:24412 const std::string& host = params_->host_and_port().host();
[email protected]8e458552014-08-05 00:02:15413 bool is_google =
414 host == "google.com" ||
415 (host.size() > 11 && host.rfind(".google.com") == host.size() - 11);
[email protected]f906bfe2011-06-09 16:35:24416 if (is_google) {
[email protected]847276962013-03-08 23:53:17417 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Google2",
[email protected]e60e47a2010-07-14 03:37:18418 connect_duration,
419 base::TimeDelta::FromMilliseconds(1),
[email protected]847276962013-03-08 23:53:17420 base::TimeDelta::FromMinutes(1),
[email protected]e60e47a2010-07-14 03:37:18421 100);
[email protected]b076d6c2011-06-29 14:47:51422 if (ssl_info.handshake_type == SSLInfo::HANDSHAKE_RESUME) {
423 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Google_"
424 "Resume_Handshake",
425 connect_duration,
426 base::TimeDelta::FromMilliseconds(1),
427 base::TimeDelta::FromMinutes(1),
428 100);
429 } else if (ssl_info.handshake_type == SSLInfo::HANDSHAKE_FULL) {
430 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Google_"
431 "Full_Handshake",
432 connect_duration,
433 base::TimeDelta::FromMilliseconds(1),
434 base::TimeDelta::FromMinutes(1),
435 100);
436 }
[email protected]835d7c82010-10-14 04:38:38437 }
[email protected]e60e47a2010-07-14 03:37:18438 }
[email protected]8b498692010-07-16 17:11:43439
jeremyim8d44fadd2015-02-10 19:18:15440 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSL_Connection_Error", std::abs(result));
jeremyim8d44fadd2015-02-10 19:18:15441
[email protected]8b498692010-07-16 17:11:43442 if (result == OK || IsCertificateError(result)) {
dchengc7eeda422015-12-26 03:56:48443 SetSocket(std::move(ssl_socket_));
[email protected]8b498692010-07-16 17:11:43444 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
445 error_response_info_.cert_request_info = new SSLCertRequestInfo;
[email protected]90499482013-06-01 00:39:50446 ssl_socket_->GetSSLCertRequestInfo(
447 error_response_info_.cert_request_info.get());
[email protected]8b498692010-07-16 17:11:43448 }
[email protected]e60e47a2010-07-14 03:37:18449
450 return result;
451}
452
[email protected]ea79ba92013-08-15 21:56:20453SSLConnectJob::State SSLConnectJob::GetInitialState(
454 SSLSocketParams::ConnectionType connection_type) {
455 switch (connection_type) {
456 case SSLSocketParams::DIRECT:
457 return STATE_TRANSPORT_CONNECT;
458 case SSLSocketParams::HTTP_PROXY:
459 return STATE_TUNNEL_CONNECT;
460 case SSLSocketParams::SOCKS_PROXY:
461 return STATE_SOCKS_CONNECT;
[email protected]ad74a592011-01-21 18:40:55462 }
[email protected]ea79ba92013-08-15 21:56:20463 NOTREACHED();
464 return STATE_NONE;
465}
466
467int SSLConnectJob::ConnectInternal() {
468 next_state_ = GetInitialState(params_->GetConnectionType());
[email protected]ad74a592011-01-21 18:40:55469 return DoLoop(OK);
[email protected]e60e47a2010-07-14 03:37:18470}
471
472SSLClientSocketPool::SSLConnectJobFactory::SSLConnectJobFactory(
[email protected]ab739042011-04-07 15:22:28473 TransportClientSocketPool* transport_pool,
[email protected]2431756e2010-09-29 20:26:13474 SOCKSClientSocketPool* socks_pool,
475 HttpProxyClientSocketPool* http_proxy_pool,
[email protected]e60e47a2010-07-14 03:37:18476 ClientSocketFactory* client_socket_factory,
[email protected]feb79bcd2011-07-21 16:55:17477 const SSLClientSocketContext& context,
[email protected]e60e47a2010-07-14 03:37:18478 NetLog* net_log)
[email protected]ab739042011-04-07 15:22:28479 : transport_pool_(transport_pool),
[email protected]e60e47a2010-07-14 03:37:18480 socks_pool_(socks_pool),
[email protected]2431756e2010-09-29 20:26:13481 http_proxy_pool_(http_proxy_pool),
[email protected]e60e47a2010-07-14 03:37:18482 client_socket_factory_(client_socket_factory),
[email protected]feb79bcd2011-07-21 16:55:17483 context_(context),
[email protected]cffd7f92014-08-21 21:30:50484 net_log_(net_log) {
[email protected]e60e47a2010-07-14 03:37:18485 base::TimeDelta max_transport_timeout = base::TimeDelta();
486 base::TimeDelta pool_timeout;
[email protected]ab739042011-04-07 15:22:28487 if (transport_pool_)
488 max_transport_timeout = transport_pool_->ConnectionTimeout();
[email protected]e60e47a2010-07-14 03:37:18489 if (socks_pool_) {
490 pool_timeout = socks_pool_->ConnectionTimeout();
491 if (pool_timeout > max_transport_timeout)
492 max_transport_timeout = pool_timeout;
493 }
494 if (http_proxy_pool_) {
495 pool_timeout = http_proxy_pool_->ConnectionTimeout();
496 if (pool_timeout > max_transport_timeout)
497 max_transport_timeout = pool_timeout;
498 }
499 timeout_ = max_transport_timeout +
500 base::TimeDelta::FromSeconds(kSSLHandshakeTimeoutInSeconds);
501}
502
[email protected]8e458552014-08-05 00:02:15503SSLClientSocketPool::SSLConnectJobFactory::~SSLConnectJobFactory() {
[email protected]8e458552014-08-05 00:02:15504}
505
[email protected]e60e47a2010-07-14 03:37:18506SSLClientSocketPool::SSLClientSocketPool(
507 int max_sockets,
508 int max_sockets_per_group,
[email protected]822581d2010-12-16 17:27:15509 CertVerifier* cert_verifier,
[email protected]6b8a3c742014-07-25 00:25:35510 ChannelIDService* channel_id_service,
[email protected]a2a41972011-12-07 17:47:27511 TransportSecurityState* transport_security_state,
[email protected]284303b62013-11-28 15:11:54512 CTVerifier* cert_transparency_verifier,
estark6f9b3d82016-01-12 21:37:05513 CTPolicyEnforcer* ct_policy_enforcer,
[email protected]c3456bb2011-12-12 22:22:19514 const std::string& ssl_session_cache_shard,
[email protected]e60e47a2010-07-14 03:37:18515 ClientSocketFactory* client_socket_factory,
[email protected]ab739042011-04-07 15:22:28516 TransportClientSocketPool* transport_pool,
[email protected]2431756e2010-09-29 20:26:13517 SOCKSClientSocketPool* socks_pool,
518 HttpProxyClientSocketPool* http_proxy_pool,
[email protected]7abf7d22010-09-04 01:41:59519 SSLConfigService* ssl_config_service,
[email protected]e60e47a2010-07-14 03:37:18520 NetLog* net_log)
[email protected]ab739042011-04-07 15:22:28521 : transport_pool_(transport_pool),
[email protected]ba00b492010-09-08 14:53:38522 socks_pool_(socks_pool),
[email protected]2431756e2010-09-29 20:26:13523 http_proxy_pool_(http_proxy_pool),
[email protected]8e458552014-08-05 00:02:15524 base_(this,
525 max_sockets,
526 max_sockets_per_group,
[email protected]82b8c962011-10-12 09:17:30527 ClientSocketPool::unused_idle_socket_timeout(),
528 ClientSocketPool::used_idle_socket_timeout(),
[email protected]8e458552014-08-05 00:02:15529 new SSLConnectJobFactory(
530 transport_pool,
531 socks_pool,
532 http_proxy_pool,
533 client_socket_factory,
[email protected]8e458552014-08-05 00:02:15534 SSLClientSocketContext(cert_verifier,
535 channel_id_service,
536 transport_security_state,
537 cert_transparency_verifier,
estark6f9b3d82016-01-12 21:37:05538 ct_policy_enforcer,
[email protected]8e458552014-08-05 00:02:15539 ssl_session_cache_shard),
[email protected]8e458552014-08-05 00:02:15540 net_log)),
rsleevif020edc2015-03-16 19:31:24541 ssl_config_service_(ssl_config_service) {
[email protected]90499482013-06-01 00:39:50542 if (ssl_config_service_.get())
[email protected]7abf7d22010-09-04 01:41:59543 ssl_config_service_->AddObserver(this);
[email protected]51fdc7c2012-04-10 19:19:48544 if (transport_pool_)
[email protected]043b68c82013-08-22 23:41:52545 base_.AddLowerLayeredPool(transport_pool_);
[email protected]51fdc7c2012-04-10 19:19:48546 if (socks_pool_)
[email protected]043b68c82013-08-22 23:41:52547 base_.AddLowerLayeredPool(socks_pool_);
[email protected]51fdc7c2012-04-10 19:19:48548 if (http_proxy_pool_)
[email protected]043b68c82013-08-22 23:41:52549 base_.AddLowerLayeredPool(http_proxy_pool_);
[email protected]7abf7d22010-09-04 01:41:59550}
[email protected]e60e47a2010-07-14 03:37:18551
[email protected]7abf7d22010-09-04 01:41:59552SSLClientSocketPool::~SSLClientSocketPool() {
[email protected]90499482013-06-01 00:39:50553 if (ssl_config_service_.get())
[email protected]7abf7d22010-09-04 01:41:59554 ssl_config_service_->RemoveObserver(this);
555}
[email protected]e60e47a2010-07-14 03:37:18556
[email protected]cffd7f92014-08-21 21:30:50557scoped_ptr<ConnectJob> SSLClientSocketPool::SSLConnectJobFactory::NewConnectJob(
[email protected]ad74a592011-01-21 18:40:55558 const std::string& group_name,
559 const PoolBase::Request& request,
560 ConnectJob::Delegate* delegate) const {
[email protected]8e458552014-08-05 00:02:15561 return scoped_ptr<ConnectJob>(new SSLConnectJob(group_name,
562 request.priority(),
563 request.params(),
564 ConnectionTimeout(),
565 transport_pool_,
566 socks_pool_,
567 http_proxy_pool_,
568 client_socket_factory_,
[email protected]8e458552014-08-05 00:02:15569 context_,
[email protected]8e458552014-08-05 00:02:15570 delegate,
571 net_log_));
[email protected]ad74a592011-01-21 18:40:55572}
573
[email protected]cffd7f92014-08-21 21:30:50574base::TimeDelta SSLClientSocketPool::SSLConnectJobFactory::ConnectionTimeout()
575 const {
[email protected]2a848e0e2012-08-09 22:27:31576 return timeout_;
577}
578
[email protected]e60e47a2010-07-14 03:37:18579int SSLClientSocketPool::RequestSocket(const std::string& group_name,
580 const void* socket_params,
581 RequestPriority priority,
582 ClientSocketHandle* handle,
[email protected]49639fa2011-12-20 23:22:41583 const CompletionCallback& callback,
[email protected]e60e47a2010-07-14 03:37:18584 const BoundNetLog& net_log) {
585 const scoped_refptr<SSLSocketParams>* casted_socket_params =
586 static_cast<const scoped_refptr<SSLSocketParams>*>(socket_params);
587
588 return base_.RequestSocket(group_name, *casted_socket_params, priority,
589 handle, callback, net_log);
590}
591
[email protected]2c2bef152010-10-13 00:55:03592void SSLClientSocketPool::RequestSockets(
593 const std::string& group_name,
594 const void* params,
595 int num_sockets,
596 const BoundNetLog& net_log) {
597 const scoped_refptr<SSLSocketParams>* casted_params =
598 static_cast<const scoped_refptr<SSLSocketParams>*>(params);
599
600 base_.RequestSockets(group_name, *casted_params, num_sockets, net_log);
601}
602
[email protected]e60e47a2010-07-14 03:37:18603void SSLClientSocketPool::CancelRequest(const std::string& group_name,
[email protected]05ea9ff2010-07-15 19:08:21604 ClientSocketHandle* handle) {
[email protected]e60e47a2010-07-14 03:37:18605 base_.CancelRequest(group_name, handle);
606}
607
608void SSLClientSocketPool::ReleaseSocket(const std::string& group_name,
[email protected]18ccfdb2013-08-15 00:13:44609 scoped_ptr<StreamSocket> socket,
610 int id) {
dchengc7eeda422015-12-26 03:56:48611 base_.ReleaseSocket(group_name, std::move(socket), id);
[email protected]e60e47a2010-07-14 03:37:18612}
613
[email protected]7af985a2012-12-14 22:40:42614void SSLClientSocketPool::FlushWithError(int error) {
615 base_.FlushWithError(error);
[email protected]e60e47a2010-07-14 03:37:18616}
617
618void SSLClientSocketPool::CloseIdleSockets() {
619 base_.CloseIdleSockets();
620}
621
[email protected]ddb1e5a2010-12-13 20:10:45622int SSLClientSocketPool::IdleSocketCount() const {
623 return base_.idle_socket_count();
624}
625
[email protected]e60e47a2010-07-14 03:37:18626int SSLClientSocketPool::IdleSocketCountInGroup(
627 const std::string& group_name) const {
628 return base_.IdleSocketCountInGroup(group_name);
629}
630
631LoadState SSLClientSocketPool::GetLoadState(
632 const std::string& group_name, const ClientSocketHandle* handle) const {
633 return base_.GetLoadState(group_name, handle);
634}
635
ketan.goyalf84eda92015-06-03 10:53:36636scoped_ptr<base::DictionaryValue> SSLClientSocketPool::GetInfoAsValue(
[email protected]ba00b492010-09-08 14:53:38637 const std::string& name,
638 const std::string& type,
639 bool include_nested_pools) const {
ketan.goyalf84eda92015-06-03 10:53:36640 scoped_ptr<base::DictionaryValue> dict(base_.GetInfoAsValue(name, type));
[email protected]ba00b492010-09-08 14:53:38641 if (include_nested_pools) {
[email protected]ea5ef4c2013-06-13 22:50:27642 base::ListValue* list = new base::ListValue();
[email protected]ab739042011-04-07 15:22:28643 if (transport_pool_) {
644 list->Append(transport_pool_->GetInfoAsValue("transport_socket_pool",
645 "transport_socket_pool",
646 false));
[email protected]ba00b492010-09-08 14:53:38647 }
[email protected]2431756e2010-09-29 20:26:13648 if (socks_pool_) {
[email protected]ba00b492010-09-08 14:53:38649 list->Append(socks_pool_->GetInfoAsValue("socks_pool",
650 "socks_pool",
651 true));
652 }
[email protected]2431756e2010-09-29 20:26:13653 if (http_proxy_pool_) {
654 list->Append(http_proxy_pool_->GetInfoAsValue("http_proxy_pool",
655 "http_proxy_pool",
656 true));
657 }
[email protected]ba00b492010-09-08 14:53:38658 dict->Set("nested_pools", list);
659 }
dchengc7eeda422015-12-26 03:56:48660 return dict;
[email protected]ba00b492010-09-08 14:53:38661}
662
[email protected]ddb1e5a2010-12-13 20:10:45663base::TimeDelta SSLClientSocketPool::ConnectionTimeout() const {
664 return base_.ConnectionTimeout();
665}
666
[email protected]043b68c82013-08-22 23:41:52667bool SSLClientSocketPool::IsStalled() const {
668 return base_.IsStalled();
669}
670
671void SSLClientSocketPool::AddHigherLayeredPool(HigherLayeredPool* higher_pool) {
672 base_.AddHigherLayeredPool(higher_pool);
673}
674
675void SSLClientSocketPool::RemoveHigherLayeredPool(
676 HigherLayeredPool* higher_pool) {
677 base_.RemoveHigherLayeredPool(higher_pool);
[email protected]ad74a592011-01-21 18:40:55678}
679
[email protected]51fdc7c2012-04-10 19:19:48680bool SSLClientSocketPool::CloseOneIdleConnection() {
681 if (base_.CloseOneIdleSocket())
682 return true;
[email protected]043b68c82013-08-22 23:41:52683 return base_.CloseOneIdleConnectionInHigherLayeredPool();
684}
685
686void SSLClientSocketPool::OnSSLConfigChanged() {
687 FlushWithError(ERR_NETWORK_CHANGED);
[email protected]51fdc7c2012-04-10 19:19:48688}
689
[email protected]e60e47a2010-07-14 03:37:18690} // namespace net