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