• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/socket/ssl_connect_job.h"
6 
7 #include <cstdlib>
8 #include <memory>
9 #include <utility>
10 
11 #include "base/feature_list.h"
12 #include "base/functional/bind.h"
13 #include "base/functional/callback_helpers.h"
14 #include "base/metrics/histogram_functions.h"
15 #include "base/metrics/histogram_macros.h"
16 #include "net/base/connection_endpoint_metadata.h"
17 #include "net/base/features.h"
18 #include "net/base/host_port_pair.h"
19 #include "net/base/net_errors.h"
20 #include "net/base/trace_constants.h"
21 #include "net/base/tracing.h"
22 #include "net/base/url_util.h"
23 #include "net/cert/x509_util.h"
24 #include "net/http/http_proxy_connect_job.h"
25 #include "net/log/net_log_source_type.h"
26 #include "net/log/net_log_values.h"
27 #include "net/log/net_log_with_source.h"
28 #include "net/socket/client_socket_factory.h"
29 #include "net/socket/client_socket_handle.h"
30 #include "net/socket/socks_connect_job.h"
31 #include "net/socket/ssl_client_socket.h"
32 #include "net/socket/transport_connect_job.h"
33 #include "net/ssl/ssl_cert_request_info.h"
34 #include "net/ssl/ssl_connection_status_flags.h"
35 #include "net/ssl/ssl_info.h"
36 #include "net/ssl/ssl_legacy_crypto_fallback.h"
37 #include "third_party/boringssl/src/include/openssl/pool.h"
38 #include "third_party/boringssl/src/include/openssl/ssl.h"
39 
40 namespace net {
41 
42 namespace {
43 
44 // Timeout for the SSL handshake portion of the connect.
45 constexpr base::TimeDelta kSSLHandshakeTimeout(base::Seconds(30));
46 
47 }  // namespace
48 
SSLSocketParams(scoped_refptr<TransportSocketParams> direct_params,scoped_refptr<SOCKSSocketParams> socks_proxy_params,scoped_refptr<HttpProxySocketParams> http_proxy_params,const HostPortPair & host_and_port,const SSLConfig & ssl_config,PrivacyMode privacy_mode,NetworkAnonymizationKey network_anonymization_key)49 SSLSocketParams::SSLSocketParams(
50     scoped_refptr<TransportSocketParams> direct_params,
51     scoped_refptr<SOCKSSocketParams> socks_proxy_params,
52     scoped_refptr<HttpProxySocketParams> http_proxy_params,
53     const HostPortPair& host_and_port,
54     const SSLConfig& ssl_config,
55     PrivacyMode privacy_mode,
56     NetworkAnonymizationKey network_anonymization_key)
57     : direct_params_(std::move(direct_params)),
58       socks_proxy_params_(std::move(socks_proxy_params)),
59       http_proxy_params_(std::move(http_proxy_params)),
60       host_and_port_(host_and_port),
61       ssl_config_(ssl_config),
62       privacy_mode_(privacy_mode),
63       network_anonymization_key_(network_anonymization_key) {
64   // Only one set of lower level ConnectJob params should be non-NULL.
65   DCHECK((direct_params_ && !socks_proxy_params_ && !http_proxy_params_) ||
66          (!direct_params_ && socks_proxy_params_ && !http_proxy_params_) ||
67          (!direct_params_ && !socks_proxy_params_ && http_proxy_params_));
68 }
69 
70 SSLSocketParams::~SSLSocketParams() = default;
71 
GetConnectionType() const72 SSLSocketParams::ConnectionType SSLSocketParams::GetConnectionType() const {
73   if (direct_params_.get()) {
74     DCHECK(!socks_proxy_params_.get());
75     DCHECK(!http_proxy_params_.get());
76     return DIRECT;
77   }
78 
79   if (socks_proxy_params_.get()) {
80     DCHECK(!http_proxy_params_.get());
81     return SOCKS_PROXY;
82   }
83 
84   DCHECK(http_proxy_params_.get());
85   return HTTP_PROXY;
86 }
87 
88 const scoped_refptr<TransportSocketParams>&
GetDirectConnectionParams() const89 SSLSocketParams::GetDirectConnectionParams() const {
90   DCHECK_EQ(GetConnectionType(), DIRECT);
91   return direct_params_;
92 }
93 
94 const scoped_refptr<SOCKSSocketParams>&
GetSocksProxyConnectionParams() const95 SSLSocketParams::GetSocksProxyConnectionParams() const {
96   DCHECK_EQ(GetConnectionType(), SOCKS_PROXY);
97   return socks_proxy_params_;
98 }
99 
100 const scoped_refptr<HttpProxySocketParams>&
GetHttpProxyConnectionParams() const101 SSLSocketParams::GetHttpProxyConnectionParams() const {
102   DCHECK_EQ(GetConnectionType(), HTTP_PROXY);
103   return http_proxy_params_;
104 }
105 
Create(RequestPriority priority,const SocketTag & socket_tag,const CommonConnectJobParams * common_connect_job_params,scoped_refptr<SSLSocketParams> params,ConnectJob::Delegate * delegate,const NetLogWithSource * net_log)106 std::unique_ptr<SSLConnectJob> SSLConnectJob::Factory::Create(
107     RequestPriority priority,
108     const SocketTag& socket_tag,
109     const CommonConnectJobParams* common_connect_job_params,
110     scoped_refptr<SSLSocketParams> params,
111     ConnectJob::Delegate* delegate,
112     const NetLogWithSource* net_log) {
113   return std::make_unique<SSLConnectJob>(priority, socket_tag,
114                                          common_connect_job_params,
115                                          std::move(params), delegate, net_log);
116 }
117 
SSLConnectJob(RequestPriority priority,const SocketTag & socket_tag,const CommonConnectJobParams * common_connect_job_params,scoped_refptr<SSLSocketParams> params,ConnectJob::Delegate * delegate,const NetLogWithSource * net_log)118 SSLConnectJob::SSLConnectJob(
119     RequestPriority priority,
120     const SocketTag& socket_tag,
121     const CommonConnectJobParams* common_connect_job_params,
122     scoped_refptr<SSLSocketParams> params,
123     ConnectJob::Delegate* delegate,
124     const NetLogWithSource* net_log)
125     : ConnectJob(
126           priority,
127           socket_tag,
128           // The SSLConnectJob's timer is only started during the SSL handshake.
129           base::TimeDelta(),
130           common_connect_job_params,
131           delegate,
132           net_log,
133           NetLogSourceType::SSL_CONNECT_JOB,
134           NetLogEventType::SSL_CONNECT_JOB_CONNECT),
135       params_(std::move(params)),
136       callback_(base::BindRepeating(&SSLConnectJob::OnIOComplete,
137                                     base::Unretained(this))) {}
138 
~SSLConnectJob()139 SSLConnectJob::~SSLConnectJob() {
140   // In the case the job was canceled, need to delete nested job first to
141   // correctly order NetLog events.
142   nested_connect_job_.reset();
143 }
144 
GetLoadState() const145 LoadState SSLConnectJob::GetLoadState() const {
146   switch (next_state_) {
147     case STATE_TRANSPORT_CONNECT:
148     case STATE_SOCKS_CONNECT:
149     case STATE_TUNNEL_CONNECT:
150       return LOAD_STATE_IDLE;
151     case STATE_TRANSPORT_CONNECT_COMPLETE:
152     case STATE_SOCKS_CONNECT_COMPLETE:
153       return nested_connect_job_->GetLoadState();
154     case STATE_TUNNEL_CONNECT_COMPLETE:
155       if (nested_socket_)
156         return LOAD_STATE_ESTABLISHING_PROXY_TUNNEL;
157       return nested_connect_job_->GetLoadState();
158     case STATE_SSL_CONNECT:
159     case STATE_SSL_CONNECT_COMPLETE:
160       return LOAD_STATE_SSL_HANDSHAKE;
161     default:
162       NOTREACHED();
163       return LOAD_STATE_IDLE;
164   }
165 }
166 
HasEstablishedConnection() const167 bool SSLConnectJob::HasEstablishedConnection() const {
168   // If waiting on a nested ConnectJob, defer to that ConnectJob's state.
169   if (nested_connect_job_)
170     return nested_connect_job_->HasEstablishedConnection();
171   // Otherwise, return true if a socket has been created.
172   return nested_socket_ || ssl_socket_;
173 }
174 
OnConnectJobComplete(int result,ConnectJob * job)175 void SSLConnectJob::OnConnectJobComplete(int result, ConnectJob* job) {
176   DCHECK_EQ(job, nested_connect_job_.get());
177   OnIOComplete(result);
178 }
179 
OnNeedsProxyAuth(const HttpResponseInfo & response,HttpAuthController * auth_controller,base::OnceClosure restart_with_auth_callback,ConnectJob * job)180 void SSLConnectJob::OnNeedsProxyAuth(
181     const HttpResponseInfo& response,
182     HttpAuthController* auth_controller,
183     base::OnceClosure restart_with_auth_callback,
184     ConnectJob* job) {
185   DCHECK_EQ(next_state_, STATE_TUNNEL_CONNECT_COMPLETE);
186 
187   // The timer shouldn't have started running yet, since the handshake only
188   // starts after a tunnel has been established through the proxy.
189   DCHECK(!TimerIsRunning());
190 
191   // Just pass the callback up to the consumer. This class doesn't need to do
192   // anything once credentials are provided.
193   NotifyDelegateOfProxyAuth(response, auth_controller,
194                             std::move(restart_with_auth_callback));
195 }
196 
GetConnectionAttempts() const197 ConnectionAttempts SSLConnectJob::GetConnectionAttempts() const {
198   return connection_attempts_;
199 }
200 
GetResolveErrorInfo() const201 ResolveErrorInfo SSLConnectJob::GetResolveErrorInfo() const {
202   return resolve_error_info_;
203 }
204 
IsSSLError() const205 bool SSLConnectJob::IsSSLError() const {
206   return ssl_negotiation_started_;
207 }
208 
GetCertRequestInfo()209 scoped_refptr<SSLCertRequestInfo> SSLConnectJob::GetCertRequestInfo() {
210   return ssl_cert_request_info_;
211 }
212 
HandshakeTimeoutForTesting()213 base::TimeDelta SSLConnectJob::HandshakeTimeoutForTesting() {
214   return kSSLHandshakeTimeout;
215 }
216 
OnIOComplete(int result)217 void SSLConnectJob::OnIOComplete(int result) {
218   int rv = DoLoop(result);
219   if (rv != ERR_IO_PENDING)
220     NotifyDelegateOfCompletion(rv);  // Deletes |this|.
221 }
222 
DoLoop(int result)223 int SSLConnectJob::DoLoop(int result) {
224   TRACE_EVENT0(NetTracingCategory(), "SSLConnectJob::DoLoop");
225   DCHECK_NE(next_state_, STATE_NONE);
226 
227   int rv = result;
228   do {
229     State state = next_state_;
230     next_state_ = STATE_NONE;
231     switch (state) {
232       case STATE_TRANSPORT_CONNECT:
233         DCHECK_EQ(OK, rv);
234         rv = DoTransportConnect();
235         break;
236       case STATE_TRANSPORT_CONNECT_COMPLETE:
237         rv = DoTransportConnectComplete(rv);
238         break;
239       case STATE_SOCKS_CONNECT:
240         DCHECK_EQ(OK, rv);
241         rv = DoSOCKSConnect();
242         break;
243       case STATE_SOCKS_CONNECT_COMPLETE:
244         rv = DoSOCKSConnectComplete(rv);
245         break;
246       case STATE_TUNNEL_CONNECT:
247         DCHECK_EQ(OK, rv);
248         rv = DoTunnelConnect();
249         break;
250       case STATE_TUNNEL_CONNECT_COMPLETE:
251         rv = DoTunnelConnectComplete(rv);
252         break;
253       case STATE_SSL_CONNECT:
254         DCHECK_EQ(OK, rv);
255         rv = DoSSLConnect();
256         break;
257       case STATE_SSL_CONNECT_COMPLETE:
258         rv = DoSSLConnectComplete(rv);
259         break;
260       default:
261         NOTREACHED() << "bad state";
262         rv = ERR_FAILED;
263         break;
264     }
265   } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
266 
267   return rv;
268 }
269 
DoTransportConnect()270 int SSLConnectJob::DoTransportConnect() {
271   DCHECK(!nested_connect_job_);
272   DCHECK(params_->GetDirectConnectionParams());
273   DCHECK(!TimerIsRunning());
274 
275   next_state_ = STATE_TRANSPORT_CONNECT_COMPLETE;
276   // If this is an ECH retry, connect to the same server as before.
277   absl::optional<TransportConnectJob::EndpointResultOverride>
278       endpoint_result_override;
279   if (ech_retry_configs_) {
280     DCHECK(ssl_client_context()->config().EncryptedClientHelloEnabled());
281     DCHECK(endpoint_result_);
282     endpoint_result_override.emplace(*endpoint_result_, dns_aliases_);
283   }
284   nested_connect_job_ = std::make_unique<TransportConnectJob>(
285       priority(), socket_tag(), common_connect_job_params(),
286       params_->GetDirectConnectionParams(), this, &net_log(),
287       std::move(endpoint_result_override));
288   return nested_connect_job_->Connect();
289 }
290 
DoTransportConnectComplete(int result)291 int SSLConnectJob::DoTransportConnectComplete(int result) {
292   resolve_error_info_ = nested_connect_job_->GetResolveErrorInfo();
293   ConnectionAttempts connection_attempts =
294       nested_connect_job_->GetConnectionAttempts();
295   connection_attempts_.insert(connection_attempts_.end(),
296                               connection_attempts.begin(),
297                               connection_attempts.end());
298   if (result == OK) {
299     next_state_ = STATE_SSL_CONNECT;
300     nested_socket_ = nested_connect_job_->PassSocket();
301     nested_socket_->GetPeerAddress(&server_address_);
302     dns_aliases_ = nested_socket_->GetDnsAliases();
303   }
304 
305   return result;
306 }
307 
DoSOCKSConnect()308 int SSLConnectJob::DoSOCKSConnect() {
309   DCHECK(!nested_connect_job_);
310   DCHECK(params_->GetSocksProxyConnectionParams());
311   DCHECK(!TimerIsRunning());
312 
313   next_state_ = STATE_SOCKS_CONNECT_COMPLETE;
314   nested_connect_job_ = std::make_unique<SOCKSConnectJob>(
315       priority(), socket_tag(), common_connect_job_params(),
316       params_->GetSocksProxyConnectionParams(), this, &net_log());
317   return nested_connect_job_->Connect();
318 }
319 
DoSOCKSConnectComplete(int result)320 int SSLConnectJob::DoSOCKSConnectComplete(int result) {
321   resolve_error_info_ = nested_connect_job_->GetResolveErrorInfo();
322   if (result == OK) {
323     next_state_ = STATE_SSL_CONNECT;
324     nested_socket_ = nested_connect_job_->PassSocket();
325   }
326 
327   return result;
328 }
329 
DoTunnelConnect()330 int SSLConnectJob::DoTunnelConnect() {
331   DCHECK(!nested_connect_job_);
332   DCHECK(params_->GetHttpProxyConnectionParams());
333   DCHECK(!TimerIsRunning());
334 
335   next_state_ = STATE_TUNNEL_CONNECT_COMPLETE;
336   scoped_refptr<HttpProxySocketParams> http_proxy_params =
337       params_->GetHttpProxyConnectionParams();
338   nested_connect_job_ = std::make_unique<HttpProxyConnectJob>(
339       priority(), socket_tag(), common_connect_job_params(),
340       params_->GetHttpProxyConnectionParams(), this, &net_log());
341   return nested_connect_job_->Connect();
342 }
343 
DoTunnelConnectComplete(int result)344 int SSLConnectJob::DoTunnelConnectComplete(int result) {
345   resolve_error_info_ = nested_connect_job_->GetResolveErrorInfo();
346   nested_socket_ = nested_connect_job_->PassSocket();
347 
348   if (result < 0) {
349     // Extract the information needed to prompt for appropriate proxy
350     // authentication so that when ClientSocketPoolBaseHelper calls
351     // |GetAdditionalErrorState|, we can easily set the state.
352     if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
353       ssl_cert_request_info_ = nested_connect_job_->GetCertRequestInfo();
354     }
355     return result;
356   }
357 
358   next_state_ = STATE_SSL_CONNECT;
359   return result;
360 }
361 
DoSSLConnect()362 int SSLConnectJob::DoSSLConnect() {
363   TRACE_EVENT0(NetTracingCategory(), "SSLConnectJob::DoSSLConnect");
364   DCHECK(!TimerIsRunning());
365 
366   next_state_ = STATE_SSL_CONNECT_COMPLETE;
367 
368   // Set the timeout to just the time allowed for the SSL handshake.
369   ResetTimer(kSSLHandshakeTimeout);
370 
371   // Get the transport's connect start and DNS times.
372   const LoadTimingInfo::ConnectTiming& socket_connect_timing =
373       nested_connect_job_->connect_timing();
374 
375   // Overwriting |connect_start| serves two purposes - it adjusts timing so
376   // |connect_start| doesn't include dns times, and it adjusts the time so
377   // as not to include time spent waiting for an idle socket.
378   connect_timing_.connect_start = socket_connect_timing.connect_start;
379   connect_timing_.domain_lookup_start =
380       socket_connect_timing.domain_lookup_start;
381   connect_timing_.domain_lookup_end = socket_connect_timing.domain_lookup_end;
382 
383   ssl_negotiation_started_ = true;
384   connect_timing_.ssl_start = base::TimeTicks::Now();
385 
386   // Save the `HostResolverEndpointResult`. `nested_connect_job_` is destroyed
387   // at the end of this function.
388   endpoint_result_ = nested_connect_job_->GetHostResolverEndpointResult();
389 
390   SSLConfig ssl_config = params_->ssl_config();
391   ssl_config.network_anonymization_key = params_->network_anonymization_key();
392   ssl_config.privacy_mode = params_->privacy_mode();
393   // We do the fallback in both cases here to ensure we separate the effect of
394   // disabling sha1 from the effect of having a single automatic retry
395   // on a potentially unreliably network connection.
396   ssl_config.disable_sha1_server_signatures =
397       disable_legacy_crypto_with_fallback_ ||
398       !ssl_client_context()->config().InsecureHashesInTLSHandshakesEnabled();
399 
400   if (ssl_client_context()->config().EncryptedClientHelloEnabled()) {
401     if (ech_retry_configs_) {
402       ssl_config.ech_config_list = *ech_retry_configs_;
403     } else if (endpoint_result_) {
404       ssl_config.ech_config_list = endpoint_result_->metadata.ech_config_list;
405     }
406     if (!ssl_config.ech_config_list.empty()) {
407       // Overriding the DNS lookup only works for direct connections. We
408       // currently do not support ECH with other connection types.
409       DCHECK_EQ(params_->GetConnectionType(), SSLSocketParams::DIRECT);
410     }
411   }
412 
413   ssl_socket_ = client_socket_factory()->CreateSSLClientSocket(
414       ssl_client_context(), std::move(nested_socket_), params_->host_and_port(),
415       ssl_config);
416   nested_connect_job_.reset();
417   return ssl_socket_->Connect(callback_);
418 }
419 
DoSSLConnectComplete(int result)420 int SSLConnectJob::DoSSLConnectComplete(int result) {
421   connect_timing_.ssl_end = base::TimeTicks::Now();
422 
423   if (result != OK && !server_address_.address().empty()) {
424     connection_attempts_.push_back(ConnectionAttempt(server_address_, result));
425     server_address_ = IPEndPoint();
426   }
427 
428   // Many servers which negotiate SHA-1 server signatures in TLS 1.2 actually
429   // support SHA-2 but preferentially sign SHA-1 if available.
430   //
431   // To get more accurate metrics, initially connect with SHA-1 disabled. If
432   // this fails, retry with them enabled. This keeps the legacy algorithms
433   // working for now, but they will only appear in metrics and DevTools if the
434   // site relies on them.
435   //
436   // See https://crbug.com/658905.
437   if (disable_legacy_crypto_with_fallback_ &&
438       (result == ERR_CONNECTION_CLOSED || result == ERR_CONNECTION_RESET ||
439        result == ERR_SSL_PROTOCOL_ERROR ||
440        result == ERR_SSL_VERSION_OR_CIPHER_MISMATCH)) {
441     ResetStateForRestart();
442     disable_legacy_crypto_with_fallback_ = false;
443     next_state_ = GetInitialState(params_->GetConnectionType());
444     return OK;
445   }
446 
447   // We record metrics based on whether the server advertised ECH support in
448   // DNS. This allows the metrics to measure the same set of servers in both
449   // control and experiment group.
450   const bool is_ech_capable =
451       endpoint_result_ && !endpoint_result_->metadata.ech_config_list.empty();
452 
453   if (!ech_retry_configs_ && result == ERR_ECH_NOT_NEGOTIATED &&
454       ssl_client_context()->config().EncryptedClientHelloEnabled()) {
455     // We used ECH, and the server could not decrypt the ClientHello. However,
456     // it was able to handshake with the public name and send authenticated
457     // retry configs. If this is not the first time around, retry the connection
458     // with the new ECHConfigList, or with ECH disabled (empty retry configs),
459     // as directed.
460     //
461     // See
462     // https://www.ietf.org/archive/id/draft-ietf-tls-esni-13.html#section-6.1.6
463     DCHECK(is_ech_capable);
464     ech_retry_configs_ = ssl_socket_->GetECHRetryConfigs();
465     net_log().AddEvent(
466         NetLogEventType::SSL_CONNECT_JOB_RESTART_WITH_ECH_CONFIG_LIST, [&] {
467           base::Value::Dict dict;
468           dict.Set("bytes", NetLogBinaryValue(*ech_retry_configs_));
469           return dict;
470         });
471 
472     // TODO(https://crbug.com/1091403): Add histograms for how often this
473     // happens.
474     ResetStateForRestart();
475     next_state_ = GetInitialState(params_->GetConnectionType());
476     return OK;
477   }
478 
479   const std::string& host = params_->host_and_port().host();
480   if (is_ech_capable &&
481       base::FeatureList::IsEnabled(features::kEncryptedClientHello)) {
482     // These values are persisted to logs. Entries should not be renumbered
483     // and numeric values should never be reused.
484     enum class ECHResult {
485       // The connection succeeded on the initial connection.
486       kSuccessInitial = 0,
487       // The connection failed on the initial connection, without providing
488       // retry configs.
489       kErrorInitial = 1,
490       // The connection succeeded after getting retry configs.
491       kSuccessRetry = 2,
492       // The connection failed after getting retry configs.
493       kErrorRetry = 3,
494       // The connection succeeded after getting a rollback signal.
495       kSuccessRollback = 4,
496       // The connection failed after getting a rollback signal.
497       kErrorRollback = 5,
498       kMaxValue = kErrorRollback,
499     };
500     const bool is_ok = result == OK;
501     ECHResult ech_result;
502     if (!ech_retry_configs_.has_value()) {
503       ech_result =
504           is_ok ? ECHResult::kSuccessInitial : ECHResult::kErrorInitial;
505     } else if (ech_retry_configs_->empty()) {
506       ech_result =
507           is_ok ? ECHResult::kSuccessRollback : ECHResult::kErrorRollback;
508     } else {
509       ech_result = is_ok ? ECHResult::kSuccessRetry : ECHResult::kErrorRetry;
510     }
511     base::UmaHistogramEnumeration("Net.SSL.ECHResult", ech_result);
512   }
513 
514   if (result == OK) {
515     DCHECK(!connect_timing_.ssl_start.is_null());
516     base::TimeDelta connect_duration =
517         connect_timing_.ssl_end - connect_timing_.ssl_start;
518     UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_2", connect_duration,
519                                base::Milliseconds(1), base::Minutes(1), 100);
520     if (is_ech_capable) {
521       UMA_HISTOGRAM_CUSTOM_TIMES("Net.SSL_Connection_Latency_ECH",
522                                  connect_duration, base::Milliseconds(1),
523                                  base::Minutes(1), 100);
524     }
525 
526     SSLInfo ssl_info;
527     bool has_ssl_info = ssl_socket_->GetSSLInfo(&ssl_info);
528     DCHECK(has_ssl_info);
529 
530     SSLVersion version =
531         SSLConnectionStatusToVersion(ssl_info.connection_status);
532     UMA_HISTOGRAM_ENUMERATION("Net.SSLVersion", version,
533                               SSL_CONNECTION_VERSION_MAX);
534     if (IsGoogleHost(host)) {
535       // Google hosts all support TLS 1.2, so any occurrences of TLS 1.0 or TLS
536       // 1.1 will be from an outdated insecure TLS MITM proxy, such as some
537       // antivirus configurations. TLS 1.0 and 1.1 are deprecated, so record
538       // these to see how prevalent they are. See https://crbug.com/896013.
539       UMA_HISTOGRAM_ENUMERATION("Net.SSLVersionGoogle", version,
540                                 SSL_CONNECTION_VERSION_MAX);
541     }
542 
543     uint16_t cipher_suite =
544         SSLConnectionStatusToCipherSuite(ssl_info.connection_status);
545     base::UmaHistogramSparse("Net.SSL_CipherSuite", cipher_suite);
546 
547     if (ssl_info.key_exchange_group != 0) {
548       base::UmaHistogramSparse("Net.SSL_KeyExchange.ECDHE",
549                                ssl_info.key_exchange_group);
550     }
551 
552     // Classify whether the connection required the legacy crypto fallback.
553     SSLLegacyCryptoFallback fallback = SSLLegacyCryptoFallback::kNoFallback;
554     if (!disable_legacy_crypto_with_fallback_) {
555       // Some servers, though they do not negotiate SHA-1, still fail the
556       // connection when SHA-1 is not offered. We believe these are servers
557       // which match the sent certificates against the ClientHello and then
558       // are configured with a SHA-1 certificate.
559       //
560       // SHA-1 certificate chains are no longer accepted, however servers may
561       // send extra unused certificates, most commonly a copy of the trust
562       // anchor. We only need to check for RSASSA-PKCS1-v1_5 signatures, because
563       // other SHA-1 signature types have already been removed from the
564       // ClientHello.
565       bool sent_sha1_cert = ssl_info.unverified_cert &&
566                             x509_util::HasRsaPkcs1Sha1Signature(
567                                 ssl_info.unverified_cert->cert_buffer());
568       if (!sent_sha1_cert && ssl_info.unverified_cert) {
569         for (const auto& cert :
570              ssl_info.unverified_cert->intermediate_buffers()) {
571           if (x509_util::HasRsaPkcs1Sha1Signature(cert.get())) {
572             sent_sha1_cert = true;
573             break;
574           }
575         }
576       }
577       if (ssl_info.peer_signature_algorithm == SSL_SIGN_RSA_PKCS1_SHA1) {
578         fallback = sent_sha1_cert
579                        ? SSLLegacyCryptoFallback::kSentSHA1CertAndUsedSHA1
580                        : SSLLegacyCryptoFallback::kUsedSHA1;
581       } else {
582         fallback = sent_sha1_cert ? SSLLegacyCryptoFallback::kSentSHA1Cert
583                                   : SSLLegacyCryptoFallback::kUnknownReason;
584       }
585     }
586     UMA_HISTOGRAM_ENUMERATION("Net.SSLLegacyCryptoFallback2", fallback);
587   }
588 
589   base::UmaHistogramSparse("Net.SSL_Connection_Error", std::abs(result));
590   if (is_ech_capable) {
591     base::UmaHistogramSparse("Net.SSL_Connection_Error_ECH", std::abs(result));
592   }
593 
594   if (result == OK || IsCertificateError(result)) {
595     SetSocket(std::move(ssl_socket_), std::move(dns_aliases_));
596   } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
597     ssl_cert_request_info_ = base::MakeRefCounted<SSLCertRequestInfo>();
598     ssl_socket_->GetSSLCertRequestInfo(ssl_cert_request_info_.get());
599   }
600 
601   return result;
602 }
603 
GetInitialState(SSLSocketParams::ConnectionType connection_type)604 SSLConnectJob::State SSLConnectJob::GetInitialState(
605     SSLSocketParams::ConnectionType connection_type) {
606   switch (connection_type) {
607     case SSLSocketParams::DIRECT:
608       return STATE_TRANSPORT_CONNECT;
609     case SSLSocketParams::HTTP_PROXY:
610       return STATE_TUNNEL_CONNECT;
611     case SSLSocketParams::SOCKS_PROXY:
612       return STATE_SOCKS_CONNECT;
613   }
614   NOTREACHED();
615   return STATE_NONE;
616 }
617 
ConnectInternal()618 int SSLConnectJob::ConnectInternal() {
619   next_state_ = GetInitialState(params_->GetConnectionType());
620   return DoLoop(OK);
621 }
622 
ResetStateForRestart()623 void SSLConnectJob::ResetStateForRestart() {
624   ResetTimer(base::TimeDelta());
625   nested_connect_job_ = nullptr;
626   nested_socket_ = nullptr;
627   ssl_socket_ = nullptr;
628   ssl_cert_request_info_ = nullptr;
629   ssl_negotiation_started_ = false;
630   resolve_error_info_ = ResolveErrorInfo();
631   server_address_ = IPEndPoint();
632 }
633 
ChangePriorityInternal(RequestPriority priority)634 void SSLConnectJob::ChangePriorityInternal(RequestPriority priority) {
635   if (nested_connect_job_)
636     nested_connect_job_->ChangePriority(priority);
637 }
638 
639 }  // namespace net
640