OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 #include "net/socket/ssl_client_socket_pool.h" | 5 #include "net/socket/ssl_client_socket_pool.h" |
6 | 6 |
| 7 #include <cstdlib> |
7 #include <utility> | 8 #include <utility> |
8 | 9 |
9 #include "base/bind.h" | 10 #include "base/bind.h" |
10 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
11 #include "base/metrics/field_trial.h" | 12 #include "base/metrics/field_trial.h" |
12 #include "base/metrics/histogram_macros.h" | 13 #include "base/metrics/histogram_macros.h" |
13 #include "base/metrics/sparse_histogram.h" | 14 #include "base/metrics/sparse_histogram.h" |
14 #include "base/profiler/scoped_tracker.h" | 15 #include "base/profiler/scoped_tracker.h" |
15 #include "base/trace_event/trace_event.h" | 16 #include "base/trace_event/trace_event.h" |
16 #include "base/values.h" | 17 #include "base/values.h" |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 client_socket_factory_(client_socket_factory), | 124 client_socket_factory_(client_socket_factory), |
124 context_(context.cert_verifier, | 125 context_(context.cert_verifier, |
125 context.channel_id_service, | 126 context.channel_id_service, |
126 context.transport_security_state, | 127 context.transport_security_state, |
127 context.cert_transparency_verifier, | 128 context.cert_transparency_verifier, |
128 context.ct_policy_enforcer, | 129 context.ct_policy_enforcer, |
129 (params->privacy_mode() == PRIVACY_MODE_ENABLED | 130 (params->privacy_mode() == PRIVACY_MODE_ENABLED |
130 ? "pm/" + context.ssl_session_cache_shard | 131 ? "pm/" + context.ssl_session_cache_shard |
131 : context.ssl_session_cache_shard)), | 132 : context.ssl_session_cache_shard)), |
132 callback_( | 133 callback_( |
133 base::Bind(&SSLConnectJob::OnIOComplete, base::Unretained(this))) {} | 134 base::Bind(&SSLConnectJob::OnIOComplete, base::Unretained(this))), |
| 135 version_interference_probe_(false), |
| 136 version_interference_error_(OK) {} |
134 | 137 |
135 SSLConnectJob::~SSLConnectJob() { | 138 SSLConnectJob::~SSLConnectJob() { |
136 } | 139 } |
137 | 140 |
138 LoadState SSLConnectJob::GetLoadState() const { | 141 LoadState SSLConnectJob::GetLoadState() const { |
139 switch (next_state_) { | 142 switch (next_state_) { |
140 case STATE_TUNNEL_CONNECT_COMPLETE: | 143 case STATE_TUNNEL_CONNECT_COMPLETE: |
141 if (transport_socket_handle_->socket()) | 144 if (transport_socket_handle_->socket()) |
142 return LOAD_STATE_ESTABLISHING_PROXY_TUNNEL; | 145 return LOAD_STATE_ESTABLISHING_PROXY_TUNNEL; |
143 // else, fall through. | 146 // else, fall through. |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
229 next_state_ = STATE_TRANSPORT_CONNECT_COMPLETE; | 232 next_state_ = STATE_TRANSPORT_CONNECT_COMPLETE; |
230 transport_socket_handle_.reset(new ClientSocketHandle()); | 233 transport_socket_handle_.reset(new ClientSocketHandle()); |
231 scoped_refptr<TransportSocketParams> direct_params = | 234 scoped_refptr<TransportSocketParams> direct_params = |
232 params_->GetDirectConnectionParams(); | 235 params_->GetDirectConnectionParams(); |
233 return transport_socket_handle_->Init(group_name(), direct_params, priority(), | 236 return transport_socket_handle_->Init(group_name(), direct_params, priority(), |
234 respect_limits(), callback_, | 237 respect_limits(), callback_, |
235 transport_pool_, net_log()); | 238 transport_pool_, net_log()); |
236 } | 239 } |
237 | 240 |
238 int SSLConnectJob::DoTransportConnectComplete(int result) { | 241 int SSLConnectJob::DoTransportConnectComplete(int result) { |
239 connection_attempts_ = transport_socket_handle_->connection_attempts(); | 242 connection_attempts_.insert( |
| 243 connection_attempts_.end(), |
| 244 transport_socket_handle_->connection_attempts().begin(), |
| 245 transport_socket_handle_->connection_attempts().end()); |
240 if (result == OK) { | 246 if (result == OK) { |
241 next_state_ = STATE_SSL_CONNECT; | 247 next_state_ = STATE_SSL_CONNECT; |
242 transport_socket_handle_->socket()->GetPeerAddress(&server_address_); | 248 transport_socket_handle_->socket()->GetPeerAddress(&server_address_); |
243 } | 249 } |
244 | 250 |
245 return result; | 251 return result; |
246 } | 252 } |
247 | 253 |
248 int SSLConnectJob::DoSOCKSConnect() { | 254 int SSLConnectJob::DoSOCKSConnect() { |
249 DCHECK(socks_pool_); | 255 DCHECK(socks_pool_); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
314 // Overwriting |connect_start| serves two purposes - it adjusts timing so | 320 // Overwriting |connect_start| serves two purposes - it adjusts timing so |
315 // |connect_start| doesn't include dns times, and it adjusts the time so | 321 // |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. | 322 // as not to include time spent waiting for an idle socket. |
317 connect_timing_.connect_start = socket_connect_timing.connect_start; | 323 connect_timing_.connect_start = socket_connect_timing.connect_start; |
318 connect_timing_.dns_start = socket_connect_timing.dns_start; | 324 connect_timing_.dns_start = socket_connect_timing.dns_start; |
319 connect_timing_.dns_end = socket_connect_timing.dns_end; | 325 connect_timing_.dns_end = socket_connect_timing.dns_end; |
320 } | 326 } |
321 | 327 |
322 connect_timing_.ssl_start = base::TimeTicks::Now(); | 328 connect_timing_.ssl_start = base::TimeTicks::Now(); |
323 | 329 |
| 330 SSLConfig ssl_config = params_->ssl_config(); |
| 331 if (version_interference_probe_) { |
| 332 DCHECK_EQ(SSL_PROTOCOL_VERSION_TLS1_3, ssl_config.version_max); |
| 333 ssl_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2; |
| 334 ssl_config.version_interference_probe = true; |
| 335 } |
324 ssl_socket_ = client_socket_factory_->CreateSSLClientSocket( | 336 ssl_socket_ = client_socket_factory_->CreateSSLClientSocket( |
325 std::move(transport_socket_handle_), params_->host_and_port(), | 337 std::move(transport_socket_handle_), params_->host_and_port(), ssl_config, |
326 params_->ssl_config(), context_); | 338 context_); |
327 return ssl_socket_->Connect(callback_); | 339 return ssl_socket_->Connect(callback_); |
328 } | 340 } |
329 | 341 |
330 int SSLConnectJob::DoSSLConnectComplete(int result) { | 342 int SSLConnectJob::DoSSLConnectComplete(int result) { |
| 343 // Version interference probes should not result in success. |
| 344 DCHECK(!version_interference_probe_ || result != OK); |
| 345 |
331 // TODO(rvargas): Remove ScopedTracker below once crbug.com/462784 is fixed. | 346 // TODO(rvargas): Remove ScopedTracker below once crbug.com/462784 is fixed. |
332 tracked_objects::ScopedTracker tracking_profile( | 347 tracked_objects::ScopedTracker tracking_profile( |
333 FROM_HERE_WITH_EXPLICIT_FUNCTION( | 348 FROM_HERE_WITH_EXPLICIT_FUNCTION( |
334 "462784 SSLConnectJob::DoSSLConnectComplete")); | 349 "462784 SSLConnectJob::DoSSLConnectComplete")); |
335 | 350 |
336 connect_timing_.ssl_end = base::TimeTicks::Now(); | 351 connect_timing_.ssl_end = base::TimeTicks::Now(); |
337 | 352 |
338 if (result != OK && !server_address_.address().empty()) { | 353 if (result != OK && !server_address_.address().empty()) { |
339 connection_attempts_.push_back(ConnectionAttempt(server_address_, result)); | 354 connection_attempts_.push_back(ConnectionAttempt(server_address_, result)); |
340 server_address_ = IPEndPoint(); | 355 server_address_ = IPEndPoint(); |
341 } | 356 } |
342 | 357 |
343 // If we want SPDY over ALPN, make sure it succeeded. | 358 // If we want SPDY over ALPN, make sure it succeeded. |
344 if (params_->expect_spdy() && | 359 if (params_->expect_spdy() && |
345 ssl_socket_->GetNegotiatedProtocol() != kProtoHTTP2) { | 360 ssl_socket_->GetNegotiatedProtocol() != kProtoHTTP2) { |
346 return ERR_ALPN_NEGOTIATION_FAILED; | 361 return ERR_ALPN_NEGOTIATION_FAILED; |
347 } | 362 } |
348 | 363 |
| 364 // Perform a TLS 1.3 version interference probe on various connection |
| 365 // errors. The retry will never produce a successful connection but may map |
| 366 // errors to ERR_SSL_VERSION_INTERFERENCE, which signals a probable |
| 367 // version-interfering middlebox. |
| 368 if (params_->ssl_config().version_max == SSL_PROTOCOL_VERSION_TLS1_3 && |
| 369 !params_->ssl_config().deprecated_cipher_suites_enabled && |
| 370 !version_interference_probe_) { |
| 371 if (result == ERR_CONNECTION_CLOSED || result == ERR_SSL_PROTOCOL_ERROR || |
| 372 result == ERR_SSL_VERSION_OR_CIPHER_MISMATCH || |
| 373 result == ERR_CONNECTION_RESET || |
| 374 result == ERR_SSL_BAD_RECORD_MAC_ALERT) { |
| 375 // Report the error code for each time a version interference probe is |
| 376 // triggered. |
| 377 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSLVersionInterferenceProbeTrigger", |
| 378 std::abs(result)); |
| 379 net_log().AddEventWithNetErrorCode( |
| 380 NetLogEventType::SSL_VERSION_INTERFERENCE_PROBE, result); |
| 381 |
| 382 ResetStateForRetry(); |
| 383 version_interference_probe_ = true; |
| 384 version_interference_error_ = result; |
| 385 next_state_ = GetInitialState(params_->GetConnectionType()); |
| 386 return OK; |
| 387 } |
| 388 } |
| 389 |
349 const std::string& host = params_->host_and_port().host(); | 390 const std::string& host = params_->host_and_port().host(); |
350 bool is_google = | 391 bool is_google = |
351 host == "google.com" || | 392 host == "google.com" || |
352 (host.size() > 11 && host.rfind(".google.com") == host.size() - 11); | 393 (host.size() > 11 && host.rfind(".google.com") == host.size() - 11); |
353 | 394 |
354 // These are hosts that we intend to use in the initial TLS 1.3 deployment. | 395 // These are hosts that we intend to use in the initial TLS 1.3 deployment. |
355 // TLS connections to them, whether or not this browser is in the experiment | 396 // TLS connections to them, whether or not this browser is in the experiment |
356 // group, form the basis of our comparisons. | 397 // group, form the basis of our comparisons. |
357 bool tls13_supported = | 398 bool tls13_supported = |
358 (host == "drive.google.com" || host == "mail.google.com"); | 399 (host == "drive.google.com" || host == "mail.google.com"); |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
443 if (is_google) { | 484 if (is_google) { |
444 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSL_Connection_Error_Google", | 485 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSL_Connection_Error_Google", |
445 std::abs(result)); | 486 std::abs(result)); |
446 } | 487 } |
447 | 488 |
448 if (tls13_supported) { | 489 if (tls13_supported) { |
449 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSL_Connection_Error_TLS13Experiment", | 490 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSL_Connection_Error_TLS13Experiment", |
450 std::abs(result)); | 491 std::abs(result)); |
451 } | 492 } |
452 | 493 |
| 494 if (result == ERR_SSL_VERSION_INTERFERENCE) { |
| 495 // Record the error code version interference was detected at. |
| 496 DCHECK(version_interference_probe_); |
| 497 DCHECK_NE(OK, version_interference_error_); |
| 498 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSLVersionInterferenceError", |
| 499 std::abs(version_interference_error_)); |
| 500 } |
| 501 |
453 if (result == OK || IsCertificateError(result)) { | 502 if (result == OK || IsCertificateError(result)) { |
454 SetSocket(std::move(ssl_socket_)); | 503 SetSocket(std::move(ssl_socket_)); |
455 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { | 504 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { |
456 error_response_info_.cert_request_info = new SSLCertRequestInfo; | 505 error_response_info_.cert_request_info = new SSLCertRequestInfo; |
457 ssl_socket_->GetSSLCertRequestInfo( | 506 ssl_socket_->GetSSLCertRequestInfo( |
458 error_response_info_.cert_request_info.get()); | 507 error_response_info_.cert_request_info.get()); |
459 } | 508 } |
460 | 509 |
461 return result; | 510 return result; |
462 } | 511 } |
(...skipping 10 matching lines...) Expand all Loading... |
473 } | 522 } |
474 NOTREACHED(); | 523 NOTREACHED(); |
475 return STATE_NONE; | 524 return STATE_NONE; |
476 } | 525 } |
477 | 526 |
478 int SSLConnectJob::ConnectInternal() { | 527 int SSLConnectJob::ConnectInternal() { |
479 next_state_ = GetInitialState(params_->GetConnectionType()); | 528 next_state_ = GetInitialState(params_->GetConnectionType()); |
480 return DoLoop(OK); | 529 return DoLoop(OK); |
481 } | 530 } |
482 | 531 |
| 532 void SSLConnectJob::ResetStateForRetry() { |
| 533 transport_socket_handle_.reset(); |
| 534 ssl_socket_.reset(); |
| 535 error_response_info_ = HttpResponseInfo(); |
| 536 server_address_ = IPEndPoint(); |
| 537 } |
| 538 |
483 SSLClientSocketPool::SSLConnectJobFactory::SSLConnectJobFactory( | 539 SSLClientSocketPool::SSLConnectJobFactory::SSLConnectJobFactory( |
484 TransportClientSocketPool* transport_pool, | 540 TransportClientSocketPool* transport_pool, |
485 SOCKSClientSocketPool* socks_pool, | 541 SOCKSClientSocketPool* socks_pool, |
486 HttpProxyClientSocketPool* http_proxy_pool, | 542 HttpProxyClientSocketPool* http_proxy_pool, |
487 ClientSocketFactory* client_socket_factory, | 543 ClientSocketFactory* client_socket_factory, |
488 const SSLClientSocketContext& context, | 544 const SSLClientSocketContext& context, |
489 NetLog* net_log) | 545 NetLog* net_log) |
490 : transport_pool_(transport_pool), | 546 : transport_pool_(transport_pool), |
491 socks_pool_(socks_pool), | 547 socks_pool_(socks_pool), |
492 http_proxy_pool_(http_proxy_pool), | 548 http_proxy_pool_(http_proxy_pool), |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
703 if (base_.CloseOneIdleSocket()) | 759 if (base_.CloseOneIdleSocket()) |
704 return true; | 760 return true; |
705 return base_.CloseOneIdleConnectionInHigherLayeredPool(); | 761 return base_.CloseOneIdleConnectionInHigherLayeredPool(); |
706 } | 762 } |
707 | 763 |
708 void SSLClientSocketPool::OnSSLConfigChanged() { | 764 void SSLClientSocketPool::OnSSLConfigChanged() { |
709 FlushWithError(ERR_NETWORK_CHANGED); | 765 FlushWithError(ERR_NETWORK_CHANGED); |
710 } | 766 } |
711 | 767 |
712 } // namespace net | 768 } // namespace net |
OLD | NEW |