blob: 2efa40434b64b74dc0753a685b12823af8eac2f2 [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
davidben3b00e402016-09-20 14:31:067#include <openssl/ssl.h>
8
dchengc7eeda422015-12-26 03:56:489#include <utility>
10
[email protected]6ecf2b92011-12-15 01:14:5211#include "base/bind.h"
12#include "base/bind_helpers.h"
[email protected]c63248d42011-02-18 17:54:3913#include "base/metrics/field_trial.h"
asvitkinec3c93722015-06-17 14:48:3714#include "base/metrics/histogram_macros.h"
[email protected]92a31242013-06-28 18:08:0815#include "base/metrics/sparse_histogram.h"
pkasting379234c2015-04-08 04:42:1216#include "base/profiler/scoped_tracker.h"
ssid6d6b40102016-04-05 18:59:5617#include "base/trace_event/trace_event.h"
[email protected]ba00b492010-09-08 14:53:3818#include "base/values.h"
[email protected]4f4de7e62010-11-12 19:55:2719#include "net/base/host_port_pair.h"
[email protected]536fd0b2013-03-14 17:41:5720#include "net/base/net_errors.h"
[email protected]33b511c2010-08-11 00:04:4321#include "net/http/http_proxy_client_socket.h"
22#include "net/http/http_proxy_client_socket_pool.h"
mikecirone8b85c432016-09-08 19:11:0023#include "net/log/net_log_source_type.h"
mikecironef22f9812016-10-04 03:40:1924#include "net/log/net_log_with_source.h"
[email protected]e60e47a2010-07-14 03:37:1825#include "net/socket/client_socket_factory.h"
26#include "net/socket/client_socket_handle.h"
[email protected]33b511c2010-08-11 00:04:4327#include "net/socket/socks_client_socket_pool.h"
28#include "net/socket/ssl_client_socket.h"
[email protected]ab739042011-04-07 15:22:2829#include "net/socket/transport_client_socket_pool.h"
[email protected]536fd0b2013-03-14 17:41:5730#include "net/ssl/ssl_cert_request_info.h"
[email protected]92a31242013-06-28 18:08:0831#include "net/ssl/ssl_connection_status_flags.h"
32#include "net/ssl/ssl_info.h"
[email protected]e60e47a2010-07-14 03:37:1833
34namespace net {
35
mikecironef22f9812016-10-04 03:40:1936class NetLog;
37
[email protected]e60e47a2010-07-14 03:37:1838SSLSocketParams::SSLSocketParams(
[email protected]ea79ba92013-08-15 21:56:2039 const scoped_refptr<TransportSocketParams>& direct_params,
40 const scoped_refptr<SOCKSSocketParams>& socks_proxy_params,
[email protected]2431756e2010-09-29 20:26:1341 const scoped_refptr<HttpProxySocketParams>& http_proxy_params,
[email protected]4f4de7e62010-11-12 19:55:2742 const HostPortPair& host_and_port,
[email protected]e60e47a2010-07-14 03:37:1843 const SSLConfig& ssl_config,
[email protected]5e5021a2013-07-17 05:23:3644 PrivacyMode privacy_mode,
[email protected]e60e47a2010-07-14 03:37:1845 int load_flags,
bncb076baf2015-06-05 00:01:1246 bool expect_spdy)
[email protected]ea79ba92013-08-15 21:56:2047 : direct_params_(direct_params),
48 socks_proxy_params_(socks_proxy_params),
[email protected]e60e47a2010-07-14 03:37:1849 http_proxy_params_(http_proxy_params),
[email protected]4f4de7e62010-11-12 19:55:2750 host_and_port_(host_and_port),
[email protected]e60e47a2010-07-14 03:37:1851 ssl_config_(ssl_config),
[email protected]5e5021a2013-07-17 05:23:3652 privacy_mode_(privacy_mode),
[email protected]e60e47a2010-07-14 03:37:1853 load_flags_(load_flags),
mmenked3641e12016-01-28 16:06:1554 expect_spdy_(expect_spdy) {
55 // Only one set of lower level pool params should be non-NULL.
56 DCHECK((direct_params_ && !socks_proxy_params_ && !http_proxy_params_) ||
57 (!direct_params_ && socks_proxy_params_ && !http_proxy_params_) ||
58 (!direct_params_ && !socks_proxy_params_ && http_proxy_params_));
[email protected]e60e47a2010-07-14 03:37:1859}
60
61SSLSocketParams::~SSLSocketParams() {}
62
[email protected]ea79ba92013-08-15 21:56:2063SSLSocketParams::ConnectionType SSLSocketParams::GetConnectionType() const {
dcheng707f8602014-09-04 00:13:5264 if (direct_params_.get()) {
65 DCHECK(!socks_proxy_params_.get());
66 DCHECK(!http_proxy_params_.get());
[email protected]ea79ba92013-08-15 21:56:2067 return DIRECT;
68 }
69
dcheng707f8602014-09-04 00:13:5270 if (socks_proxy_params_.get()) {
71 DCHECK(!http_proxy_params_.get());
[email protected]ea79ba92013-08-15 21:56:2072 return SOCKS_PROXY;
73 }
74
dcheng707f8602014-09-04 00:13:5275 DCHECK(http_proxy_params_.get());
[email protected]ea79ba92013-08-15 21:56:2076 return HTTP_PROXY;
77}
78
79const scoped_refptr<TransportSocketParams>&
80SSLSocketParams::GetDirectConnectionParams() const {
81 DCHECK_EQ(GetConnectionType(), DIRECT);
82 return direct_params_;
83}
84
85const scoped_refptr<SOCKSSocketParams>&
86SSLSocketParams::GetSocksProxyConnectionParams() const {
87 DCHECK_EQ(GetConnectionType(), SOCKS_PROXY);
88 return socks_proxy_params_;
89}
90
91const scoped_refptr<HttpProxySocketParams>&
92SSLSocketParams::GetHttpProxyConnectionParams() const {
93 DCHECK_EQ(GetConnectionType(), HTTP_PROXY);
94 return http_proxy_params_;
95}
96
[email protected]e60e47a2010-07-14 03:37:1897// Timeout for the SSL handshake portion of the connect.
98static const int kSSLHandshakeTimeoutInSeconds = 30;
99
[email protected]feb79bcd2011-07-21 16:55:17100SSLConnectJob::SSLConnectJob(const std::string& group_name,
[email protected]3f6007ab2013-08-22 19:45:39101 RequestPriority priority,
mmenked3641e12016-01-28 16:06:15102 ClientSocketPool::RespectLimits respect_limits,
[email protected]feb79bcd2011-07-21 16:55:17103 const scoped_refptr<SSLSocketParams>& params,
104 const base::TimeDelta& timeout_duration,
105 TransportClientSocketPool* transport_pool,
106 SOCKSClientSocketPool* socks_pool,
107 HttpProxyClientSocketPool* http_proxy_pool,
108 ClientSocketFactory* client_socket_factory,
[email protected]feb79bcd2011-07-21 16:55:17109 const SSLClientSocketContext& context,
110 Delegate* delegate,
111 NetLog* net_log)
tfarina428341112016-09-22 13:38:20112 : ConnectJob(
113 group_name,
114 timeout_duration,
115 priority,
116 respect_limits,
117 delegate,
118 NetLogWithSource::Make(net_log, NetLogSourceType::CONNECT_JOB)),
[email protected]e60e47a2010-07-14 03:37:18119 params_(params),
[email protected]ab739042011-04-07 15:22:28120 transport_pool_(transport_pool),
[email protected]e60e47a2010-07-14 03:37:18121 socks_pool_(socks_pool),
[email protected]2431756e2010-09-29 20:26:13122 http_proxy_pool_(http_proxy_pool),
[email protected]e60e47a2010-07-14 03:37:18123 client_socket_factory_(client_socket_factory),
[email protected]5e5021a2013-07-17 05:23:36124 context_(context.cert_verifier,
[email protected]6b8a3c742014-07-25 00:25:35125 context.channel_id_service,
[email protected]5e5021a2013-07-17 05:23:36126 context.transport_security_state,
[email protected]284303b62013-11-28 15:11:54127 context.cert_transparency_verifier,
estark6f9b3d82016-01-12 21:37:05128 context.ct_policy_enforcer,
[email protected]314b03992014-04-01 01:28:53129 (params->privacy_mode() == PRIVACY_MODE_ENABLED
[email protected]5e5021a2013-07-17 05:23:36130 ? "pm/" + context.ssl_session_cache_shard
131 : context.ssl_session_cache_shard)),
rsleevif020edc2015-03-16 19:31:24132 callback_(
mmenked3641e12016-01-28 16:06:15133 base::Bind(&SSLConnectJob::OnIOComplete, base::Unretained(this))) {}
[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);
ttuttle1f2d7e92015-04-28 16:17:47169
170 handle->set_connection_attempts(connection_attempts_);
[email protected]e60e47a2010-07-14 03:37:18171}
172
173void SSLConnectJob::OnIOComplete(int result) {
174 int rv = DoLoop(result);
175 if (rv != ERR_IO_PENDING)
176 NotifyDelegateOfCompletion(rv); // Deletes |this|.
177}
178
179int SSLConnectJob::DoLoop(int result) {
ssid6d6b40102016-04-05 18:59:56180 TRACE_EVENT0("net", "SSLConnectJob::DoLoop");
[email protected]e60e47a2010-07-14 03:37:18181 DCHECK_NE(next_state_, STATE_NONE);
182
183 int rv = result;
184 do {
185 State state = next_state_;
186 next_state_ = STATE_NONE;
187 switch (state) {
[email protected]ab739042011-04-07 15:22:28188 case STATE_TRANSPORT_CONNECT:
[email protected]e60e47a2010-07-14 03:37:18189 DCHECK_EQ(OK, rv);
[email protected]ab739042011-04-07 15:22:28190 rv = DoTransportConnect();
[email protected]e60e47a2010-07-14 03:37:18191 break;
[email protected]ab739042011-04-07 15:22:28192 case STATE_TRANSPORT_CONNECT_COMPLETE:
193 rv = DoTransportConnectComplete(rv);
[email protected]e60e47a2010-07-14 03:37:18194 break;
195 case STATE_SOCKS_CONNECT:
196 DCHECK_EQ(OK, rv);
197 rv = DoSOCKSConnect();
198 break;
199 case STATE_SOCKS_CONNECT_COMPLETE:
200 rv = DoSOCKSConnectComplete(rv);
201 break;
202 case STATE_TUNNEL_CONNECT:
203 DCHECK_EQ(OK, rv);
204 rv = DoTunnelConnect();
205 break;
206 case STATE_TUNNEL_CONNECT_COMPLETE:
207 rv = DoTunnelConnectComplete(rv);
208 break;
209 case STATE_SSL_CONNECT:
210 DCHECK_EQ(OK, rv);
211 rv = DoSSLConnect();
212 break;
213 case STATE_SSL_CONNECT_COMPLETE:
214 rv = DoSSLConnectComplete(rv);
215 break;
216 default:
217 NOTREACHED() << "bad state";
218 rv = ERR_FAILED;
219 break;
220 }
221 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
222
223 return rv;
224}
225
[email protected]ab739042011-04-07 15:22:28226int SSLConnectJob::DoTransportConnect() {
227 DCHECK(transport_pool_);
[email protected]899c3e92010-08-28 15:53:50228
[email protected]ab739042011-04-07 15:22:28229 next_state_ = STATE_TRANSPORT_CONNECT_COMPLETE;
[email protected]e60e47a2010-07-14 03:37:18230 transport_socket_handle_.reset(new ClientSocketHandle());
[email protected]ea79ba92013-08-15 21:56:20231 scoped_refptr<TransportSocketParams> direct_params =
232 params_->GetDirectConnectionParams();
rsleevif020edc2015-03-16 19:31:24233 return transport_socket_handle_->Init(group_name(), direct_params, priority(),
mmenked3641e12016-01-28 16:06:15234 respect_limits(), callback_,
235 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,
mmenked3641e12016-01-28 16:06:15255 priority(), respect_limits(), callback_,
256 socks_pool_, 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,
mmenked3641e12016-01-28 16:06:15274 priority(), respect_limits(), callback_,
275 http_proxy_pool_, 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() {
ssid6d6b40102016-04-05 18:59:56298 TRACE_EVENT0("net", "SSLConnectJob::DoSSLConnect");
pkasting93ba27f62015-02-28 02:53:46299 // TODO(pkasting): Remove ScopedTracker below once crbug.com/462815 is fixed.
pkasting58e029b2015-02-21 05:17:28300 tracked_objects::ScopedTracker tracking_profile(
rsleevif020edc2015-03-16 19:31:24301 FROM_HERE_WITH_EXPLICIT_FUNCTION("462815 SSLConnectJob::DoSSLConnect"));
302
303 next_state_ = STATE_SSL_CONNECT_COMPLETE;
[email protected]8e458552014-08-05 00:02:15304
[email protected]e60e47a2010-07-14 03:37:18305 // Reset the timeout to just the time allowed for the SSL handshake.
306 ResetTimer(base::TimeDelta::FromSeconds(kSSLHandshakeTimeoutInSeconds));
[email protected]034df0f32013-01-07 23:17:48307
308 // If the handle has a fresh socket, get its connect start and DNS times.
309 // This should always be the case.
310 const LoadTimingInfo::ConnectTiming& socket_connect_timing =
311 transport_socket_handle_->connect_timing();
312 if (!transport_socket_handle_->is_reused() &&
313 !socket_connect_timing.connect_start.is_null()) {
314 // Overwriting |connect_start| serves two purposes - it adjusts timing so
315 // |connect_start| doesn't include dns times, and it adjusts the time so
316 // as not to include time spent waiting for an idle socket.
317 connect_timing_.connect_start = socket_connect_timing.connect_start;
318 connect_timing_.dns_start = socket_connect_timing.dns_start;
319 connect_timing_.dns_end = socket_connect_timing.dns_end;
320 }
321
rsleevif020edc2015-03-16 19:31:24322 connect_timing_.ssl_start = base::TimeTicks::Now();
323
[email protected]18ccfdb2013-08-15 00:13:44324 ssl_socket_ = client_socket_factory_->CreateSSLClientSocket(
dchengc7eeda422015-12-26 03:56:48325 std::move(transport_socket_handle_), params_->host_and_port(),
326 params_->ssl_config(), context_);
rsleevif020edc2015-03-16 19:31:24327 return ssl_socket_->Connect(callback_);
[email protected]e60e47a2010-07-14 03:37:18328}
329
330int SSLConnectJob::DoSSLConnectComplete(int result) {
rvargas1270c002015-04-03 08:11:09331 // TODO(rvargas): Remove ScopedTracker below once crbug.com/462784 is fixed.
332 tracked_objects::ScopedTracker tracking_profile(
333 FROM_HERE_WITH_EXPLICIT_FUNCTION(
334 "462784 SSLConnectJob::DoSSLConnectComplete"));
335
[email protected]034df0f32013-01-07 23:17:48336 connect_timing_.ssl_end = base::TimeTicks::Now();
337
ttuttle1f2d7e92015-04-28 16:17:47338 if (result != OK && !server_address_.address().empty()) {
339 connection_attempts_.push_back(ConnectionAttempt(server_address_, result));
340 server_address_ = IPEndPoint();
341 }
342
bnc94c92842016-09-21 15:22:52343 // If we want SPDY over ALPN, make sure it succeeded.
bncb076baf2015-06-05 00:01:12344 if (params_->expect_spdy() &&
bnc7ba7da82016-08-03 14:08:37345 ssl_socket_->GetNegotiatedProtocol() != kProtoHTTP2) {
bnc94c92842016-09-21 15:22:52346 return ERR_ALPN_NEGOTIATION_FAILED;
davidben6974bf72015-04-27 17:52:48347 }
[email protected]e60e47a2010-07-14 03:37:18348
349 if (result == OK ||
350 ssl_socket_->IgnoreCertError(result, params_->load_flags())) {
[email protected]034df0f32013-01-07 23:17:48351 DCHECK(!connect_timing_.ssl_start.is_null());
[email protected]e60e47a2010-07-14 03:37:18352 base::TimeDelta connect_duration =
[email protected]034df0f32013-01-07 23:17:48353 connect_timing_.ssl_end - connect_timing_.ssl_start;
bncb076baf2015-06-05 00:01:12354 if (params_->expect_spdy()) {
[email protected]847276962013-03-08 23:53:17355 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SpdyConnectionLatency_2",
[email protected]e60e47a2010-07-14 03:37:18356 connect_duration,
357 base::TimeDelta::FromMilliseconds(1),
[email protected]847276962013-03-08 23:53:17358 base::TimeDelta::FromMinutes(1),
[email protected]e60e47a2010-07-14 03:37:18359 100);
[email protected]f906bfe2011-06-09 16:35:24360 }
361
[email protected]847276962013-03-08 23:53:17362 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_2",
[email protected]f906bfe2011-06-09 16:35:24363 connect_duration,
364 base::TimeDelta::FromMilliseconds(1),
[email protected]847276962013-03-08 23:53:17365 base::TimeDelta::FromMinutes(1),
[email protected]f906bfe2011-06-09 16:35:24366 100);
367
[email protected]b076d6c2011-06-29 14:47:51368 SSLInfo ssl_info;
davidbend3f15152015-02-20 23:43:09369 bool has_ssl_info = ssl_socket_->GetSSLInfo(&ssl_info);
370 DCHECK(has_ssl_info);
[email protected]b076d6c2011-06-29 14:47:51371
davidben9ff250e02015-02-19 23:06:51372 UMA_HISTOGRAM_ENUMERATION("Net.SSLVersion", SSLConnectionStatusToVersion(
373 ssl_info.connection_status),
374 SSL_CONNECTION_VERSION_MAX);
375
Avi Drissman13fc8932015-12-20 04:40:46376 uint16_t cipher_suite =
sigbjorn66456a22015-09-18 10:45:14377 SSLConnectionStatusToCipherSuite(ssl_info.connection_status);
378 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSL_CipherSuite", cipher_suite);
379
davidben3b00e402016-09-20 14:31:06380 const SSL_CIPHER* cipher = SSL_get_cipher_by_value(cipher_suite);
381 bool is_cecpq1 = cipher && SSL_CIPHER_is_CECPQ1(cipher);
382
383 if (ssl_info.key_exchange_group != 0) {
sigbjorn66456a22015-09-18 10:45:14384 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSL_KeyExchange.ECDHE",
davidben3b00e402016-09-20 14:31:06385 ssl_info.key_exchange_group);
sigbjorn66456a22015-09-18 10:45:14386 }
[email protected]92a31242013-06-28 18:08:08387
[email protected]b076d6c2011-06-29 14:47:51388 if (ssl_info.handshake_type == SSLInfo::HANDSHAKE_RESUME) {
389 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Resume_Handshake",
390 connect_duration,
391 base::TimeDelta::FromMilliseconds(1),
392 base::TimeDelta::FromMinutes(1),
393 100);
394 } else if (ssl_info.handshake_type == SSLInfo::HANDSHAKE_FULL) {
395 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Full_Handshake",
396 connect_duration,
397 base::TimeDelta::FromMilliseconds(1),
398 base::TimeDelta::FromMinutes(1),
399 100);
400 }
401
[email protected]f906bfe2011-06-09 16:35:24402 const std::string& host = params_->host_and_port().host();
[email protected]8e458552014-08-05 00:02:15403 bool is_google =
404 host == "google.com" ||
405 (host.size() > 11 && host.rfind(".google.com") == host.size() - 11);
[email protected]f906bfe2011-06-09 16:35:24406 if (is_google) {
[email protected]847276962013-03-08 23:53:17407 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Google2",
[email protected]e60e47a2010-07-14 03:37:18408 connect_duration,
409 base::TimeDelta::FromMilliseconds(1),
[email protected]847276962013-03-08 23:53:17410 base::TimeDelta::FromMinutes(1),
[email protected]e60e47a2010-07-14 03:37:18411 100);
[email protected]b076d6c2011-06-29 14:47:51412 if (ssl_info.handshake_type == SSLInfo::HANDSHAKE_RESUME) {
413 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Google_"
414 "Resume_Handshake",
415 connect_duration,
416 base::TimeDelta::FromMilliseconds(1),
417 base::TimeDelta::FromMinutes(1),
418 100);
419 } else if (ssl_info.handshake_type == SSLInfo::HANDSHAKE_FULL) {
420 UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_Google_"
421 "Full_Handshake",
422 connect_duration,
423 base::TimeDelta::FromMilliseconds(1),
424 base::TimeDelta::FromMinutes(1),
425 100);
mabe0d8c582016-08-12 02:06:40426
427 // These are hosts that we expect to always offer CECPQ1. Connections
428 // to them, whether or not this browser is in the experiment group, form
429 // the basis of our comparisons.
mab537c7b12016-08-15 23:47:21430 bool cecpq1_expected_to_be_offered =
431 ssl_info.is_issued_by_known_root &&
mabe0d8c582016-08-12 02:06:40432 (host == "play.google.com" || host == "checkout.google.com" ||
433 host == "wallet.google.com");
mab537c7b12016-08-15 23:47:21434 if (cecpq1_expected_to_be_offered) {
mabe0d8c582016-08-12 02:06:40435 UMA_HISTOGRAM_CUSTOM_TIMES(
436 "Net.SSL_Connection_Latency_PostQuantumSupported_Full_Handshake",
437 connect_duration, base::TimeDelta::FromMilliseconds(1),
438 base::TimeDelta::FromMinutes(1), 100);
439 if (SSLClientSocket::IsPostQuantumExperimentEnabled()) {
440 // But don't trust that these hosts offer CECPQ1: make sure. If
441 // we're doing everything right on the server side, |is_cecpq1|
442 // should always be true if we get here, modulo MITM.
443 UMA_HISTOGRAM_BOOLEAN("Net.SSL_Connection_PostQuantum_Negotiated",
444 is_cecpq1);
445 }
446 }
[email protected]b076d6c2011-06-29 14:47:51447 }
[email protected]835d7c82010-10-14 04:38:38448 }
[email protected]e60e47a2010-07-14 03:37:18449 }
[email protected]8b498692010-07-16 17:11:43450
jeremyim8d44fadd2015-02-10 19:18:15451 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSL_Connection_Error", std::abs(result));
jeremyim8d44fadd2015-02-10 19:18:15452
[email protected]8b498692010-07-16 17:11:43453 if (result == OK || IsCertificateError(result)) {
dchengc7eeda422015-12-26 03:56:48454 SetSocket(std::move(ssl_socket_));
[email protected]8b498692010-07-16 17:11:43455 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
456 error_response_info_.cert_request_info = new SSLCertRequestInfo;
[email protected]90499482013-06-01 00:39:50457 ssl_socket_->GetSSLCertRequestInfo(
458 error_response_info_.cert_request_info.get());
[email protected]8b498692010-07-16 17:11:43459 }
[email protected]e60e47a2010-07-14 03:37:18460
461 return result;
462}
463
[email protected]ea79ba92013-08-15 21:56:20464SSLConnectJob::State SSLConnectJob::GetInitialState(
465 SSLSocketParams::ConnectionType connection_type) {
466 switch (connection_type) {
467 case SSLSocketParams::DIRECT:
468 return STATE_TRANSPORT_CONNECT;
469 case SSLSocketParams::HTTP_PROXY:
470 return STATE_TUNNEL_CONNECT;
471 case SSLSocketParams::SOCKS_PROXY:
472 return STATE_SOCKS_CONNECT;
[email protected]ad74a592011-01-21 18:40:55473 }
[email protected]ea79ba92013-08-15 21:56:20474 NOTREACHED();
475 return STATE_NONE;
476}
477
478int SSLConnectJob::ConnectInternal() {
479 next_state_ = GetInitialState(params_->GetConnectionType());
[email protected]ad74a592011-01-21 18:40:55480 return DoLoop(OK);
[email protected]e60e47a2010-07-14 03:37:18481}
482
483SSLClientSocketPool::SSLConnectJobFactory::SSLConnectJobFactory(
[email protected]ab739042011-04-07 15:22:28484 TransportClientSocketPool* transport_pool,
[email protected]2431756e2010-09-29 20:26:13485 SOCKSClientSocketPool* socks_pool,
486 HttpProxyClientSocketPool* http_proxy_pool,
[email protected]e60e47a2010-07-14 03:37:18487 ClientSocketFactory* client_socket_factory,
[email protected]feb79bcd2011-07-21 16:55:17488 const SSLClientSocketContext& context,
[email protected]e60e47a2010-07-14 03:37:18489 NetLog* net_log)
[email protected]ab739042011-04-07 15:22:28490 : transport_pool_(transport_pool),
[email protected]e60e47a2010-07-14 03:37:18491 socks_pool_(socks_pool),
[email protected]2431756e2010-09-29 20:26:13492 http_proxy_pool_(http_proxy_pool),
[email protected]e60e47a2010-07-14 03:37:18493 client_socket_factory_(client_socket_factory),
[email protected]feb79bcd2011-07-21 16:55:17494 context_(context),
[email protected]cffd7f92014-08-21 21:30:50495 net_log_(net_log) {
[email protected]e60e47a2010-07-14 03:37:18496 base::TimeDelta max_transport_timeout = base::TimeDelta();
497 base::TimeDelta pool_timeout;
[email protected]ab739042011-04-07 15:22:28498 if (transport_pool_)
499 max_transport_timeout = transport_pool_->ConnectionTimeout();
[email protected]e60e47a2010-07-14 03:37:18500 if (socks_pool_) {
501 pool_timeout = socks_pool_->ConnectionTimeout();
502 if (pool_timeout > max_transport_timeout)
503 max_transport_timeout = pool_timeout;
504 }
505 if (http_proxy_pool_) {
506 pool_timeout = http_proxy_pool_->ConnectionTimeout();
507 if (pool_timeout > max_transport_timeout)
508 max_transport_timeout = pool_timeout;
509 }
510 timeout_ = max_transport_timeout +
511 base::TimeDelta::FromSeconds(kSSLHandshakeTimeoutInSeconds);
512}
513
[email protected]8e458552014-08-05 00:02:15514SSLClientSocketPool::SSLConnectJobFactory::~SSLConnectJobFactory() {
[email protected]8e458552014-08-05 00:02:15515}
516
[email protected]e60e47a2010-07-14 03:37:18517SSLClientSocketPool::SSLClientSocketPool(
518 int max_sockets,
519 int max_sockets_per_group,
[email protected]822581d2010-12-16 17:27:15520 CertVerifier* cert_verifier,
[email protected]6b8a3c742014-07-25 00:25:35521 ChannelIDService* channel_id_service,
[email protected]a2a41972011-12-07 17:47:27522 TransportSecurityState* transport_security_state,
[email protected]284303b62013-11-28 15:11:54523 CTVerifier* cert_transparency_verifier,
estark6f9b3d82016-01-12 21:37:05524 CTPolicyEnforcer* ct_policy_enforcer,
[email protected]c3456bb2011-12-12 22:22:19525 const std::string& ssl_session_cache_shard,
[email protected]e60e47a2010-07-14 03:37:18526 ClientSocketFactory* client_socket_factory,
[email protected]ab739042011-04-07 15:22:28527 TransportClientSocketPool* transport_pool,
[email protected]2431756e2010-09-29 20:26:13528 SOCKSClientSocketPool* socks_pool,
529 HttpProxyClientSocketPool* http_proxy_pool,
[email protected]7abf7d22010-09-04 01:41:59530 SSLConfigService* ssl_config_service,
[email protected]e60e47a2010-07-14 03:37:18531 NetLog* net_log)
[email protected]ab739042011-04-07 15:22:28532 : transport_pool_(transport_pool),
[email protected]ba00b492010-09-08 14:53:38533 socks_pool_(socks_pool),
[email protected]2431756e2010-09-29 20:26:13534 http_proxy_pool_(http_proxy_pool),
[email protected]8e458552014-08-05 00:02:15535 base_(this,
536 max_sockets,
537 max_sockets_per_group,
[email protected]82b8c962011-10-12 09:17:30538 ClientSocketPool::unused_idle_socket_timeout(),
539 ClientSocketPool::used_idle_socket_timeout(),
[email protected]8e458552014-08-05 00:02:15540 new SSLConnectJobFactory(
541 transport_pool,
542 socks_pool,
543 http_proxy_pool,
544 client_socket_factory,
[email protected]8e458552014-08-05 00:02:15545 SSLClientSocketContext(cert_verifier,
546 channel_id_service,
547 transport_security_state,
548 cert_transparency_verifier,
estark6f9b3d82016-01-12 21:37:05549 ct_policy_enforcer,
[email protected]8e458552014-08-05 00:02:15550 ssl_session_cache_shard),
[email protected]8e458552014-08-05 00:02:15551 net_log)),
rsleevif020edc2015-03-16 19:31:24552 ssl_config_service_(ssl_config_service) {
[email protected]90499482013-06-01 00:39:50553 if (ssl_config_service_.get())
[email protected]7abf7d22010-09-04 01:41:59554 ssl_config_service_->AddObserver(this);
[email protected]51fdc7c2012-04-10 19:19:48555 if (transport_pool_)
[email protected]043b68c82013-08-22 23:41:52556 base_.AddLowerLayeredPool(transport_pool_);
[email protected]51fdc7c2012-04-10 19:19:48557 if (socks_pool_)
[email protected]043b68c82013-08-22 23:41:52558 base_.AddLowerLayeredPool(socks_pool_);
[email protected]51fdc7c2012-04-10 19:19:48559 if (http_proxy_pool_)
[email protected]043b68c82013-08-22 23:41:52560 base_.AddLowerLayeredPool(http_proxy_pool_);
[email protected]7abf7d22010-09-04 01:41:59561}
[email protected]e60e47a2010-07-14 03:37:18562
[email protected]7abf7d22010-09-04 01:41:59563SSLClientSocketPool::~SSLClientSocketPool() {
[email protected]90499482013-06-01 00:39:50564 if (ssl_config_service_.get())
[email protected]7abf7d22010-09-04 01:41:59565 ssl_config_service_->RemoveObserver(this);
566}
[email protected]e60e47a2010-07-14 03:37:18567
danakj655b66c2016-04-16 00:51:38568std::unique_ptr<ConnectJob>
569SSLClientSocketPool::SSLConnectJobFactory::NewConnectJob(
[email protected]ad74a592011-01-21 18:40:55570 const std::string& group_name,
571 const PoolBase::Request& request,
572 ConnectJob::Delegate* delegate) const {
danakj655b66c2016-04-16 00:51:38573 return std::unique_ptr<ConnectJob>(new SSLConnectJob(
mmenked3641e12016-01-28 16:06:15574 group_name, request.priority(), request.respect_limits(),
575 request.params(), ConnectionTimeout(), transport_pool_, socks_pool_,
576 http_proxy_pool_, client_socket_factory_, context_, delegate, net_log_));
[email protected]ad74a592011-01-21 18:40:55577}
578
[email protected]cffd7f92014-08-21 21:30:50579base::TimeDelta SSLClientSocketPool::SSLConnectJobFactory::ConnectionTimeout()
580 const {
[email protected]2a848e0e2012-08-09 22:27:31581 return timeout_;
582}
583
[email protected]e60e47a2010-07-14 03:37:18584int SSLClientSocketPool::RequestSocket(const std::string& group_name,
585 const void* socket_params,
586 RequestPriority priority,
mmenked3641e12016-01-28 16:06:15587 RespectLimits respect_limits,
[email protected]e60e47a2010-07-14 03:37:18588 ClientSocketHandle* handle,
[email protected]49639fa2011-12-20 23:22:41589 const CompletionCallback& callback,
tfarina428341112016-09-22 13:38:20590 const NetLogWithSource& net_log) {
[email protected]e60e47a2010-07-14 03:37:18591 const scoped_refptr<SSLSocketParams>* casted_socket_params =
592 static_cast<const scoped_refptr<SSLSocketParams>*>(socket_params);
593
594 return base_.RequestSocket(group_name, *casted_socket_params, priority,
mmenked3641e12016-01-28 16:06:15595 respect_limits, handle, callback, net_log);
[email protected]e60e47a2010-07-14 03:37:18596}
597
tfarina428341112016-09-22 13:38:20598void SSLClientSocketPool::RequestSockets(const std::string& group_name,
599 const void* params,
600 int num_sockets,
601 const NetLogWithSource& net_log) {
[email protected]2c2bef152010-10-13 00:55:03602 const scoped_refptr<SSLSocketParams>* casted_params =
603 static_cast<const scoped_refptr<SSLSocketParams>*>(params);
604
605 base_.RequestSockets(group_name, *casted_params, num_sockets, net_log);
606}
607
[email protected]e60e47a2010-07-14 03:37:18608void SSLClientSocketPool::CancelRequest(const std::string& group_name,
[email protected]05ea9ff2010-07-15 19:08:21609 ClientSocketHandle* handle) {
[email protected]e60e47a2010-07-14 03:37:18610 base_.CancelRequest(group_name, handle);
611}
612
613void SSLClientSocketPool::ReleaseSocket(const std::string& group_name,
danakj655b66c2016-04-16 00:51:38614 std::unique_ptr<StreamSocket> socket,
[email protected]18ccfdb2013-08-15 00:13:44615 int id) {
dchengc7eeda422015-12-26 03:56:48616 base_.ReleaseSocket(group_name, std::move(socket), id);
[email protected]e60e47a2010-07-14 03:37:18617}
618
[email protected]7af985a2012-12-14 22:40:42619void SSLClientSocketPool::FlushWithError(int error) {
620 base_.FlushWithError(error);
[email protected]e60e47a2010-07-14 03:37:18621}
622
623void SSLClientSocketPool::CloseIdleSockets() {
624 base_.CloseIdleSockets();
625}
626
[email protected]ddb1e5a2010-12-13 20:10:45627int SSLClientSocketPool::IdleSocketCount() const {
628 return base_.idle_socket_count();
629}
630
[email protected]e60e47a2010-07-14 03:37:18631int SSLClientSocketPool::IdleSocketCountInGroup(
632 const std::string& group_name) const {
633 return base_.IdleSocketCountInGroup(group_name);
634}
635
636LoadState SSLClientSocketPool::GetLoadState(
637 const std::string& group_name, const ClientSocketHandle* handle) const {
638 return base_.GetLoadState(group_name, handle);
639}
640
danakj655b66c2016-04-16 00:51:38641std::unique_ptr<base::DictionaryValue> SSLClientSocketPool::GetInfoAsValue(
[email protected]ba00b492010-09-08 14:53:38642 const std::string& name,
643 const std::string& type,
644 bool include_nested_pools) const {
danakj655b66c2016-04-16 00:51:38645 std::unique_ptr<base::DictionaryValue> dict(base_.GetInfoAsValue(name, type));
[email protected]ba00b492010-09-08 14:53:38646 if (include_nested_pools) {
[email protected]ea5ef4c2013-06-13 22:50:27647 base::ListValue* list = new base::ListValue();
[email protected]ab739042011-04-07 15:22:28648 if (transport_pool_) {
649 list->Append(transport_pool_->GetInfoAsValue("transport_socket_pool",
650 "transport_socket_pool",
651 false));
[email protected]ba00b492010-09-08 14:53:38652 }
[email protected]2431756e2010-09-29 20:26:13653 if (socks_pool_) {
[email protected]ba00b492010-09-08 14:53:38654 list->Append(socks_pool_->GetInfoAsValue("socks_pool",
655 "socks_pool",
656 true));
657 }
[email protected]2431756e2010-09-29 20:26:13658 if (http_proxy_pool_) {
659 list->Append(http_proxy_pool_->GetInfoAsValue("http_proxy_pool",
660 "http_proxy_pool",
661 true));
662 }
[email protected]ba00b492010-09-08 14:53:38663 dict->Set("nested_pools", list);
664 }
dchengc7eeda422015-12-26 03:56:48665 return dict;
[email protected]ba00b492010-09-08 14:53:38666}
667
[email protected]ddb1e5a2010-12-13 20:10:45668base::TimeDelta SSLClientSocketPool::ConnectionTimeout() const {
669 return base_.ConnectionTimeout();
670}
671
[email protected]043b68c82013-08-22 23:41:52672bool SSLClientSocketPool::IsStalled() const {
673 return base_.IsStalled();
674}
675
676void SSLClientSocketPool::AddHigherLayeredPool(HigherLayeredPool* higher_pool) {
677 base_.AddHigherLayeredPool(higher_pool);
678}
679
680void SSLClientSocketPool::RemoveHigherLayeredPool(
681 HigherLayeredPool* higher_pool) {
682 base_.RemoveHigherLayeredPool(higher_pool);
[email protected]ad74a592011-01-21 18:40:55683}
684
[email protected]51fdc7c2012-04-10 19:19:48685bool SSLClientSocketPool::CloseOneIdleConnection() {
686 if (base_.CloseOneIdleSocket())
687 return true;
[email protected]043b68c82013-08-22 23:41:52688 return base_.CloseOneIdleConnectionInHigherLayeredPool();
689}
690
691void SSLClientSocketPool::OnSSLConfigChanged() {
692 FlushWithError(ERR_NETWORK_CHANGED);
[email protected]51fdc7c2012-04-10 19:19:48693}
694
[email protected]e60e47a2010-07-14 03:37:18695} // namespace net