ssl_connect_job.cc 23 KB

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