| 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 |