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

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: mpearson comment 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
« no previous file with comments | « net/socket/ssl_client_socket_pool.h ('k') | net/socket/ssl_client_socket_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « net/socket/ssl_client_socket_pool.h ('k') | net/socket/ssl_client_socket_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698