| Index: net/socket/ssl_client_socket_pool.cc
|
| diff --git a/net/socket/ssl_client_socket_pool.cc b/net/socket/ssl_client_socket_pool.cc
|
| index b335e46b1f95330864f82f380a9f69f5e23153ee..a557e5be2e850cf3edf8cab9f524229f5ff0f7b0 100644
|
| --- a/net/socket/ssl_client_socket_pool.cc
|
| +++ b/net/socket/ssl_client_socket_pool.cc
|
| @@ -4,6 +4,7 @@
|
|
|
| #include "net/socket/ssl_client_socket_pool.h"
|
|
|
| +#include <cstdlib>
|
| #include <utility>
|
|
|
| #include "base/bind.h"
|
| @@ -130,7 +131,9 @@ SSLConnectJob::SSLConnectJob(const std::string& group_name,
|
| ? "pm/" + context.ssl_session_cache_shard
|
| : context.ssl_session_cache_shard)),
|
| callback_(
|
| - base::Bind(&SSLConnectJob::OnIOComplete, base::Unretained(this))) {}
|
| + base::Bind(&SSLConnectJob::OnIOComplete, base::Unretained(this))),
|
| + version_interference_probe_(false),
|
| + version_interference_error_(OK) {}
|
|
|
| SSLConnectJob::~SSLConnectJob() {
|
| }
|
| @@ -236,7 +239,10 @@ int SSLConnectJob::DoTransportConnect() {
|
| }
|
|
|
| int SSLConnectJob::DoTransportConnectComplete(int result) {
|
| - connection_attempts_ = transport_socket_handle_->connection_attempts();
|
| + connection_attempts_.insert(
|
| + connection_attempts_.end(),
|
| + transport_socket_handle_->connection_attempts().begin(),
|
| + transport_socket_handle_->connection_attempts().end());
|
| if (result == OK) {
|
| next_state_ = STATE_SSL_CONNECT;
|
| transport_socket_handle_->socket()->GetPeerAddress(&server_address_);
|
| @@ -321,13 +327,22 @@ int SSLConnectJob::DoSSLConnect() {
|
|
|
| connect_timing_.ssl_start = base::TimeTicks::Now();
|
|
|
| + SSLConfig ssl_config = params_->ssl_config();
|
| + if (version_interference_probe_) {
|
| + DCHECK_EQ(SSL_PROTOCOL_VERSION_TLS1_3, ssl_config.version_max);
|
| + ssl_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
|
| + ssl_config.version_interference_probe = true;
|
| + }
|
| ssl_socket_ = client_socket_factory_->CreateSSLClientSocket(
|
| - std::move(transport_socket_handle_), params_->host_and_port(),
|
| - params_->ssl_config(), context_);
|
| + std::move(transport_socket_handle_), params_->host_and_port(), ssl_config,
|
| + context_);
|
| return ssl_socket_->Connect(callback_);
|
| }
|
|
|
| int SSLConnectJob::DoSSLConnectComplete(int result) {
|
| + // Version interference probes should not result in success.
|
| + DCHECK(!version_interference_probe_ || result != OK);
|
| +
|
| // TODO(rvargas): Remove ScopedTracker below once crbug.com/462784 is fixed.
|
| tracked_objects::ScopedTracker tracking_profile(
|
| FROM_HERE_WITH_EXPLICIT_FUNCTION(
|
| @@ -346,6 +361,32 @@ int SSLConnectJob::DoSSLConnectComplete(int result) {
|
| return ERR_ALPN_NEGOTIATION_FAILED;
|
| }
|
|
|
| + // Perform a TLS 1.3 version interference probe on various connection
|
| + // errors. The retry will never produce a successful connection but may map
|
| + // errors to ERR_SSL_VERSION_INTERFERENCE, which signals a probable
|
| + // version-interfering middlebox.
|
| + if (params_->ssl_config().version_max == SSL_PROTOCOL_VERSION_TLS1_3 &&
|
| + !params_->ssl_config().deprecated_cipher_suites_enabled &&
|
| + !version_interference_probe_) {
|
| + if (result == ERR_CONNECTION_CLOSED || result == ERR_SSL_PROTOCOL_ERROR ||
|
| + result == ERR_SSL_VERSION_OR_CIPHER_MISMATCH ||
|
| + result == ERR_CONNECTION_RESET ||
|
| + result == ERR_SSL_BAD_RECORD_MAC_ALERT) {
|
| + // Report the error code for each time a version interference probe is
|
| + // triggered.
|
| + UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSLVersionInterferenceProbeTrigger",
|
| + std::abs(result));
|
| + net_log().AddEventWithNetErrorCode(
|
| + NetLogEventType::SSL_VERSION_INTERFERENCE_PROBE, result);
|
| +
|
| + ResetStateForRetry();
|
| + version_interference_probe_ = true;
|
| + version_interference_error_ = result;
|
| + next_state_ = GetInitialState(params_->GetConnectionType());
|
| + return OK;
|
| + }
|
| + }
|
| +
|
| const std::string& host = params_->host_and_port().host();
|
| bool is_google =
|
| host == "google.com" ||
|
| @@ -450,6 +491,14 @@ int SSLConnectJob::DoSSLConnectComplete(int result) {
|
| std::abs(result));
|
| }
|
|
|
| + if (result == ERR_SSL_VERSION_INTERFERENCE) {
|
| + // Record the error code version interference was detected at.
|
| + DCHECK(version_interference_probe_);
|
| + DCHECK_NE(OK, version_interference_error_);
|
| + UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSLVersionInterferenceError",
|
| + std::abs(version_interference_error_));
|
| + }
|
| +
|
| if (result == OK || IsCertificateError(result)) {
|
| SetSocket(std::move(ssl_socket_));
|
| } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
|
| @@ -480,6 +529,13 @@ int SSLConnectJob::ConnectInternal() {
|
| return DoLoop(OK);
|
| }
|
|
|
| +void SSLConnectJob::ResetStateForRetry() {
|
| + transport_socket_handle_.reset();
|
| + ssl_socket_.reset();
|
| + error_response_info_ = HttpResponseInfo();
|
| + server_address_ = IPEndPoint();
|
| +}
|
| +
|
| SSLClientSocketPool::SSLConnectJobFactory::SSLConnectJobFactory(
|
| TransportClientSocketPool* transport_pool,
|
| SOCKSClientSocketPool* socks_pool,
|
|
|