Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(62)

Side by Side Diff: net/socket/ssl_client_socket_pool.cc

Issue 2800853008: Add a dedicated error code for TLS 1.3 interference. (Closed)
Patch Set: shrink CL Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698