blob: cb327a5139d3061afa71b6cf6b8e7d61b4c95c49 [file] [log] [blame]
Matt Menke7b5051072019-01-27 21:22:491// Copyright 2019 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
5#include "net/socket/ssl_connect_job.h"
6
7#include <memory>
8#include <string>
9
10#include "base/callback.h"
11#include "base/compiler_specific.h"
Matt Menke7b5051072019-01-27 21:22:4912#include "base/strings/string_util.h"
13#include "base/strings/utf_string_conversions.h"
David Benjamin07a07d652020-02-26 22:26:5914#include "base/test/metrics/histogram_tester.h"
15#include "base/test/scoped_feature_list.h"
Gabriel Charettec7108742019-08-23 03:31:4016#include "base/test/task_environment.h"
Matt Menke7b5051072019-01-27 21:22:4917#include "base/time/time.h"
18#include "net/base/auth.h"
David Benjamin07a07d652020-02-26 22:26:5919#include "net/base/features.h"
Matt Menke7b5051072019-01-27 21:22:4920#include "net/base/load_timing_info.h"
21#include "net/base/net_errors.h"
Matt Menkeae58eeb2019-05-24 21:09:5022#include "net/base/network_isolation_key.h"
Matt Menke7b5051072019-01-27 21:22:4923#include "net/cert/ct_policy_enforcer.h"
24#include "net/cert/mock_cert_verifier.h"
Matt Menke7b5051072019-01-27 21:22:4925#include "net/dns/mock_host_resolver.h"
Ben Schwartz3ff4dc1e62021-04-27 21:15:2326#include "net/dns/public/secure_dns_policy.h"
Matt Menke7b5051072019-01-27 21:22:4927#include "net/http/http_auth_handler_factory.h"
28#include "net/http/http_network_session.h"
Matt Menke0754b5d02019-02-10 21:46:4329#include "net/http/http_proxy_connect_job.h"
Matt Menke7b5051072019-01-27 21:22:4930#include "net/http/http_request_headers.h"
31#include "net/http/http_response_headers.h"
Matt Menke609160742019-08-02 18:47:2632#include "net/http/http_server_properties.h"
Matt Menke7b5051072019-01-27 21:22:4933#include "net/http/transport_security_state.h"
34#include "net/log/net_log_source.h"
35#include "net/log/net_log_with_source.h"
Nicolas Arciniegad2013f92020-02-07 23:00:5636#include "net/proxy_resolution/configured_proxy_resolution_service.h"
Victor Vasiliev7752898d2019-11-14 21:30:2237#include "net/quic/quic_context.h"
Matt Menke7b5051072019-01-27 21:22:4938#include "net/socket/connect_job_test_util.h"
Matt Menke6030ed9f2019-04-11 20:25:5539#include "net/socket/connection_attempts.h"
Matt Menke7b5051072019-01-27 21:22:4940#include "net/socket/next_proto.h"
41#include "net/socket/socket_tag.h"
42#include "net/socket/socket_test_util.h"
43#include "net/socket/socks_connect_job.h"
Matt Menke7b5051072019-01-27 21:22:4944#include "net/socket/transport_connect_job.h"
45#include "net/ssl/ssl_config_service_defaults.h"
David Benjamin07a07d652020-02-26 22:26:5946#include "net/ssl/ssl_connection_status_flags.h"
47#include "net/ssl/ssl_legacy_crypto_fallback.h"
48#include "net/test/cert_test_util.h"
Matt Menke7b5051072019-01-27 21:22:4949#include "net/test/gtest_util.h"
David Benjamindc5fd6a2022-03-24 23:00:4150#include "net/test/ssl_test_util.h"
Matt Menke7b5051072019-01-27 21:22:4951#include "net/test/test_certificate_data.h"
David Benjamin07a07d652020-02-26 22:26:5952#include "net/test/test_data_directory.h"
Gabriel Charettec7108742019-08-23 03:31:4053#include "net/test/test_with_task_environment.h"
Matt Menke7b5051072019-01-27 21:22:4954#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
55#include "testing/gtest/include/gtest/gtest.h"
David Benjamin07a07d652020-02-26 22:26:5956#include "third_party/boringssl/src/include/openssl/ssl.h"
Matt Menke8db2ff52021-11-23 20:17:4657#include "url/gurl.h"
Eric Orthc98a3e62021-07-02 17:46:3758#include "url/scheme_host_port.h"
59#include "url/url_constants.h"
Matt Menke7b5051072019-01-27 21:22:4960
61namespace net {
62namespace {
63
David Benjamindc5fd6a2022-03-24 23:00:4164IPAddress ParseIP(const std::string& ip) {
65 IPAddress address;
66 CHECK(address.AssignFromIPLiteral(ip));
67 return address;
68}
69
Matt Menke7b5051072019-01-27 21:22:4970// Just check that all connect times are set to base::TimeTicks::Now(), for
71// tests that don't update the mocked out time.
72void CheckConnectTimesSet(const LoadTimingInfo::ConnectTiming& connect_timing) {
73 EXPECT_EQ(base::TimeTicks::Now(), connect_timing.dns_start);
74 EXPECT_EQ(base::TimeTicks::Now(), connect_timing.dns_end);
75 EXPECT_EQ(base::TimeTicks::Now(), connect_timing.connect_start);
76 EXPECT_EQ(base::TimeTicks::Now(), connect_timing.ssl_start);
77 EXPECT_EQ(base::TimeTicks::Now(), connect_timing.ssl_end);
78 EXPECT_EQ(base::TimeTicks::Now(), connect_timing.connect_end);
79}
80
81// Just check that all connect times are set to base::TimeTicks::Now(), except
82// for DNS times, for tests that don't update the mocked out time and use a
83// proxy.
84void CheckConnectTimesExceptDnsSet(
85 const LoadTimingInfo::ConnectTiming& connect_timing) {
86 EXPECT_TRUE(connect_timing.dns_start.is_null());
87 EXPECT_TRUE(connect_timing.dns_end.is_null());
88 EXPECT_EQ(base::TimeTicks::Now(), connect_timing.connect_start);
89 EXPECT_EQ(base::TimeTicks::Now(), connect_timing.ssl_start);
90 EXPECT_EQ(base::TimeTicks::Now(), connect_timing.ssl_end);
91 EXPECT_EQ(base::TimeTicks::Now(), connect_timing.connect_end);
92}
93
Gabriel Charette694c3c332019-08-19 14:53:0594class SSLConnectJobTest : public WithTaskEnvironment, public testing::Test {
Matt Menke7b5051072019-01-27 21:22:4995 public:
96 SSLConnectJobTest()
Gabriel Charette694c3c332019-08-19 14:53:0597 : WithTaskEnvironment(base::test::TaskEnvironment::TimeSource::MOCK_TIME),
Nicolas Arciniegad2013f92020-02-07 23:00:5698 proxy_resolution_service_(
99 ConfiguredProxyResolutionService::CreateDirect()),
Tsuyoshi Horo2c0a5042022-07-06 05:53:07100 ssl_config_service_(std::make_unique<SSLConfigServiceDefaults>()),
Eric Orthbe2efac2019-03-06 01:11:11101 http_auth_handler_factory_(HttpAuthHandlerFactory::CreateDefault()),
Matt Menke7b5051072019-01-27 21:22:49102 session_(CreateNetworkSession()),
Tsuyoshi Horo2c0a5042022-07-06 05:53:07103 direct_transport_socket_params_(
104 base::MakeRefCounted<TransportSocketParams>(
105 url::SchemeHostPort(url::kHttpsScheme, "host", 443),
106 NetworkIsolationKey(),
107 SecureDnsPolicy::kAllow,
108 OnHostResolutionCallback(),
109 /*supported_alpns=*/
110 base::flat_set<std::string>({"h2", "http/1.1"}))),
Matt Menke7b5051072019-01-27 21:22:49111 proxy_transport_socket_params_(
Tsuyoshi Horo2c0a5042022-07-06 05:53:07112 base::MakeRefCounted<TransportSocketParams>(
113 HostPortPair("proxy", 443),
114 NetworkIsolationKey(),
115 SecureDnsPolicy::kAllow,
116 OnHostResolutionCallback(),
117 /*supported_alpns=*/base::flat_set<std::string>({}))),
118 socks_socket_params_(base::MakeRefCounted<SOCKSSocketParams>(
119 proxy_transport_socket_params_,
120 true,
121 HostPortPair("sockshost", 443),
122 NetworkIsolationKey(),
123 TRAFFIC_ANNOTATION_FOR_TESTS)),
124 http_proxy_socket_params_(base::MakeRefCounted<HttpProxySocketParams>(
125 proxy_transport_socket_params_,
126 nullptr /* ssl_params */,
127 false /* is_quic */,
128 HostPortPair("host", 80),
129 /*tunnel=*/true,
130 TRAFFIC_ANNOTATION_FOR_TESTS,
131 NetworkIsolationKey())),
Gabriel Charette694c3c332019-08-19 14:53:05132 common_connect_job_params_(session_->CreateCommonConnectJobParams()) {}
Matt Menke7b5051072019-01-27 21:22:49133
134 ~SSLConnectJobTest() override = default;
135
136 std::unique_ptr<ConnectJob> CreateConnectJob(
137 TestConnectJobDelegate* test_delegate,
138 ProxyServer::Scheme proxy_scheme = ProxyServer::SCHEME_DIRECT,
139 RequestPriority priority = DEFAULT_PRIORITY) {
140 return std::make_unique<SSLConnectJob>(
Matt Menkea6f99ad2019-03-08 02:26:43141 priority, SocketTag(), &common_connect_job_params_,
Matt Menke14819512019-03-02 16:59:58142 SSLParams(proxy_scheme), test_delegate, nullptr /* net_log */);
Matt Menke7b5051072019-01-27 21:22:49143 }
144
145 scoped_refptr<SSLSocketParams> SSLParams(ProxyServer::Scheme proxy) {
146 return base::MakeRefCounted<SSLSocketParams>(
147 proxy == ProxyServer::SCHEME_DIRECT ? direct_transport_socket_params_
148 : nullptr,
149 proxy == ProxyServer::SCHEME_SOCKS5 ? socks_socket_params_ : nullptr,
150 proxy == ProxyServer::SCHEME_HTTP ? http_proxy_socket_params_ : nullptr,
David Benjamin151ec6b2019-08-02 19:38:52151 HostPortPair("host", 443), SSLConfig(), PRIVACY_MODE_DISABLED,
David Benjamin6f2da652019-06-26 23:36:35152 NetworkIsolationKey());
Matt Menke7b5051072019-01-27 21:22:49153 }
154
155 void AddAuthToCache() {
Jan Wilken Dörriec92a6d7242021-03-23 17:43:48156 const std::u16string kFoo(u"foo");
157 const std::u16string kBar(u"bar");
Matt Menke7b5051072019-01-27 21:22:49158 session_->http_auth_cache()->Add(
Matt Menke8db2ff52021-11-23 20:17:46159 url::SchemeHostPort(GURL("http://proxy:443/")), HttpAuth::AUTH_PROXY,
160 "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC, NetworkIsolationKey(),
Matt Menkebe090422019-10-18 20:25:26161 "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");
Matt Menke7b5051072019-01-27 21:22:49162 }
163
Tsuyoshi Horoc921c502022-07-06 05:31:54164 std::unique_ptr<HttpNetworkSession> CreateNetworkSession() {
Matt Menke30a878c2021-07-20 22:25:09165 HttpNetworkSessionContext session_context;
Matt Menke7b5051072019-01-27 21:22:49166 session_context.host_resolver = &host_resolver_;
167 session_context.cert_verifier = &cert_verifier_;
168 session_context.transport_security_state = &transport_security_state_;
Matt Menke7b5051072019-01-27 21:22:49169 session_context.ct_policy_enforcer = &ct_policy_enforcer_;
170 session_context.proxy_resolution_service = proxy_resolution_service_.get();
171 session_context.client_socket_factory = &socket_factory_;
172 session_context.ssl_config_service = ssl_config_service_.get();
173 session_context.http_auth_handler_factory =
174 http_auth_handler_factory_.get();
175 session_context.http_server_properties = &http_server_properties_;
Victor Vasiliev7752898d2019-11-14 21:30:22176 session_context.quic_context = &quic_context_;
Tsuyoshi Horoc921c502022-07-06 05:31:54177 return std::make_unique<HttpNetworkSession>(HttpNetworkSessionParams(),
178 session_context);
Matt Menke7b5051072019-01-27 21:22:49179 }
180
181 protected:
182 MockClientSocketFactory socket_factory_;
Eric Orthbe86fee2021-10-28 22:31:11183 MockHostResolver host_resolver_{/*default_result=*/MockHostResolverBase::
184 RuleResolver::GetLocalhostResult()};
Matt Menke7b5051072019-01-27 21:22:49185 MockCertVerifier cert_verifier_;
186 TransportSecurityState transport_security_state_;
Matt Menke7b5051072019-01-27 21:22:49187 DefaultCTPolicyEnforcer ct_policy_enforcer_;
Nicolas Arciniega8ec5bfa2020-03-20 05:07:26188 const std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
Matt Menke7b5051072019-01-27 21:22:49189 const std::unique_ptr<SSLConfigService> ssl_config_service_;
190 const std::unique_ptr<HttpAuthHandlerFactory> http_auth_handler_factory_;
Matt Menke609160742019-08-02 18:47:26191 HttpServerProperties http_server_properties_;
Victor Vasiliev7752898d2019-11-14 21:30:22192 QuicContext quic_context_;
Matt Menke7b5051072019-01-27 21:22:49193 const std::unique_ptr<HttpNetworkSession> session_;
Matt Menke7b5051072019-01-27 21:22:49194
195 scoped_refptr<TransportSocketParams> direct_transport_socket_params_;
Matt Menke7b5051072019-01-27 21:22:49196
197 scoped_refptr<TransportSocketParams> proxy_transport_socket_params_;
198 scoped_refptr<SOCKSSocketParams> socks_socket_params_;
199 scoped_refptr<HttpProxySocketParams> http_proxy_socket_params_;
200
Matt Menkea6f99ad2019-03-08 02:26:43201 const CommonConnectJobParams common_connect_job_params_;
Matt Menke7b5051072019-01-27 21:22:49202};
203
204TEST_F(SSLConnectJobTest, TCPFail) {
205 for (IoMode io_mode : {SYNCHRONOUS, ASYNC}) {
206 SCOPED_TRACE(io_mode);
207 host_resolver_.set_synchronous_mode(io_mode == SYNCHRONOUS);
208 StaticSocketDataProvider data;
209 data.set_connect_data(MockConnect(io_mode, ERR_CONNECTION_FAILED));
210 socket_factory_.AddSocketDataProvider(&data);
211
212 TestConnectJobDelegate test_delegate;
213 std::unique_ptr<ConnectJob> ssl_connect_job =
214 CreateConnectJob(&test_delegate);
215 test_delegate.StartJobExpectingResult(
216 ssl_connect_job.get(), ERR_CONNECTION_FAILED, io_mode == SYNCHRONOUS);
217 EXPECT_FALSE(test_delegate.socket());
Matt Menke6f84d1f12019-04-11 19:26:47218 EXPECT_FALSE(ssl_connect_job->IsSSLError());
Matt Menke6030ed9f2019-04-11 20:25:55219 ConnectionAttempts connection_attempts =
220 ssl_connect_job->GetConnectionAttempts();
221 ASSERT_EQ(1u, connection_attempts.size());
222 EXPECT_THAT(connection_attempts[0].result,
Matt Menke7b5051072019-01-27 21:22:49223 test::IsError(ERR_CONNECTION_FAILED));
224 }
225}
226
Matt Menke36eaf5c2019-04-02 16:15:52227TEST_F(SSLConnectJobTest, TCPTimeout) {
Peter Kastinge5a38ed2021-10-02 03:06:35228 const base::TimeDelta kTinyTime = base::Microseconds(1);
Matt Menke36eaf5c2019-04-02 16:15:52229
230 // Make request hang.
231 host_resolver_.set_ondemand_mode(true);
232
233 TestConnectJobDelegate test_delegate;
234 std::unique_ptr<ConnectJob> ssl_connect_job =
235 CreateConnectJob(&test_delegate);
236 ASSERT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
237
238 // Right up until just before the TCP connection timeout, the job does not
239 // time out.
240 FastForwardBy(TransportConnectJob::ConnectionTimeout() - kTinyTime);
241 EXPECT_FALSE(test_delegate.has_result());
242
243 // But at the exact time of TCP connection timeout, the job fails.
244 FastForwardBy(kTinyTime);
245 EXPECT_TRUE(test_delegate.has_result());
246 EXPECT_THAT(test_delegate.WaitForResult(), test::IsError(ERR_TIMED_OUT));
247}
248
249TEST_F(SSLConnectJobTest, SSLTimeoutSyncConnect) {
Peter Kastinge5a38ed2021-10-02 03:06:35250 const base::TimeDelta kTinyTime = base::Microseconds(1);
Matt Menke36eaf5c2019-04-02 16:15:52251
252 // DNS lookup and transport connect complete synchronously, but SSL
253 // negotiation hangs.
254 host_resolver_.set_synchronous_mode(true);
255 StaticSocketDataProvider data;
256 data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
257 socket_factory_.AddSocketDataProvider(&data);
258 SSLSocketDataProvider ssl(SYNCHRONOUS, ERR_IO_PENDING);
259 socket_factory_.AddSSLSocketDataProvider(&ssl);
260
261 // Make request hang.
262 TestConnectJobDelegate test_delegate;
263 std::unique_ptr<ConnectJob> ssl_connect_job =
264 CreateConnectJob(&test_delegate);
265 ASSERT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
266
267 // Right up until just before the SSL handshake timeout, the job does not time
268 // out.
269 FastForwardBy(SSLConnectJob::HandshakeTimeoutForTesting() - kTinyTime);
270 EXPECT_FALSE(test_delegate.has_result());
271
272 // But at the exact SSL handshake timeout time, the job fails.
273 FastForwardBy(kTinyTime);
274 EXPECT_TRUE(test_delegate.has_result());
275 EXPECT_THAT(test_delegate.WaitForResult(), test::IsError(ERR_TIMED_OUT));
276}
277
278TEST_F(SSLConnectJobTest, SSLTimeoutAsyncTcpConnect) {
Peter Kastinge5a38ed2021-10-02 03:06:35279 const base::TimeDelta kTinyTime = base::Microseconds(1);
Matt Menke36eaf5c2019-04-02 16:15:52280
281 // DNS lookup is asynchronous, and later SSL negotiation hangs.
282 host_resolver_.set_ondemand_mode(true);
283 StaticSocketDataProvider data;
284 data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
285 socket_factory_.AddSocketDataProvider(&data);
286 SSLSocketDataProvider ssl(SYNCHRONOUS, ERR_IO_PENDING);
287 socket_factory_.AddSSLSocketDataProvider(&ssl);
288
289 TestConnectJobDelegate test_delegate;
290 std::unique_ptr<ConnectJob> ssl_connect_job =
291 CreateConnectJob(&test_delegate);
292 // Connecting should hand on the TransportConnectJob connect.
293 ASSERT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
294
295 // Right up until just before the TCP connection timeout, the job does not
296 // time out.
297 FastForwardBy(TransportConnectJob::ConnectionTimeout() - kTinyTime);
298 EXPECT_FALSE(test_delegate.has_result());
299
300 // The DNS lookup completes, and a TCP connection is immediately establshed,
301 // which cancels the TCP connection timer. The SSL handshake timer is started,
302 // and the SSL handshake hangs.
303 host_resolver_.ResolveOnlyRequestNow();
304 EXPECT_FALSE(test_delegate.has_result());
305
306 // Right up until just before the SSL handshake timeout, the job does not time
307 // out.
308 FastForwardBy(SSLConnectJob::HandshakeTimeoutForTesting() - kTinyTime);
309 EXPECT_FALSE(test_delegate.has_result());
310
311 // But at the exact SSL handshake timeout time, the job fails.
312 FastForwardBy(kTinyTime);
313 EXPECT_TRUE(test_delegate.has_result());
314 EXPECT_THAT(test_delegate.WaitForResult(), test::IsError(ERR_TIMED_OUT));
315}
316
Matt Menke7b5051072019-01-27 21:22:49317TEST_F(SSLConnectJobTest, BasicDirectSync) {
318 host_resolver_.set_synchronous_mode(true);
319 StaticSocketDataProvider data;
320 data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
321 socket_factory_.AddSocketDataProvider(&data);
322 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
323 socket_factory_.AddSSLSocketDataProvider(&ssl);
324
325 TestConnectJobDelegate test_delegate;
326 std::unique_ptr<ConnectJob> ssl_connect_job =
327 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_DIRECT, MEDIUM);
328
329 test_delegate.StartJobExpectingResult(ssl_connect_job.get(), OK,
330 true /* expect_sync_result */);
331 EXPECT_EQ(MEDIUM, host_resolver_.last_request_priority());
332
Matt Menke6030ed9f2019-04-11 20:25:55333 ConnectionAttempts connection_attempts =
334 ssl_connect_job->GetConnectionAttempts();
335 EXPECT_EQ(0u, connection_attempts.size());
Matt Menke7b5051072019-01-27 21:22:49336 CheckConnectTimesSet(ssl_connect_job->connect_timing());
337}
338
339TEST_F(SSLConnectJobTest, BasicDirectAsync) {
340 host_resolver_.set_ondemand_mode(true);
341 base::TimeTicks start_time = base::TimeTicks::Now();
342 StaticSocketDataProvider data;
343 data.set_connect_data(MockConnect(ASYNC, OK));
344 socket_factory_.AddSocketDataProvider(&data);
345 SSLSocketDataProvider ssl(ASYNC, OK);
346 socket_factory_.AddSSLSocketDataProvider(&ssl);
347
348 TestConnectJobDelegate test_delegate;
349 std::unique_ptr<ConnectJob> ssl_connect_job =
350 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_DIRECT, MEDIUM);
351 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
352 EXPECT_TRUE(host_resolver_.has_pending_requests());
353 EXPECT_EQ(MEDIUM, host_resolver_.last_request_priority());
Peter Kastinge5a38ed2021-10-02 03:06:35354 FastForwardBy(base::Seconds(5));
Matt Menke7b5051072019-01-27 21:22:49355
356 base::TimeTicks resolve_complete_time = base::TimeTicks::Now();
357 host_resolver_.ResolveAllPending();
358 EXPECT_THAT(test_delegate.WaitForResult(), test::IsOk());
359
Matt Menke6030ed9f2019-04-11 20:25:55360 ConnectionAttempts connection_attempts =
361 ssl_connect_job->GetConnectionAttempts();
362 EXPECT_EQ(0u, connection_attempts.size());
Matt Menke7b5051072019-01-27 21:22:49363
364 // Check times. Since time is mocked out, all times will be the same, except
365 // |dns_start|, which is the only one recorded before the FastForwardBy()
366 // call. The test classes don't allow any other phases to be triggered on
367 // demand, or delayed by a set interval.
368 EXPECT_EQ(start_time, ssl_connect_job->connect_timing().dns_start);
369 EXPECT_EQ(resolve_complete_time, ssl_connect_job->connect_timing().dns_end);
370 EXPECT_EQ(resolve_complete_time,
371 ssl_connect_job->connect_timing().connect_start);
372 EXPECT_EQ(resolve_complete_time, ssl_connect_job->connect_timing().ssl_start);
373 EXPECT_EQ(resolve_complete_time, ssl_connect_job->connect_timing().ssl_end);
374 EXPECT_EQ(resolve_complete_time,
375 ssl_connect_job->connect_timing().connect_end);
376}
377
Matt Menke9d5e2c92019-02-05 01:42:23378TEST_F(SSLConnectJobTest, DirectHasEstablishedConnection) {
379 host_resolver_.set_ondemand_mode(true);
380 StaticSocketDataProvider data;
381 data.set_connect_data(MockConnect(ASYNC, OK));
382 socket_factory_.AddSocketDataProvider(&data);
383
384 // SSL negotiation hangs. Value returned after SSL negotiation is complete
385 // doesn't matter, as HasEstablishedConnection() may only be used between job
386 // start and job complete.
387 SSLSocketDataProvider ssl(SYNCHRONOUS, ERR_IO_PENDING);
388 socket_factory_.AddSSLSocketDataProvider(&ssl);
389
390 TestConnectJobDelegate test_delegate;
391 std::unique_ptr<ConnectJob> ssl_connect_job =
392 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_DIRECT, MEDIUM);
393 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
394 EXPECT_TRUE(host_resolver_.has_pending_requests());
395 EXPECT_EQ(LOAD_STATE_RESOLVING_HOST, ssl_connect_job->GetLoadState());
396 EXPECT_FALSE(ssl_connect_job->HasEstablishedConnection());
397
398 // DNS resolution completes, and then the ConnectJob tries to connect the
399 // socket, which should succeed asynchronously.
400 host_resolver_.ResolveNow(1);
401 EXPECT_EQ(LOAD_STATE_CONNECTING, ssl_connect_job->GetLoadState());
402 EXPECT_FALSE(ssl_connect_job->HasEstablishedConnection());
403
404 // Spinning the message loop causes the socket to finish connecting. The SSL
405 // handshake should start and hang.
406 base::RunLoop().RunUntilIdle();
407 EXPECT_FALSE(test_delegate.has_result());
408 EXPECT_EQ(LOAD_STATE_SSL_HANDSHAKE, ssl_connect_job->GetLoadState());
409 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
410}
411
Matt Menke7b5051072019-01-27 21:22:49412TEST_F(SSLConnectJobTest, RequestPriority) {
413 host_resolver_.set_ondemand_mode(true);
Matt Menke7b5051072019-01-27 21:22:49414 for (int initial_priority = MINIMUM_PRIORITY;
415 initial_priority <= MAXIMUM_PRIORITY; ++initial_priority) {
416 SCOPED_TRACE(initial_priority);
417 for (int new_priority = MINIMUM_PRIORITY; new_priority <= MAXIMUM_PRIORITY;
418 ++new_priority) {
419 SCOPED_TRACE(new_priority);
420 if (initial_priority == new_priority)
421 continue;
422 TestConnectJobDelegate test_delegate;
423 std::unique_ptr<ConnectJob> ssl_connect_job =
424 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_DIRECT,
425 static_cast<RequestPriority>(initial_priority));
426 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
427 EXPECT_TRUE(host_resolver_.has_pending_requests());
428 int request_id = host_resolver_.num_resolve();
429 EXPECT_EQ(initial_priority, host_resolver_.request_priority(request_id));
430
431 ssl_connect_job->ChangePriority(
432 static_cast<RequestPriority>(new_priority));
433 EXPECT_EQ(new_priority, host_resolver_.request_priority(request_id));
434
435 ssl_connect_job->ChangePriority(
436 static_cast<RequestPriority>(initial_priority));
437 EXPECT_EQ(initial_priority, host_resolver_.request_priority(request_id));
Matt Menke7b5051072019-01-27 21:22:49438 }
439 }
440}
441
Ben Schwartz3ff4dc1e62021-04-27 21:15:23442TEST_F(SSLConnectJobTest, SecureDnsPolicy) {
443 for (auto secure_dns_policy :
444 {SecureDnsPolicy::kAllow, SecureDnsPolicy::kDisable}) {
dalyk5f48a132019-10-14 15:20:19445 TestConnectJobDelegate test_delegate;
446 direct_transport_socket_params_ =
Matt Menkecd439232019-11-05 15:15:33447 base::MakeRefCounted<TransportSocketParams>(
Eric Orthc98a3e62021-07-02 17:46:37448 url::SchemeHostPort(url::kHttpsScheme, "host", 443),
449 NetworkIsolationKey(), secure_dns_policy,
David Benjamin13072a42022-02-10 22:23:21450 OnHostResolutionCallback(),
451 /*supported_alpns=*/base::flat_set<std::string>{"h2", "http/1.1"});
dalyk5f48a132019-10-14 15:20:19452 auto common_connect_job_params = session_->CreateCommonConnectJobParams();
453 std::unique_ptr<ConnectJob> ssl_connect_job =
454 std::make_unique<SSLConnectJob>(DEFAULT_PRIORITY, SocketTag(),
455 &common_connect_job_params,
456 SSLParams(ProxyServer::SCHEME_DIRECT),
457 &test_delegate, nullptr /* net_log */);
458
459 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
Ben Schwartz432ce032021-05-05 21:49:24460 EXPECT_EQ(secure_dns_policy, host_resolver_.last_secure_dns_policy());
dalyk5f48a132019-10-14 15:20:19461 }
462}
463
dalykedd30d982019-12-16 15:31:10464TEST_F(SSLConnectJobTest, DirectHostResolutionFailure) {
465 host_resolver_.rules()->AddSimulatedTimeoutFailure("host");
466
467 TestConnectJobDelegate test_delegate;
468 std::unique_ptr<ConnectJob> ssl_connect_job =
469 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_DIRECT);
470 test_delegate.StartJobExpectingResult(ssl_connect_job.get(),
471 ERR_NAME_NOT_RESOLVED,
472 false /* expect_sync_result */);
473 EXPECT_THAT(ssl_connect_job->GetResolveErrorInfo().error,
474 test::IsError(ERR_DNS_TIMED_OUT));
475}
476
Matt Menke7b5051072019-01-27 21:22:49477TEST_F(SSLConnectJobTest, DirectCertError) {
478 StaticSocketDataProvider data;
479 socket_factory_.AddSocketDataProvider(&data);
480 SSLSocketDataProvider ssl(ASYNC, ERR_CERT_COMMON_NAME_INVALID);
481 socket_factory_.AddSSLSocketDataProvider(&ssl);
482
483 TestConnectJobDelegate test_delegate(
484 TestConnectJobDelegate::SocketExpected::ALWAYS);
485 std::unique_ptr<ConnectJob> ssl_connect_job =
486 CreateConnectJob(&test_delegate);
487
488 test_delegate.StartJobExpectingResult(ssl_connect_job.get(),
489 ERR_CERT_COMMON_NAME_INVALID,
490 false /* expect_sync_result */);
Matt Menke6f84d1f12019-04-11 19:26:47491 EXPECT_TRUE(ssl_connect_job->IsSSLError());
Matt Menke6030ed9f2019-04-11 20:25:55492 ConnectionAttempts connection_attempts =
493 ssl_connect_job->GetConnectionAttempts();
494 ASSERT_EQ(1u, connection_attempts.size());
495 EXPECT_THAT(connection_attempts[0].result,
Matt Menke7b5051072019-01-27 21:22:49496 test::IsError(ERR_CERT_COMMON_NAME_INVALID));
497 CheckConnectTimesSet(ssl_connect_job->connect_timing());
498}
499
500TEST_F(SSLConnectJobTest, DirectSSLError) {
501 StaticSocketDataProvider data;
502 socket_factory_.AddSocketDataProvider(&data);
David Benjamin07a07d652020-02-26 22:26:59503 SSLSocketDataProvider ssl(ASYNC, ERR_BAD_SSL_CLIENT_AUTH_CERT);
Matt Menke7b5051072019-01-27 21:22:49504 socket_factory_.AddSSLSocketDataProvider(&ssl);
505
506 TestConnectJobDelegate test_delegate;
507 std::unique_ptr<ConnectJob> ssl_connect_job =
508 CreateConnectJob(&test_delegate);
509
510 test_delegate.StartJobExpectingResult(ssl_connect_job.get(),
David Benjamin07a07d652020-02-26 22:26:59511 ERR_BAD_SSL_CLIENT_AUTH_CERT,
Matt Menke7b5051072019-01-27 21:22:49512 false /* expect_sync_result */);
Matt Menke6030ed9f2019-04-11 20:25:55513 ConnectionAttempts connection_attempts =
514 ssl_connect_job->GetConnectionAttempts();
515 ASSERT_EQ(1u, connection_attempts.size());
516 EXPECT_THAT(connection_attempts[0].result,
David Benjamin07a07d652020-02-26 22:26:59517 test::IsError(ERR_BAD_SSL_CLIENT_AUTH_CERT));
518}
519
520// Test that the legacy crypto fallback is triggered on applicable error codes.
521TEST_F(SSLConnectJobTest, DirectLegacyCryptoFallback) {
522 for (Error error :
523 {ERR_CONNECTION_CLOSED, ERR_CONNECTION_RESET, ERR_SSL_PROTOCOL_ERROR,
524 ERR_SSL_VERSION_OR_CIPHER_MISMATCH}) {
525 SCOPED_TRACE(error);
526
527 for (bool second_attempt_ok : {true, false}) {
528 SCOPED_TRACE(second_attempt_ok);
529
530 StaticSocketDataProvider data;
531 socket_factory_.AddSocketDataProvider(&data);
532 SSLSocketDataProvider ssl(ASYNC, error);
533 socket_factory_.AddSSLSocketDataProvider(&ssl);
534 ssl.expected_disable_legacy_crypto = true;
535
536 Error error2 = second_attempt_ok ? OK : error;
537 StaticSocketDataProvider data2;
538 socket_factory_.AddSocketDataProvider(&data2);
539 SSLSocketDataProvider ssl2(ASYNC, error2);
540 socket_factory_.AddSSLSocketDataProvider(&ssl2);
541 ssl2.expected_disable_legacy_crypto = false;
542
543 TestConnectJobDelegate test_delegate;
544 std::unique_ptr<ConnectJob> ssl_connect_job =
545 CreateConnectJob(&test_delegate);
546
547 test_delegate.StartJobExpectingResult(ssl_connect_job.get(), error2,
548 /*expect_sync_result=*/false);
549 ConnectionAttempts connection_attempts =
550 ssl_connect_job->GetConnectionAttempts();
551 if (second_attempt_ok) {
552 ASSERT_EQ(1u, connection_attempts.size());
553 EXPECT_THAT(connection_attempts[0].result, test::IsError(error));
554 } else {
555 ASSERT_EQ(2u, connection_attempts.size());
556 EXPECT_THAT(connection_attempts[0].result, test::IsError(error));
557 EXPECT_THAT(connection_attempts[1].result, test::IsError(error));
558 }
559 }
560 }
561}
562
David Benjamin07a07d652020-02-26 22:26:59563TEST_F(SSLConnectJobTest, LegacyCryptoFallbackHistograms) {
564 base::FilePath certs_dir = GetTestCertsDirectory();
565
566 scoped_refptr<X509Certificate> sha1_leaf =
567 ImportCertFromFile(certs_dir, "sha1_leaf.pem");
568 ASSERT_TRUE(sha1_leaf);
569
570 scoped_refptr<X509Certificate> ok_cert =
571 ImportCertFromFile(certs_dir, "ok_cert.pem");
572 ASSERT_TRUE(ok_cert);
573
574 // Make a copy of |ok_cert| with an unused |sha1_leaf| in the intermediate
575 // list.
576 std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> intermediates;
577 for (const auto& cert : ok_cert->intermediate_buffers()) {
578 intermediates.push_back(bssl::UpRef(cert));
579 }
580 intermediates.push_back(bssl::UpRef(sha1_leaf->cert_buffer()));
581 scoped_refptr<X509Certificate> ok_with_unused_sha1 =
582 X509Certificate::CreateFromBuffer(bssl::UpRef(ok_cert->cert_buffer()),
583 std::move(intermediates));
584 ASSERT_TRUE(ok_with_unused_sha1);
585
586 // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
587 const uint16_t kModernCipher = 0xc02f;
David Benjamin07a07d652020-02-26 22:26:59588
589 struct HistogramTest {
590 SSLLegacyCryptoFallback expected;
591 Error first_attempt;
592 uint16_t cipher_suite;
593 uint16_t peer_signature_algorithm;
594 scoped_refptr<X509Certificate> unverified_cert;
595 };
596
597 const HistogramTest kHistogramTests[] = {
598 // Connections not using the fallback map to kNoFallback.
599 {SSLLegacyCryptoFallback::kNoFallback, OK, kModernCipher,
600 SSL_SIGN_RSA_PSS_RSAE_SHA256, ok_cert},
601 {SSLLegacyCryptoFallback::kNoFallback, OK, kModernCipher,
602 SSL_SIGN_RSA_PSS_RSAE_SHA256, sha1_leaf},
603 {SSLLegacyCryptoFallback::kNoFallback, OK, kModernCipher,
604 SSL_SIGN_RSA_PSS_RSAE_SHA256, ok_with_unused_sha1},
605
David Benjamin07a07d652020-02-26 22:26:59606 // Connections using SHA-1 map to kUsedSHA1 or kSentSHA1CertAndUsedSHA1.
607 {SSLLegacyCryptoFallback::kUsedSHA1, ERR_SSL_PROTOCOL_ERROR,
608 kModernCipher, SSL_SIGN_RSA_PKCS1_SHA1, ok_cert},
609 {SSLLegacyCryptoFallback::kSentSHA1CertAndUsedSHA1,
610 ERR_SSL_PROTOCOL_ERROR, kModernCipher, SSL_SIGN_RSA_PKCS1_SHA1,
611 sha1_leaf},
612 {SSLLegacyCryptoFallback::kSentSHA1CertAndUsedSHA1,
613 ERR_SSL_PROTOCOL_ERROR, kModernCipher, SSL_SIGN_RSA_PKCS1_SHA1,
614 ok_with_unused_sha1},
615
616 // Connections using neither map to kUnknownReason or kSentSHA1Cert.
617 {SSLLegacyCryptoFallback::kUnknownReason, ERR_SSL_PROTOCOL_ERROR,
618 kModernCipher, SSL_SIGN_RSA_PSS_RSAE_SHA256, ok_cert},
619 {SSLLegacyCryptoFallback::kSentSHA1Cert, ERR_SSL_PROTOCOL_ERROR,
620 kModernCipher, SSL_SIGN_RSA_PSS_RSAE_SHA256, sha1_leaf},
621 {SSLLegacyCryptoFallback::kSentSHA1Cert, ERR_SSL_PROTOCOL_ERROR,
622 kModernCipher, SSL_SIGN_RSA_PSS_RSAE_SHA256, ok_with_unused_sha1},
623 };
Daniel Cheng5feb16f2022-02-28 06:52:07624 for (size_t i = 0; i < std::size(kHistogramTests); i++) {
David Benjamin07a07d652020-02-26 22:26:59625 SCOPED_TRACE(i);
626 const auto& test = kHistogramTests[i];
627
628 base::HistogramTester tester;
629
630 SSLInfo ssl_info;
631 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_TLS1_2,
632 &ssl_info.connection_status);
633 SSLConnectionStatusSetCipherSuite(test.cipher_suite,
634 &ssl_info.connection_status);
635 ssl_info.peer_signature_algorithm = test.peer_signature_algorithm;
636 ssl_info.unverified_cert = test.unverified_cert;
637
638 StaticSocketDataProvider data;
639 socket_factory_.AddSocketDataProvider(&data);
640 SSLSocketDataProvider ssl(ASYNC, test.first_attempt);
641 socket_factory_.AddSSLSocketDataProvider(&ssl);
642 ssl.expected_disable_legacy_crypto = true;
643
644 StaticSocketDataProvider data2;
645 SSLSocketDataProvider ssl2(ASYNC, OK);
646 if (test.first_attempt != OK) {
647 socket_factory_.AddSocketDataProvider(&data2);
648 socket_factory_.AddSSLSocketDataProvider(&ssl2);
649 ssl2.ssl_info = ssl_info;
650 ssl2.expected_disable_legacy_crypto = false;
651 } else {
652 ssl.ssl_info = ssl_info;
653 }
654
655 TestConnectJobDelegate test_delegate;
656 std::unique_ptr<ConnectJob> ssl_connect_job =
657 CreateConnectJob(&test_delegate);
658
659 test_delegate.StartJobExpectingResult(ssl_connect_job.get(), OK,
660 /*expect_sync_result=*/false);
661
David Benjaminb803d302022-07-26 18:35:09662 tester.ExpectUniqueSample("Net.SSLLegacyCryptoFallback2", test.expected, 1);
David Benjamin07a07d652020-02-26 22:26:59663 }
Matt Menke7b5051072019-01-27 21:22:49664}
665
666TEST_F(SSLConnectJobTest, DirectWithNPN) {
667 StaticSocketDataProvider data;
668 socket_factory_.AddSocketDataProvider(&data);
669 SSLSocketDataProvider ssl(ASYNC, OK);
670 ssl.next_proto = kProtoHTTP11;
671 socket_factory_.AddSSLSocketDataProvider(&ssl);
672
673 TestConnectJobDelegate test_delegate;
674 std::unique_ptr<ConnectJob> ssl_connect_job =
675 CreateConnectJob(&test_delegate);
676
677 test_delegate.StartJobExpectingResult(ssl_connect_job.get(), OK,
678 false /* expect_sync_result */);
679 EXPECT_TRUE(test_delegate.socket()->WasAlpnNegotiated());
680 CheckConnectTimesSet(ssl_connect_job->connect_timing());
681}
682
683TEST_F(SSLConnectJobTest, DirectGotHTTP2) {
684 StaticSocketDataProvider data;
685 socket_factory_.AddSocketDataProvider(&data);
686 SSLSocketDataProvider ssl(ASYNC, OK);
687 ssl.next_proto = kProtoHTTP2;
688 socket_factory_.AddSSLSocketDataProvider(&ssl);
689
690 TestConnectJobDelegate test_delegate;
691 std::unique_ptr<ConnectJob> ssl_connect_job =
692 CreateConnectJob(&test_delegate);
693
694 test_delegate.StartJobExpectingResult(ssl_connect_job.get(), OK,
695 false /* expect_sync_result */);
696 EXPECT_TRUE(test_delegate.socket()->WasAlpnNegotiated());
697 EXPECT_EQ(kProtoHTTP2, test_delegate.socket()->GetNegotiatedProtocol());
698 CheckConnectTimesSet(ssl_connect_job->connect_timing());
699}
700
701TEST_F(SSLConnectJobTest, SOCKSFail) {
702 for (IoMode io_mode : {SYNCHRONOUS, ASYNC}) {
703 SCOPED_TRACE(io_mode);
704 host_resolver_.set_synchronous_mode(io_mode == SYNCHRONOUS);
705 StaticSocketDataProvider data;
706 data.set_connect_data(MockConnect(io_mode, ERR_CONNECTION_FAILED));
707 socket_factory_.AddSocketDataProvider(&data);
708
709 TestConnectJobDelegate test_delegate;
710 std::unique_ptr<ConnectJob> ssl_connect_job =
711 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_SOCKS5);
712 test_delegate.StartJobExpectingResult(ssl_connect_job.get(),
713 ERR_PROXY_CONNECTION_FAILED,
714 io_mode == SYNCHRONOUS);
Matt Menke6f84d1f12019-04-11 19:26:47715 EXPECT_FALSE(ssl_connect_job->IsSSLError());
Matt Menke7b5051072019-01-27 21:22:49716
Matt Menke6030ed9f2019-04-11 20:25:55717 ConnectionAttempts connection_attempts =
718 ssl_connect_job->GetConnectionAttempts();
719 EXPECT_EQ(0u, connection_attempts.size());
Matt Menke7b5051072019-01-27 21:22:49720 }
721}
722
dalykedd30d982019-12-16 15:31:10723TEST_F(SSLConnectJobTest, SOCKSHostResolutionFailure) {
724 host_resolver_.rules()->AddSimulatedTimeoutFailure("proxy");
725
726 TestConnectJobDelegate test_delegate;
727 std::unique_ptr<ConnectJob> ssl_connect_job =
728 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_SOCKS5);
729 test_delegate.StartJobExpectingResult(ssl_connect_job.get(),
730 ERR_PROXY_CONNECTION_FAILED,
731 false /* expect_sync_result */);
732 EXPECT_THAT(ssl_connect_job->GetResolveErrorInfo().error,
733 test::IsError(ERR_DNS_TIMED_OUT));
734}
735
Matt Menke7b5051072019-01-27 21:22:49736TEST_F(SSLConnectJobTest, SOCKSBasic) {
737 for (IoMode io_mode : {SYNCHRONOUS, ASYNC}) {
738 SCOPED_TRACE(io_mode);
Peter Kasting0ff39d42021-06-14 13:26:06739 const uint8_t kSOCKS5Request[] = {0x05, 0x01, 0x00, 0x03, 0x09, 's',
740 'o', 'c', 'k', 's', 'h', 'o',
741 's', 't', 0x01, 0xBB};
Matt Menke7b5051072019-01-27 21:22:49742
743 MockWrite writes[] = {
744 MockWrite(io_mode, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength),
Peter Kasting0ff39d42021-06-14 13:26:06745 MockWrite(io_mode, reinterpret_cast<const char*>(kSOCKS5Request),
Daniel Cheng5feb16f2022-02-28 06:52:07746 std::size(kSOCKS5Request)),
Matt Menke628d624f2019-02-09 00:40:24747 };
Matt Menke7b5051072019-01-27 21:22:49748
749 MockRead reads[] = {
750 MockRead(io_mode, kSOCKS5GreetResponse, kSOCKS5GreetResponseLength),
Matt Menke628d624f2019-02-09 00:40:24751 MockRead(io_mode, kSOCKS5OkResponse, kSOCKS5OkResponseLength),
752 };
Matt Menke7b5051072019-01-27 21:22:49753
754 host_resolver_.set_synchronous_mode(io_mode == SYNCHRONOUS);
755 StaticSocketDataProvider data(reads, writes);
756 data.set_connect_data(MockConnect(io_mode, OK));
757 socket_factory_.AddSocketDataProvider(&data);
758 SSLSocketDataProvider ssl(io_mode, OK);
759 socket_factory_.AddSSLSocketDataProvider(&ssl);
760
761 TestConnectJobDelegate test_delegate;
762 std::unique_ptr<ConnectJob> ssl_connect_job =
763 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_SOCKS5);
764 test_delegate.StartJobExpectingResult(ssl_connect_job.get(), OK,
765 io_mode == SYNCHRONOUS);
766 CheckConnectTimesExceptDnsSet(ssl_connect_job->connect_timing());
Cammie Smith Barnesaa2a8b52020-12-17 19:33:19767
768 // Proxies should not set any DNS aliases.
769 EXPECT_TRUE(test_delegate.socket()->GetDnsAliases().empty());
Matt Menke7b5051072019-01-27 21:22:49770 }
771}
772
Matt Menke628d624f2019-02-09 00:40:24773TEST_F(SSLConnectJobTest, SOCKSHasEstablishedConnection) {
Peter Kasting0ff39d42021-06-14 13:26:06774 const uint8_t kSOCKS5Request[] = {0x05, 0x01, 0x00, 0x03, 0x09, 's',
775 'o', 'c', 'k', 's', 'h', 'o',
776 's', 't', 0x01, 0xBB};
Matt Menke628d624f2019-02-09 00:40:24777
778 MockWrite writes[] = {
779 MockWrite(SYNCHRONOUS, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength, 0),
Peter Kasting0ff39d42021-06-14 13:26:06780 MockWrite(SYNCHRONOUS, reinterpret_cast<const char*>(kSOCKS5Request),
Daniel Cheng5feb16f2022-02-28 06:52:07781 std::size(kSOCKS5Request), 3),
Matt Menke628d624f2019-02-09 00:40:24782 };
783
784 MockRead reads[] = {
785 // Pause so can probe current state.
786 MockRead(ASYNC, ERR_IO_PENDING, 1),
787 MockRead(ASYNC, kSOCKS5GreetResponse, kSOCKS5GreetResponseLength, 2),
788 MockRead(SYNCHRONOUS, kSOCKS5OkResponse, kSOCKS5OkResponseLength, 4),
789 };
790
791 host_resolver_.set_ondemand_mode(true);
792 SequencedSocketData data(reads, writes);
793 data.set_connect_data(MockConnect(ASYNC, OK));
794 socket_factory_.AddSocketDataProvider(&data);
795
796 // SSL negotiation hangs. Value returned after SSL negotiation is complete
797 // doesn't matter, as HasEstablishedConnection() may only be used between job
798 // start and job complete.
799 SSLSocketDataProvider ssl(SYNCHRONOUS, ERR_IO_PENDING);
800 socket_factory_.AddSSLSocketDataProvider(&ssl);
801
802 TestConnectJobDelegate test_delegate;
803 std::unique_ptr<ConnectJob> ssl_connect_job =
804 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_SOCKS5);
805 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
806 EXPECT_TRUE(host_resolver_.has_pending_requests());
807 EXPECT_EQ(LOAD_STATE_RESOLVING_HOST, ssl_connect_job->GetLoadState());
808 EXPECT_FALSE(ssl_connect_job->HasEstablishedConnection());
809
810 // DNS resolution completes, and then the ConnectJob tries to connect the
811 // socket, which should succeed asynchronously.
812 host_resolver_.ResolveNow(1);
813 EXPECT_EQ(LOAD_STATE_CONNECTING, ssl_connect_job->GetLoadState());
814 EXPECT_FALSE(ssl_connect_job->HasEstablishedConnection());
815
816 // Spin the message loop until the first read of the handshake.
817 // HasEstablishedConnection() should return true, as a TCP connection has been
818 // successfully established by this point.
819 data.RunUntilPaused();
820 EXPECT_FALSE(test_delegate.has_result());
821 EXPECT_EQ(LOAD_STATE_CONNECTING, ssl_connect_job->GetLoadState());
822 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
823
824 // Finish up the handshake, and spin the message loop until the SSL handshake
825 // starts and hang.
826 data.Resume();
827 base::RunLoop().RunUntilIdle();
828 EXPECT_FALSE(test_delegate.has_result());
829 EXPECT_EQ(LOAD_STATE_SSL_HANDSHAKE, ssl_connect_job->GetLoadState());
830 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
831}
832
Matt Menke7b5051072019-01-27 21:22:49833TEST_F(SSLConnectJobTest, SOCKSRequestPriority) {
834 host_resolver_.set_ondemand_mode(true);
Matt Menke7b5051072019-01-27 21:22:49835 for (int initial_priority = MINIMUM_PRIORITY;
836 initial_priority <= MAXIMUM_PRIORITY; ++initial_priority) {
837 SCOPED_TRACE(initial_priority);
838 for (int new_priority = MINIMUM_PRIORITY; new_priority <= MAXIMUM_PRIORITY;
839 ++new_priority) {
840 SCOPED_TRACE(new_priority);
841 if (initial_priority == new_priority)
842 continue;
843 TestConnectJobDelegate test_delegate;
844 std::unique_ptr<ConnectJob> ssl_connect_job =
845 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_SOCKS5,
846 static_cast<RequestPriority>(initial_priority));
847 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
848 EXPECT_TRUE(host_resolver_.has_pending_requests());
849 int request_id = host_resolver_.num_resolve();
850 EXPECT_EQ(initial_priority, host_resolver_.request_priority(request_id));
851
852 ssl_connect_job->ChangePriority(
853 static_cast<RequestPriority>(new_priority));
854 EXPECT_EQ(new_priority, host_resolver_.request_priority(request_id));
855
856 ssl_connect_job->ChangePriority(
857 static_cast<RequestPriority>(initial_priority));
858 EXPECT_EQ(initial_priority, host_resolver_.request_priority(request_id));
Matt Menke7b5051072019-01-27 21:22:49859 }
860 }
861}
862
863TEST_F(SSLConnectJobTest, HttpProxyFail) {
864 for (IoMode io_mode : {SYNCHRONOUS, ASYNC}) {
865 SCOPED_TRACE(io_mode);
866 host_resolver_.set_synchronous_mode(io_mode == SYNCHRONOUS);
867 StaticSocketDataProvider data;
868 data.set_connect_data(MockConnect(io_mode, ERR_CONNECTION_FAILED));
869 socket_factory_.AddSocketDataProvider(&data);
870
871 TestConnectJobDelegate test_delegate;
872 std::unique_ptr<ConnectJob> ssl_connect_job =
873 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_HTTP);
874 test_delegate.StartJobExpectingResult(ssl_connect_job.get(),
875 ERR_PROXY_CONNECTION_FAILED,
876 io_mode == SYNCHRONOUS);
877
Matt Menke6f84d1f12019-04-11 19:26:47878 EXPECT_FALSE(ssl_connect_job->IsSSLError());
Matt Menke6030ed9f2019-04-11 20:25:55879 ConnectionAttempts connection_attempts =
880 ssl_connect_job->GetConnectionAttempts();
881 EXPECT_EQ(0u, connection_attempts.size());
Matt Menke7b5051072019-01-27 21:22:49882 }
883}
884
dalykedd30d982019-12-16 15:31:10885TEST_F(SSLConnectJobTest, HttpProxyHostResolutionFailure) {
886 host_resolver_.rules()->AddSimulatedTimeoutFailure("proxy");
887
888 TestConnectJobDelegate test_delegate;
889 std::unique_ptr<ConnectJob> ssl_connect_job =
890 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_HTTP);
891 test_delegate.StartJobExpectingResult(ssl_connect_job.get(),
892 ERR_PROXY_CONNECTION_FAILED,
893 false /* expect_sync_result */);
894 EXPECT_THAT(ssl_connect_job->GetResolveErrorInfo().error,
895 test::IsError(ERR_DNS_TIMED_OUT));
896}
897
Matt Menkeb57663b32019-03-01 17:17:10898TEST_F(SSLConnectJobTest, HttpProxyAuthChallenge) {
899 MockWrite writes[] = {
900 MockWrite(ASYNC, 0,
901 "CONNECT host:80 HTTP/1.1\r\n"
902 "Host: host:80\r\n"
903 "Proxy-Connection: keep-alive\r\n\r\n"),
904 MockWrite(ASYNC, 5,
905 "CONNECT host:80 HTTP/1.1\r\n"
906 "Host: host:80\r\n"
907 "Proxy-Connection: keep-alive\r\n"
908 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
909 };
910 MockRead reads[] = {
911 MockRead(ASYNC, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"),
912 MockRead(ASYNC, 2, "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
913 MockRead(ASYNC, 3, "Content-Length: 10\r\n\r\n"),
914 MockRead(ASYNC, 4, "0123456789"),
915 MockRead(ASYNC, 6, "HTTP/1.1 200 Connection Established\r\n\r\n"),
916 };
917 StaticSocketDataProvider data(reads, writes);
918 socket_factory_.AddSocketDataProvider(&data);
919 SSLSocketDataProvider ssl(ASYNC, OK);
920 socket_factory_.AddSSLSocketDataProvider(&ssl);
921
Matt Menkeb57663b32019-03-01 17:17:10922 TestConnectJobDelegate test_delegate;
923 std::unique_ptr<ConnectJob> ssl_connect_job =
924 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_HTTP);
925 ASSERT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
926 test_delegate.WaitForAuthChallenge(1);
927
928 EXPECT_EQ(407, test_delegate.auth_response_info().headers->response_code());
929 std::string proxy_authenticate;
930 ASSERT_TRUE(test_delegate.auth_response_info().headers->EnumerateHeader(
931 nullptr, "Proxy-Authenticate", &proxy_authenticate));
932 EXPECT_EQ(proxy_authenticate, "Basic realm=\"MyRealm1\"");
933
934 // While waiting for auth credentials to be provided, the Job should not time
935 // out.
Peter Kastinge5a38ed2021-10-02 03:06:35936 FastForwardBy(base::Days(1));
Matt Menkeb57663b32019-03-01 17:17:10937 test_delegate.WaitForAuthChallenge(1);
938 EXPECT_FALSE(test_delegate.has_result());
939
940 // Respond to challenge.
Jan Wilken Dörriec92a6d7242021-03-23 17:43:48941 test_delegate.auth_controller()->ResetAuth(AuthCredentials(u"foo", u"bar"));
Matt Menkeb57663b32019-03-01 17:17:10942 test_delegate.RunAuthCallback();
943
944 EXPECT_THAT(test_delegate.WaitForResult(), test::IsOk());
Cammie Smith Barnesaa2a8b52020-12-17 19:33:19945
946 // Proxies should not set any DNS aliases.
947 EXPECT_TRUE(test_delegate.socket()->GetDnsAliases().empty());
Matt Menkeb57663b32019-03-01 17:17:10948}
949
950TEST_F(SSLConnectJobTest, HttpProxyAuthWithCachedCredentials) {
Matt Menke7b5051072019-01-27 21:22:49951 for (IoMode io_mode : {SYNCHRONOUS, ASYNC}) {
952 SCOPED_TRACE(io_mode);
953 host_resolver_.set_synchronous_mode(io_mode == SYNCHRONOUS);
954 MockWrite writes[] = {
955 MockWrite(io_mode,
956 "CONNECT host:80 HTTP/1.1\r\n"
957 "Host: host:80\r\n"
958 "Proxy-Connection: keep-alive\r\n"
959 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
960 };
961 MockRead reads[] = {
962 MockRead(io_mode, "HTTP/1.1 200 Connection Established\r\n\r\n"),
963 };
964 StaticSocketDataProvider data(reads, writes);
965 data.set_connect_data(MockConnect(io_mode, OK));
966 socket_factory_.AddSocketDataProvider(&data);
967 AddAuthToCache();
968 SSLSocketDataProvider ssl(io_mode, OK);
969 socket_factory_.AddSSLSocketDataProvider(&ssl);
970
971 TestConnectJobDelegate test_delegate;
972 std::unique_ptr<ConnectJob> ssl_connect_job =
973 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_HTTP);
974 test_delegate.StartJobExpectingResult(ssl_connect_job.get(), OK,
975 io_mode == SYNCHRONOUS);
976 CheckConnectTimesExceptDnsSet(ssl_connect_job->connect_timing());
Cammie Smith Barnesaa2a8b52020-12-17 19:33:19977 EXPECT_TRUE(test_delegate.socket()->GetDnsAliases().empty());
Matt Menke7b5051072019-01-27 21:22:49978 }
979}
980
981TEST_F(SSLConnectJobTest, HttpProxyRequestPriority) {
982 host_resolver_.set_ondemand_mode(true);
Matt Menke7b5051072019-01-27 21:22:49983 for (int initial_priority = MINIMUM_PRIORITY;
984 initial_priority <= MAXIMUM_PRIORITY; ++initial_priority) {
985 SCOPED_TRACE(initial_priority);
986 for (int new_priority = MINIMUM_PRIORITY; new_priority <= MAXIMUM_PRIORITY;
987 ++new_priority) {
988 SCOPED_TRACE(new_priority);
989 if (initial_priority == new_priority)
990 continue;
991 TestConnectJobDelegate test_delegate;
992 std::unique_ptr<ConnectJob> ssl_connect_job =
993 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_HTTP,
994 static_cast<RequestPriority>(initial_priority));
995 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
996 EXPECT_TRUE(host_resolver_.has_pending_requests());
997 int request_id = host_resolver_.num_resolve();
998 EXPECT_EQ(initial_priority, host_resolver_.request_priority(request_id));
999
1000 ssl_connect_job->ChangePriority(
1001 static_cast<RequestPriority>(new_priority));
1002 EXPECT_EQ(new_priority, host_resolver_.request_priority(request_id));
1003
1004 ssl_connect_job->ChangePriority(
1005 static_cast<RequestPriority>(initial_priority));
1006 EXPECT_EQ(initial_priority, host_resolver_.request_priority(request_id));
Matt Menke7b5051072019-01-27 21:22:491007 }
1008 }
1009}
1010
Matt Menkeaade5812019-03-02 13:38:001011TEST_F(SSLConnectJobTest, HttpProxyAuthHasEstablishedConnection) {
1012 host_resolver_.set_ondemand_mode(true);
1013 MockWrite writes[] = {
1014 MockWrite(ASYNC, 0,
1015 "CONNECT host:80 HTTP/1.1\r\n"
1016 "Host: host:80\r\n"
1017 "Proxy-Connection: keep-alive\r\n\r\n"),
1018 MockWrite(ASYNC, 3,
1019 "CONNECT host:80 HTTP/1.1\r\n"
1020 "Host: host:80\r\n"
1021 "Proxy-Connection: keep-alive\r\n"
1022 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1023 };
1024 MockRead reads[] = {
1025 // Pause reading.
1026 MockRead(ASYNC, ERR_IO_PENDING, 1),
1027 MockRead(ASYNC, 2,
1028 "HTTP/1.1 407 Proxy Authentication Required\r\n"
1029 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
1030 "Content-Length: 0\r\n\r\n"),
1031 // Pause reading.
1032 MockRead(ASYNC, ERR_IO_PENDING, 4),
1033 MockRead(ASYNC, 5, "HTTP/1.1 200 Connection Established\r\n\r\n"),
1034 };
1035 SequencedSocketData data(reads, writes);
1036 socket_factory_.AddSocketDataProvider(&data);
1037 SSLSocketDataProvider ssl(ASYNC, OK);
1038 socket_factory_.AddSSLSocketDataProvider(&ssl);
1039
Matt Menkeaade5812019-03-02 13:38:001040 TestConnectJobDelegate test_delegate;
1041 std::unique_ptr<ConnectJob> ssl_connect_job =
1042 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_HTTP);
1043 ASSERT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
1044 EXPECT_TRUE(host_resolver_.has_pending_requests());
1045 EXPECT_EQ(LOAD_STATE_RESOLVING_HOST, ssl_connect_job->GetLoadState());
1046 EXPECT_FALSE(ssl_connect_job->HasEstablishedConnection());
1047
1048 // DNS resolution completes, and then the ConnectJob tries to connect the
1049 // socket, which should succeed asynchronously.
1050 host_resolver_.ResolveOnlyRequestNow();
1051 EXPECT_EQ(LOAD_STATE_CONNECTING, ssl_connect_job->GetLoadState());
1052 EXPECT_FALSE(ssl_connect_job->HasEstablishedConnection());
1053
1054 // Spinning the message loop causes the connection to be established and the
1055 // nested HttpProxyConnectJob to start establishing a tunnel.
1056 base::RunLoop().RunUntilIdle();
1057 EXPECT_FALSE(test_delegate.has_result());
1058 EXPECT_EQ(LOAD_STATE_ESTABLISHING_PROXY_TUNNEL,
1059 ssl_connect_job->GetLoadState());
1060 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
1061
1062 // Receive the auth challenge.
1063 data.Resume();
1064 test_delegate.WaitForAuthChallenge(1);
1065 EXPECT_FALSE(test_delegate.has_result());
1066 EXPECT_EQ(LOAD_STATE_IDLE, ssl_connect_job->GetLoadState());
1067 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
1068
1069 // Respond to challenge.
Jan Wilken Dörriec92a6d7242021-03-23 17:43:481070 test_delegate.auth_controller()->ResetAuth(AuthCredentials(u"foo", u"bar"));
Matt Menkeaade5812019-03-02 13:38:001071 test_delegate.RunAuthCallback();
1072 EXPECT_FALSE(test_delegate.has_result());
1073 EXPECT_EQ(LOAD_STATE_ESTABLISHING_PROXY_TUNNEL,
1074 ssl_connect_job->GetLoadState());
1075 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
1076
1077 // Run until the next read pauses.
1078 base::RunLoop().RunUntilIdle();
1079 EXPECT_FALSE(test_delegate.has_result());
1080 EXPECT_EQ(LOAD_STATE_ESTABLISHING_PROXY_TUNNEL,
1081 ssl_connect_job->GetLoadState());
1082 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
1083
1084 // Receive the connection established response, at which point SSL negotiation
1085 // finally starts.
1086 data.Resume();
1087 EXPECT_FALSE(test_delegate.has_result());
1088 EXPECT_EQ(LOAD_STATE_SSL_HANDSHAKE, ssl_connect_job->GetLoadState());
1089 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
1090
1091 EXPECT_THAT(test_delegate.WaitForResult(), test::IsOk());
1092}
1093
1094TEST_F(SSLConnectJobTest,
1095 HttpProxyAuthHasEstablishedConnectionWithProxyConnectionClose) {
1096 host_resolver_.set_ondemand_mode(true);
1097 MockWrite writes1[] = {
1098 MockWrite(ASYNC, 0,
1099 "CONNECT host:80 HTTP/1.1\r\n"
1100 "Host: host:80\r\n"
1101 "Proxy-Connection: keep-alive\r\n\r\n"),
1102 };
1103 MockRead reads1[] = {
1104 // Pause reading.
1105 MockRead(ASYNC, ERR_IO_PENDING, 1),
1106 MockRead(ASYNC, 2,
1107 "HTTP/1.1 407 Proxy Authentication Required\r\n"
1108 "Proxy-Connection: Close\r\n"
1109 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
1110 "Content-Length: 0\r\n\r\n"),
1111 };
1112 SequencedSocketData data1(reads1, writes1);
1113 socket_factory_.AddSocketDataProvider(&data1);
1114
1115 MockWrite writes2[] = {
1116 MockWrite(ASYNC, 0,
1117 "CONNECT host:80 HTTP/1.1\r\n"
1118 "Host: host:80\r\n"
1119 "Proxy-Connection: keep-alive\r\n"
1120 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1121 };
1122 MockRead reads2[] = {
1123 // Pause reading.
1124 MockRead(ASYNC, ERR_IO_PENDING, 1),
1125 MockRead(ASYNC, 2, "HTTP/1.1 200 Connection Established\r\n\r\n"),
1126 };
1127 SequencedSocketData data2(reads2, writes2);
1128 socket_factory_.AddSocketDataProvider(&data2);
1129 SSLSocketDataProvider ssl(ASYNC, OK);
1130 socket_factory_.AddSSLSocketDataProvider(&ssl);
1131
Matt Menkeaade5812019-03-02 13:38:001132 TestConnectJobDelegate test_delegate;
1133 std::unique_ptr<ConnectJob> ssl_connect_job =
1134 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_HTTP);
1135 ASSERT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
1136 EXPECT_TRUE(host_resolver_.has_pending_requests());
1137 EXPECT_EQ(LOAD_STATE_RESOLVING_HOST, ssl_connect_job->GetLoadState());
1138 EXPECT_FALSE(ssl_connect_job->HasEstablishedConnection());
1139
1140 // DNS resolution completes, and then the ConnectJob tries to connect the
1141 // socket, which should succeed asynchronously.
1142 host_resolver_.ResolveOnlyRequestNow();
1143 EXPECT_EQ(LOAD_STATE_CONNECTING, ssl_connect_job->GetLoadState());
1144 EXPECT_FALSE(ssl_connect_job->HasEstablishedConnection());
1145
1146 // Spinning the message loop causes the connection to be established and the
1147 // nested HttpProxyConnectJob to start establishing a tunnel.
1148 base::RunLoop().RunUntilIdle();
1149 EXPECT_FALSE(test_delegate.has_result());
1150 EXPECT_EQ(LOAD_STATE_ESTABLISHING_PROXY_TUNNEL,
1151 ssl_connect_job->GetLoadState());
1152 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
1153
1154 // Receive the auth challenge.
1155 data1.Resume();
1156 test_delegate.WaitForAuthChallenge(1);
1157 EXPECT_FALSE(test_delegate.has_result());
1158 EXPECT_EQ(LOAD_STATE_IDLE, ssl_connect_job->GetLoadState());
1159 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
1160
1161 // Respond to challenge.
Jan Wilken Dörriec92a6d7242021-03-23 17:43:481162 test_delegate.auth_controller()->ResetAuth(AuthCredentials(u"foo", u"bar"));
Matt Menkeaade5812019-03-02 13:38:001163 test_delegate.RunAuthCallback();
1164 EXPECT_FALSE(test_delegate.has_result());
1165 EXPECT_EQ(LOAD_STATE_ESTABLISHING_PROXY_TUNNEL,
1166 ssl_connect_job->GetLoadState());
1167 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
1168
1169 // Run until the next DNS lookup.
1170 base::RunLoop().RunUntilIdle();
1171 EXPECT_TRUE(host_resolver_.has_pending_requests());
1172 EXPECT_EQ(LOAD_STATE_RESOLVING_HOST, ssl_connect_job->GetLoadState());
1173 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
1174
1175 // DNS resolution completes, and then the ConnectJob tries to connect the
1176 // socket, which should succeed asynchronously.
1177 host_resolver_.ResolveOnlyRequestNow();
1178 EXPECT_EQ(LOAD_STATE_CONNECTING, ssl_connect_job->GetLoadState());
1179 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
1180
1181 // Spinning the message loop causes the connection to be established and the
1182 // nested HttpProxyConnectJob to start establishing a tunnel.
1183 base::RunLoop().RunUntilIdle();
1184 EXPECT_FALSE(test_delegate.has_result());
1185 EXPECT_EQ(LOAD_STATE_ESTABLISHING_PROXY_TUNNEL,
1186 ssl_connect_job->GetLoadState());
1187 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
1188
1189 // Receive the connection established response, at which point SSL negotiation
1190 // finally starts.
1191 data2.Resume();
1192 EXPECT_FALSE(test_delegate.has_result());
1193 EXPECT_EQ(LOAD_STATE_SSL_HANDSHAKE, ssl_connect_job->GetLoadState());
1194 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
1195
1196 EXPECT_THAT(test_delegate.WaitForResult(), test::IsOk());
1197}
1198
Cammie Smith Barnesaa2a8b52020-12-17 19:33:191199TEST_F(SSLConnectJobTest, DnsAliases) {
1200 host_resolver_.set_synchronous_mode(true);
1201
1202 // Resolve an AddressList with DNS aliases.
1203 std::vector<std::string> aliases({"alias1", "alias2", "host"});
1204 host_resolver_.rules()->AddIPLiteralRuleWithDnsAliases("host", "2.2.2.2",
1205 std::move(aliases));
1206 StaticSocketDataProvider data;
1207 data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1208 socket_factory_.AddSocketDataProvider(&data);
1209 SSLSocketDataProvider ssl(ASYNC, OK);
1210 socket_factory_.AddSSLSocketDataProvider(&ssl);
1211 TestConnectJobDelegate test_delegate;
1212
1213 std::unique_ptr<ConnectJob> ssl_connect_job =
1214 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_DIRECT, MEDIUM);
1215
1216 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
1217
1218 base::RunLoop().RunUntilIdle();
1219
1220 // Verify that the elements of the alias list are those from the
1221 // parameter vector.
1222 EXPECT_THAT(test_delegate.socket()->GetDnsAliases(),
1223 testing::ElementsAre("alias1", "alias2", "host"));
1224}
1225
1226TEST_F(SSLConnectJobTest, NoAdditionalDnsAliases) {
1227 host_resolver_.set_synchronous_mode(true);
1228
1229 // Resolve an AddressList without additional DNS aliases. (The parameter
1230 // is an empty vector.)
1231 std::vector<std::string> aliases;
1232 host_resolver_.rules()->AddIPLiteralRuleWithDnsAliases("host", "2.2.2.2",
1233 std::move(aliases));
1234 StaticSocketDataProvider data;
1235 data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1236 socket_factory_.AddSocketDataProvider(&data);
1237 SSLSocketDataProvider ssl(ASYNC, OK);
1238 socket_factory_.AddSSLSocketDataProvider(&ssl);
1239 TestConnectJobDelegate test_delegate;
1240
1241 std::unique_ptr<ConnectJob> ssl_connect_job =
1242 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_DIRECT, MEDIUM);
1243
1244 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
1245
1246 base::RunLoop().RunUntilIdle();
1247
1248 // Verify that the alias list only contains "host".
1249 EXPECT_THAT(test_delegate.socket()->GetDnsAliases(),
1250 testing::ElementsAre("host"));
1251}
1252
David Benjamin1edf73f2022-06-09 18:26:511253// Test that `SSLConnectJob` passes the ECHConfigList from DNS to
1254// `SSLClientSocket`.
1255TEST_F(SSLConnectJobTest, EncryptedClientHello) {
1256 std::vector<uint8_t> ech_config_list1, ech_config_list2;
1257 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1258 &ech_config_list1));
1259 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1260 &ech_config_list2));
1261
1262 // Configure two HTTPS RR routes, to test we pass the correct one.
1263 HostResolverEndpointResult endpoint1, endpoint2;
1264 endpoint1.ip_endpoints = {IPEndPoint(ParseIP("1::"), 8441)};
1265 endpoint1.metadata.supported_protocol_alpns = {"http/1.1"};
1266 endpoint1.metadata.ech_config_list = ech_config_list1;
1267 endpoint2.ip_endpoints = {IPEndPoint(ParseIP("2::"), 8442)};
1268 endpoint2.metadata.supported_protocol_alpns = {"http/1.1"};
1269 endpoint2.metadata.ech_config_list = ech_config_list2;
Tsuyoshi Horo81db8902022-08-18 01:06:261270 host_resolver_.rules()->AddRule(
1271 "host", MockHostResolverBase::RuleResolver::RuleResult(
1272 std::vector{endpoint1, endpoint2}));
David Benjamin1edf73f2022-06-09 18:26:511273
1274 for (bool feature_enabled : {true, false}) {
1275 SCOPED_TRACE(feature_enabled);
1276 base::test::ScopedFeatureList feature_list;
1277 if (feature_enabled) {
1278 feature_list.InitAndEnableFeature(features::kEncryptedClientHello);
1279 } else {
1280 feature_list.InitAndDisableFeature(features::kEncryptedClientHello);
1281 }
1282
1283 // The first connection attempt will be to `endpoint1`, which will fail.
1284 StaticSocketDataProvider data1;
1285 data1.set_expected_addresses(AddressList(endpoint1.ip_endpoints));
1286 data1.set_connect_data(MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED));
1287 socket_factory_.AddSocketDataProvider(&data1);
1288 // The second connection attempt will be to `endpoint2`, which will succeed.
1289 StaticSocketDataProvider data2;
1290 data2.set_expected_addresses(AddressList(endpoint2.ip_endpoints));
1291 data2.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1292 socket_factory_.AddSocketDataProvider(&data2);
1293 // The handshake then succeeds.
1294 SSLSocketDataProvider ssl2(ASYNC, OK);
1295 // The ECH configuration should be passed if and only if the feature is
1296 // enabled.
1297 ssl2.expected_ech_config_list =
1298 feature_enabled ? ech_config_list2 : std::vector<uint8_t>{};
1299 socket_factory_.AddSSLSocketDataProvider(&ssl2);
1300
1301 // The connection should ultimately succeed.
1302 base::HistogramTester histogram_tester;
1303 TestConnectJobDelegate test_delegate;
1304 std::unique_ptr<ConnectJob> ssl_connect_job =
1305 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_DIRECT, MEDIUM);
1306 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
1307 EXPECT_THAT(test_delegate.WaitForResult(), test::IsOk());
1308
1309 // Whether or not the feature is enabled, we should record data for the
1310 // ECH-capable server.
1311 histogram_tester.ExpectUniqueSample("Net.SSL_Connection_Error_ECH", OK, 1);
1312 histogram_tester.ExpectTotalCount("Net.SSL_Connection_Latency_ECH", 1);
1313 // The ECH result should only be recorded if ECH was actually enabled.
1314 if (feature_enabled) {
1315 histogram_tester.ExpectUniqueSample("Net.SSL.ECHResult",
1316 0 /* kSuccessInitial */, 1);
1317 } else {
1318 histogram_tester.ExpectTotalCount("Net.SSL.ECHResult", 0);
1319 }
1320 }
1321}
1322
David Benjamindc5fd6a2022-03-24 23:00:411323// Test that `SSLConnectJob` retries the connection if there was a stale ECH
1324// configuration.
1325TEST_F(SSLConnectJobTest, ECHStaleConfig) {
1326 base::test::ScopedFeatureList feature_list;
1327 feature_list.InitAndEnableFeature(features::kEncryptedClientHello);
1328
1329 std::vector<uint8_t> ech_config_list1, ech_config_list2, ech_config_list3;
1330 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1331 &ech_config_list1));
1332 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1333 &ech_config_list2));
1334 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1335 &ech_config_list3));
1336
1337 // Configure two HTTPS RR routes, to test the retry uses the correct one.
1338 HostResolverEndpointResult endpoint1, endpoint2;
1339 endpoint1.ip_endpoints = {IPEndPoint(ParseIP("1::"), 8441)};
1340 endpoint1.metadata.supported_protocol_alpns = {"http/1.1"};
1341 endpoint1.metadata.ech_config_list = ech_config_list1;
1342 endpoint2.ip_endpoints = {IPEndPoint(ParseIP("2::"), 8442)};
1343 endpoint2.metadata.supported_protocol_alpns = {"http/1.1"};
1344 endpoint2.metadata.ech_config_list = ech_config_list2;
Tsuyoshi Horo81db8902022-08-18 01:06:261345 host_resolver_.rules()->AddRule(
1346 "host", MockHostResolverBase::RuleResolver::RuleResult(
1347 std::vector{endpoint1, endpoint2}));
David Benjamindc5fd6a2022-03-24 23:00:411348
1349 // The first connection attempt will be to `endpoint1`, which will fail.
1350 StaticSocketDataProvider data1;
1351 data1.set_expected_addresses(AddressList(endpoint1.ip_endpoints));
1352 data1.set_connect_data(MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED));
1353 socket_factory_.AddSocketDataProvider(&data1);
1354 // The second connection attempt will be to `endpoint2`, which will succeed.
1355 StaticSocketDataProvider data2;
1356 data2.set_expected_addresses(AddressList(endpoint2.ip_endpoints));
1357 data2.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1358 socket_factory_.AddSocketDataProvider(&data2);
1359 // The handshake will then fail, but then provide retry configs.
1360 SSLSocketDataProvider ssl2(ASYNC, ERR_ECH_NOT_NEGOTIATED);
1361 ssl2.expected_ech_config_list = ech_config_list2;
1362 ssl2.ech_retry_configs = ech_config_list3;
1363 socket_factory_.AddSSLSocketDataProvider(&ssl2);
1364 // The third connection attempt should skip `endpoint1` and retry with only
1365 // `endpoint2`.
1366 StaticSocketDataProvider data3;
1367 data3.set_expected_addresses(AddressList(endpoint2.ip_endpoints));
1368 data3.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1369 socket_factory_.AddSocketDataProvider(&data3);
1370 // The handshake should be passed the retry configs.
1371 SSLSocketDataProvider ssl3(ASYNC, OK);
1372 ssl3.expected_ech_config_list = ech_config_list3;
1373 socket_factory_.AddSSLSocketDataProvider(&ssl3);
1374
1375 // The connection should ultimately succeed.
David Benjamin1edf73f2022-06-09 18:26:511376 base::HistogramTester histogram_tester;
David Benjamindc5fd6a2022-03-24 23:00:411377 TestConnectJobDelegate test_delegate;
1378 std::unique_ptr<ConnectJob> ssl_connect_job =
1379 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_DIRECT, MEDIUM);
1380 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
1381 EXPECT_THAT(test_delegate.WaitForResult(), test::IsOk());
David Benjamin1edf73f2022-06-09 18:26:511382
1383 histogram_tester.ExpectUniqueSample("Net.SSL.ECHResult",
1384 2 /* kSuccessRetry */, 1);
David Benjamindc5fd6a2022-03-24 23:00:411385}
1386
1387// Test that `SSLConnectJob` retries the connection given a secure rollback
1388// signal.
1389TEST_F(SSLConnectJobTest, ECHRollback) {
1390 base::test::ScopedFeatureList feature_list;
1391 feature_list.InitAndEnableFeature(features::kEncryptedClientHello);
1392
1393 std::vector<uint8_t> ech_config_list1, ech_config_list2;
1394 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1395 &ech_config_list1));
1396 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1397 &ech_config_list2));
1398
1399 // Configure two HTTPS RR routes, to test the retry uses the correct one.
1400 HostResolverEndpointResult endpoint1, endpoint2;
1401 endpoint1.ip_endpoints = {IPEndPoint(ParseIP("1::"), 8441)};
1402 endpoint1.metadata.supported_protocol_alpns = {"http/1.1"};
1403 endpoint1.metadata.ech_config_list = ech_config_list1;
1404 endpoint2.ip_endpoints = {IPEndPoint(ParseIP("2::"), 8442)};
1405 endpoint2.metadata.supported_protocol_alpns = {"http/1.1"};
1406 endpoint2.metadata.ech_config_list = ech_config_list2;
Tsuyoshi Horo81db8902022-08-18 01:06:261407 host_resolver_.rules()->AddRule(
1408 "host", MockHostResolverBase::RuleResolver::RuleResult(
1409 std::vector{endpoint1, endpoint2}));
David Benjamindc5fd6a2022-03-24 23:00:411410
1411 // The first connection attempt will be to `endpoint1`, which will fail.
1412 StaticSocketDataProvider data1;
1413 data1.set_expected_addresses(AddressList(endpoint1.ip_endpoints));
1414 data1.set_connect_data(MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED));
1415 socket_factory_.AddSocketDataProvider(&data1);
1416 // The second connection attempt will be to `endpoint2`, which will succeed.
1417 StaticSocketDataProvider data2;
1418 data2.set_expected_addresses(AddressList(endpoint2.ip_endpoints));
1419 data2.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1420 socket_factory_.AddSocketDataProvider(&data2);
1421 // The handshake will then fail, and provide no retry configs.
1422 SSLSocketDataProvider ssl2(ASYNC, ERR_ECH_NOT_NEGOTIATED);
1423 ssl2.expected_ech_config_list = ech_config_list2;
1424 ssl2.ech_retry_configs = std::vector<uint8_t>();
1425 socket_factory_.AddSSLSocketDataProvider(&ssl2);
1426 // The third connection attempt should skip `endpoint1` and retry with only
1427 // `endpoint2`.
1428 StaticSocketDataProvider data3;
1429 data3.set_expected_addresses(AddressList(endpoint2.ip_endpoints));
1430 data3.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1431 socket_factory_.AddSocketDataProvider(&data3);
1432 // The handshake should not be passed ECH configs.
1433 SSLSocketDataProvider ssl3(ASYNC, OK);
1434 ssl3.expected_ech_config_list = std::vector<uint8_t>();
1435 socket_factory_.AddSSLSocketDataProvider(&ssl3);
1436
1437 // The connection should ultimately succeed.
David Benjamin1edf73f2022-06-09 18:26:511438 base::HistogramTester histogram_tester;
David Benjamindc5fd6a2022-03-24 23:00:411439 TestConnectJobDelegate test_delegate;
1440 std::unique_ptr<ConnectJob> ssl_connect_job =
1441 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_DIRECT, MEDIUM);
1442 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
1443 EXPECT_THAT(test_delegate.WaitForResult(), test::IsOk());
David Benjamin1edf73f2022-06-09 18:26:511444
1445 histogram_tester.ExpectUniqueSample("Net.SSL.ECHResult",
1446 4 /* kSuccessRollback */, 1);
David Benjamindc5fd6a2022-03-24 23:00:411447}
1448
1449// Test that `SSLConnectJob` will not retry more than once.
1450TEST_F(SSLConnectJobTest, ECHTooManyRetries) {
1451 base::test::ScopedFeatureList feature_list;
1452 feature_list.InitAndEnableFeature(features::kEncryptedClientHello);
1453
1454 std::vector<uint8_t> ech_config_list1, ech_config_list2, ech_config_list3;
1455 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1456 &ech_config_list1));
1457 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1458 &ech_config_list2));
1459 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1460 &ech_config_list3));
1461
1462 HostResolverEndpointResult endpoint;
1463 endpoint.ip_endpoints = {IPEndPoint(ParseIP("1::"), 8441)};
1464 endpoint.metadata.supported_protocol_alpns = {"http/1.1"};
1465 endpoint.metadata.ech_config_list = ech_config_list1;
Tsuyoshi Horo81db8902022-08-18 01:06:261466 host_resolver_.rules()->AddRule(
1467 "host",
1468 MockHostResolverBase::RuleResolver::RuleResult(std::vector{endpoint}));
David Benjamindc5fd6a2022-03-24 23:00:411469
1470 // The first connection attempt will succeed.
1471 StaticSocketDataProvider data1;
1472 data1.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1473 socket_factory_.AddSocketDataProvider(&data1);
1474 // The handshake will then fail, but provide retry configs.
1475 SSLSocketDataProvider ssl1(ASYNC, ERR_ECH_NOT_NEGOTIATED);
1476 ssl1.expected_ech_config_list = ech_config_list1;
1477 ssl1.ech_retry_configs = ech_config_list2;
1478 socket_factory_.AddSSLSocketDataProvider(&ssl1);
1479 // The second connection attempt will succeed.
1480 StaticSocketDataProvider data2;
1481 data2.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1482 socket_factory_.AddSocketDataProvider(&data2);
1483 // The handshake will then fail, but provide new retry configs.
1484 SSLSocketDataProvider ssl2(ASYNC, ERR_ECH_NOT_NEGOTIATED);
1485 ssl2.expected_ech_config_list = ech_config_list2;
1486 ssl2.ech_retry_configs = ech_config_list3;
1487 socket_factory_.AddSSLSocketDataProvider(&ssl2);
1488 // There will be no third connection attempt.
1489
David Benjamin1edf73f2022-06-09 18:26:511490 base::HistogramTester histogram_tester;
David Benjamindc5fd6a2022-03-24 23:00:411491 TestConnectJobDelegate test_delegate;
1492 std::unique_ptr<ConnectJob> ssl_connect_job =
1493 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_DIRECT, MEDIUM);
1494 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
1495 EXPECT_THAT(test_delegate.WaitForResult(),
1496 test::IsError(ERR_ECH_NOT_NEGOTIATED));
David Benjamin1edf73f2022-06-09 18:26:511497
1498 histogram_tester.ExpectUniqueSample("Net.SSL.ECHResult", 3 /* kErrorRetry */,
1499 1);
David Benjamindc5fd6a2022-03-24 23:00:411500}
1501
1502// Test that `SSLConnectJob` will not retry for ECH given the wrong error.
1503TEST_F(SSLConnectJobTest, ECHWrongRetryError) {
1504 base::test::ScopedFeatureList feature_list;
1505 feature_list.InitAndEnableFeature(features::kEncryptedClientHello);
1506
1507 std::vector<uint8_t> ech_config_list1, ech_config_list2;
1508 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1509 &ech_config_list1));
1510 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1511 &ech_config_list2));
1512
1513 HostResolverEndpointResult endpoint;
1514 endpoint.ip_endpoints = {IPEndPoint(ParseIP("1::"), 8441)};
1515 endpoint.metadata.supported_protocol_alpns = {"http/1.1"};
1516 endpoint.metadata.ech_config_list = ech_config_list1;
Tsuyoshi Horo81db8902022-08-18 01:06:261517 host_resolver_.rules()->AddRule(
1518 "host",
1519 MockHostResolverBase::RuleResolver::RuleResult(std::vector{endpoint}));
David Benjamindc5fd6a2022-03-24 23:00:411520
1521 // The first connection attempt will succeed.
1522 StaticSocketDataProvider data1;
1523 data1.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1524 socket_factory_.AddSocketDataProvider(&data1);
1525 // The handshake will then fail, but provide retry configs.
1526 SSLSocketDataProvider ssl1(ASYNC, ERR_FAILED);
1527 ssl1.expected_ech_config_list = ech_config_list1;
1528 ssl1.ech_retry_configs = ech_config_list2;
1529 socket_factory_.AddSSLSocketDataProvider(&ssl1);
1530 // There will be no second connection attempt.
1531
David Benjamin1edf73f2022-06-09 18:26:511532 base::HistogramTester histogram_tester;
David Benjamindc5fd6a2022-03-24 23:00:411533 TestConnectJobDelegate test_delegate;
1534 std::unique_ptr<ConnectJob> ssl_connect_job =
1535 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_DIRECT, MEDIUM);
1536 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
1537 EXPECT_THAT(test_delegate.WaitForResult(), test::IsError(ERR_FAILED));
David Benjamin1edf73f2022-06-09 18:26:511538
1539 histogram_tester.ExpectUniqueSample("Net.SSL.ECHResult",
1540 1 /* kErrorInitial */, 1);
David Benjamindc5fd6a2022-03-24 23:00:411541}
1542
1543// Test the legacy crypto callback can trigger after the ECH recovery flow.
1544TEST_F(SSLConnectJobTest, ECHRecoveryThenLegacyCrypto) {
1545 base::test::ScopedFeatureList feature_list;
1546 feature_list.InitAndEnableFeature(features::kEncryptedClientHello);
1547
1548 std::vector<uint8_t> ech_config_list1, ech_config_list2, ech_config_list3;
1549 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1550 &ech_config_list1));
1551 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1552 &ech_config_list2));
1553 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1554 &ech_config_list3));
1555
1556 // Configure two HTTPS RR routes, to test the retry uses the correct one.
1557 HostResolverEndpointResult endpoint1, endpoint2;
1558 endpoint1.ip_endpoints = {IPEndPoint(ParseIP("1::"), 8441)};
1559 endpoint1.metadata.supported_protocol_alpns = {"http/1.1"};
1560 endpoint1.metadata.ech_config_list = ech_config_list1;
1561 endpoint2.ip_endpoints = {IPEndPoint(ParseIP("2::"), 8442)};
1562 endpoint2.metadata.supported_protocol_alpns = {"http/1.1"};
1563 endpoint2.metadata.ech_config_list = ech_config_list2;
Tsuyoshi Horo81db8902022-08-18 01:06:261564 host_resolver_.rules()->AddRule(
1565 "host", MockHostResolverBase::RuleResolver::RuleResult(
1566 std::vector{endpoint1, endpoint2}));
David Benjamindc5fd6a2022-03-24 23:00:411567
1568 // The first connection attempt will be to `endpoint1`, which will fail.
1569 StaticSocketDataProvider data1;
1570 data1.set_expected_addresses(AddressList(endpoint1.ip_endpoints));
1571 data1.set_connect_data(MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED));
1572 socket_factory_.AddSocketDataProvider(&data1);
1573 // The second connection attempt will be to `endpoint2`, which will succeed.
1574 StaticSocketDataProvider data2;
1575 data2.set_expected_addresses(AddressList(endpoint2.ip_endpoints));
1576 data2.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1577 socket_factory_.AddSocketDataProvider(&data2);
1578 // The handshake will then fail, and provide retry configs.
1579 SSLSocketDataProvider ssl2(ASYNC, ERR_ECH_NOT_NEGOTIATED);
1580 ssl2.expected_ech_config_list = ech_config_list2;
1581 ssl2.expected_disable_legacy_crypto = true;
1582 ssl2.ech_retry_configs = ech_config_list3;
1583 socket_factory_.AddSSLSocketDataProvider(&ssl2);
1584 // The third connection attempt should skip `endpoint1` and retry with only
1585 // `endpoint2`.
1586 StaticSocketDataProvider data3;
1587 data3.set_expected_addresses(AddressList(endpoint2.ip_endpoints));
1588 data3.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1589 socket_factory_.AddSocketDataProvider(&data3);
1590 // The handshake should be passed the retry configs. This will progress
1591 // further but trigger the legacy crypto fallback.
1592 SSLSocketDataProvider ssl3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
1593 ssl3.expected_ech_config_list = ech_config_list3;
1594 ssl3.expected_disable_legacy_crypto = true;
1595 socket_factory_.AddSSLSocketDataProvider(&ssl3);
1596 // The third connection attempt should still skip `endpoint1` and retry with
1597 // only `endpoint2`.
1598 StaticSocketDataProvider data4;
1599 data4.set_expected_addresses(AddressList(endpoint2.ip_endpoints));
1600 data4.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1601 socket_factory_.AddSocketDataProvider(&data4);
1602 // The handshake should still be passed ECH retry configs. This time, the
1603 // connection enables legacy crypto and succeeds.
1604 SSLSocketDataProvider ssl4(ASYNC, OK);
1605 ssl4.expected_ech_config_list = ech_config_list3;
1606 ssl4.expected_disable_legacy_crypto = false;
1607 socket_factory_.AddSSLSocketDataProvider(&ssl4);
1608
1609 // The connection should ultimately succeed.
David Benjamin1edf73f2022-06-09 18:26:511610 base::HistogramTester histogram_tester;
David Benjamindc5fd6a2022-03-24 23:00:411611 TestConnectJobDelegate test_delegate;
1612 std::unique_ptr<ConnectJob> ssl_connect_job =
1613 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_DIRECT, MEDIUM);
1614 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
1615 EXPECT_THAT(test_delegate.WaitForResult(), test::IsOk());
David Benjamin1edf73f2022-06-09 18:26:511616
1617 histogram_tester.ExpectUniqueSample("Net.SSL.ECHResult",
1618 2 /* kSuccessRetry */, 1);
David Benjamindc5fd6a2022-03-24 23:00:411619}
1620
1621// Test the ECH recovery flow can trigger after the legacy crypto fallback.
1622TEST_F(SSLConnectJobTest, LegacyCryptoThenECHRecovery) {
1623 base::test::ScopedFeatureList feature_list;
1624 feature_list.InitAndEnableFeature(features::kEncryptedClientHello);
1625
1626 std::vector<uint8_t> ech_config_list1, ech_config_list2, ech_config_list3;
1627 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1628 &ech_config_list1));
1629 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1630 &ech_config_list2));
1631 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1632 &ech_config_list3));
1633
1634 // Configure two HTTPS RR routes, to test the retry uses the correct one.
1635 HostResolverEndpointResult endpoint1, endpoint2;
1636 endpoint1.ip_endpoints = {IPEndPoint(ParseIP("1::"), 8441)};
1637 endpoint1.metadata.supported_protocol_alpns = {"http/1.1"};
1638 endpoint1.metadata.ech_config_list = ech_config_list1;
1639 endpoint2.ip_endpoints = {IPEndPoint(ParseIP("2::"), 8442)};
1640 endpoint2.metadata.supported_protocol_alpns = {"http/1.1"};
1641 endpoint2.metadata.ech_config_list = ech_config_list2;
Tsuyoshi Horo81db8902022-08-18 01:06:261642 host_resolver_.rules()->AddRule(
1643 "host", MockHostResolverBase::RuleResolver::RuleResult(
1644 std::vector{endpoint1, endpoint2}));
David Benjamindc5fd6a2022-03-24 23:00:411645
1646 // The first connection attempt will be to `endpoint1`, which will fail.
1647 StaticSocketDataProvider data1;
1648 data1.set_expected_addresses(AddressList(endpoint1.ip_endpoints));
1649 data1.set_connect_data(MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED));
1650 socket_factory_.AddSocketDataProvider(&data1);
1651 // The second connection attempt will be to `endpoint2`, which will succeed.
1652 StaticSocketDataProvider data2;
1653 data2.set_expected_addresses(AddressList(endpoint2.ip_endpoints));
1654 data2.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1655 socket_factory_.AddSocketDataProvider(&data2);
1656 // The handshake will then fail, and trigger the legacy cryptography fallback.
1657 SSLSocketDataProvider ssl2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
1658 ssl2.expected_ech_config_list = ech_config_list2;
1659 ssl2.expected_disable_legacy_crypto = true;
1660 socket_factory_.AddSSLSocketDataProvider(&ssl2);
1661 // The third and fourth connection attempts proceed as before, but with legacy
1662 // cryptography enabled.
1663 StaticSocketDataProvider data3;
1664 data3.set_expected_addresses(AddressList(endpoint1.ip_endpoints));
1665 data3.set_connect_data(MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED));
1666 socket_factory_.AddSocketDataProvider(&data3);
1667 StaticSocketDataProvider data4;
1668 data4.set_expected_addresses(AddressList(endpoint2.ip_endpoints));
1669 data4.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1670 socket_factory_.AddSocketDataProvider(&data4);
1671 // The handshake enables legacy crypto. Now ECH fails with retry configs.
1672 SSLSocketDataProvider ssl4(ASYNC, ERR_ECH_NOT_NEGOTIATED);
1673 ssl4.expected_ech_config_list = ech_config_list2;
1674 ssl4.expected_disable_legacy_crypto = false;
1675 ssl4.ech_retry_configs = ech_config_list3;
1676 socket_factory_.AddSSLSocketDataProvider(&ssl4);
1677 // The fourth connection attempt should still skip `endpoint1` and retry with
1678 // only `endpoint2`.
1679 StaticSocketDataProvider data5;
1680 data5.set_expected_addresses(AddressList(endpoint2.ip_endpoints));
1681 data5.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1682 socket_factory_.AddSocketDataProvider(&data5);
1683 // The handshake will now succeed with ECH retry configs and legacy
1684 // cryptography.
1685 SSLSocketDataProvider ssl5(ASYNC, OK);
1686 ssl5.expected_ech_config_list = ech_config_list3;
1687 ssl5.expected_disable_legacy_crypto = false;
1688 socket_factory_.AddSSLSocketDataProvider(&ssl5);
1689
1690 // The connection should ultimately succeed.
David Benjamin1edf73f2022-06-09 18:26:511691 base::HistogramTester histogram_tester;
David Benjamindc5fd6a2022-03-24 23:00:411692 TestConnectJobDelegate test_delegate;
1693 std::unique_ptr<ConnectJob> ssl_connect_job =
1694 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_DIRECT, MEDIUM);
1695 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
1696 EXPECT_THAT(test_delegate.WaitForResult(), test::IsOk());
David Benjamin1edf73f2022-06-09 18:26:511697
1698 histogram_tester.ExpectUniqueSample("Net.SSL.ECHResult",
1699 2 /* kSuccessRetry */, 1);
David Benjamindc5fd6a2022-03-24 23:00:411700}
1701
Matt Menke7b5051072019-01-27 21:22:491702} // namespace
1703} // namespace net