1 // Copyright 2019 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/socket/ssl_connect_job.h"
6
7 #include <memory>
8 #include <string>
9
10 #include "base/compiler_specific.h"
11 #include "base/functional/callback.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "base/test/metrics/histogram_tester.h"
15 #include "base/test/scoped_feature_list.h"
16 #include "base/test/task_environment.h"
17 #include "base/time/time.h"
18 #include "net/base/auth.h"
19 #include "net/base/features.h"
20 #include "net/base/host_port_pair.h"
21 #include "net/base/load_timing_info.h"
22 #include "net/base/net_errors.h"
23 #include "net/base/network_anonymization_key.h"
24 #include "net/base/network_isolation_key.h"
25 #include "net/base/proxy_chain.h"
26 #include "net/base/proxy_server.h"
27 #include "net/base/proxy_string_util.h"
28 #include "net/cert/mock_cert_verifier.h"
29 #include "net/dns/mock_host_resolver.h"
30 #include "net/dns/public/secure_dns_policy.h"
31 #include "net/http/http_auth_handler_factory.h"
32 #include "net/http/http_network_session.h"
33 #include "net/http/http_proxy_connect_job.h"
34 #include "net/http/http_request_headers.h"
35 #include "net/http/http_response_headers.h"
36 #include "net/http/http_server_properties.h"
37 #include "net/http/transport_security_state.h"
38 #include "net/log/net_log_source.h"
39 #include "net/log/net_log_with_source.h"
40 #include "net/proxy_resolution/configured_proxy_resolution_service.h"
41 #include "net/quic/quic_context.h"
42 #include "net/socket/connect_job_test_util.h"
43 #include "net/socket/connection_attempts.h"
44 #include "net/socket/next_proto.h"
45 #include "net/socket/socket_tag.h"
46 #include "net/socket/socket_test_util.h"
47 #include "net/socket/socks_connect_job.h"
48 #include "net/socket/transport_connect_job.h"
49 #include "net/ssl/ssl_config_service_defaults.h"
50 #include "net/ssl/ssl_connection_status_flags.h"
51 #include "net/ssl/test_ssl_config_service.h"
52 #include "net/test/cert_test_util.h"
53 #include "net/test/gtest_util.h"
54 #include "net/test/ssl_test_util.h"
55 #include "net/test/test_certificate_data.h"
56 #include "net/test/test_data_directory.h"
57 #include "net/test/test_with_task_environment.h"
58 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
59 #include "net/url_request/static_http_user_agent_settings.h"
60 #include "testing/gtest/include/gtest/gtest.h"
61 #include "third_party/boringssl/src/include/openssl/ssl.h"
62 #include "url/gurl.h"
63 #include "url/scheme_host_port.h"
64 #include "url/url_constants.h"
65
66 namespace net {
67 namespace {
68
ParseIP(const std::string & ip)69 IPAddress ParseIP(const std::string& ip) {
70 IPAddress address;
71 CHECK(address.AssignFromIPLiteral(ip));
72 return address;
73 }
74
75 // Just check that all connect times are set to base::TimeTicks::Now(), for
76 // tests that don't update the mocked out time.
CheckConnectTimesSet(const LoadTimingInfo::ConnectTiming & connect_timing)77 void CheckConnectTimesSet(const LoadTimingInfo::ConnectTiming& connect_timing) {
78 EXPECT_EQ(base::TimeTicks::Now(), connect_timing.domain_lookup_start);
79 EXPECT_EQ(base::TimeTicks::Now(), connect_timing.domain_lookup_end);
80 EXPECT_EQ(base::TimeTicks::Now(), connect_timing.connect_start);
81 EXPECT_EQ(base::TimeTicks::Now(), connect_timing.ssl_start);
82 EXPECT_EQ(base::TimeTicks::Now(), connect_timing.ssl_end);
83 EXPECT_EQ(base::TimeTicks::Now(), connect_timing.connect_end);
84 }
85
86 // Just check that all connect times are set to base::TimeTicks::Now(), except
87 // for DNS times, for tests that don't update the mocked out time and use a
88 // proxy.
CheckConnectTimesExceptDnsSet(const LoadTimingInfo::ConnectTiming & connect_timing)89 void CheckConnectTimesExceptDnsSet(
90 const LoadTimingInfo::ConnectTiming& connect_timing) {
91 EXPECT_TRUE(connect_timing.domain_lookup_start.is_null());
92 EXPECT_TRUE(connect_timing.domain_lookup_end.is_null());
93 EXPECT_EQ(base::TimeTicks::Now(), connect_timing.connect_start);
94 EXPECT_EQ(base::TimeTicks::Now(), connect_timing.ssl_start);
95 EXPECT_EQ(base::TimeTicks::Now(), connect_timing.ssl_end);
96 EXPECT_EQ(base::TimeTicks::Now(), connect_timing.connect_end);
97 }
98
99 const url::SchemeHostPort kHostHttps{url::kHttpsScheme, "host", 443};
100 const HostPortPair kHostHttp{"host", 80};
101 const ProxyServer kSocksProxyServer{ProxyServer::SCHEME_SOCKS5,
102 HostPortPair("sockshost", 443)};
103 const ProxyServer kHttpProxyServer{ProxyServer::SCHEME_HTTP,
104 HostPortPair("proxy", 443)};
105
106 const ProxyChain kHttpProxyChain{kHttpProxyServer};
107
108 class SSLConnectJobTest : public WithTaskEnvironment, public testing::Test {
109 public:
SSLConnectJobTest()110 SSLConnectJobTest()
111 : WithTaskEnvironment(base::test::TaskEnvironment::TimeSource::MOCK_TIME),
112 proxy_resolution_service_(
113 ConfiguredProxyResolutionService::CreateDirect()),
114 ssl_config_service_(
115 std::make_unique<TestSSLConfigService>(SSLContextConfig())),
116 http_auth_handler_factory_(HttpAuthHandlerFactory::CreateDefault()),
117 session_(CreateNetworkSession()),
118 common_connect_job_params_(session_->CreateCommonConnectJobParams()) {}
119
120 ~SSLConnectJobTest() override = default;
121
CreateDirectTransportSocketParams(SecureDnsPolicy secure_dns_policy) const122 scoped_refptr<TransportSocketParams> CreateDirectTransportSocketParams(
123 SecureDnsPolicy secure_dns_policy) const {
124 return base::MakeRefCounted<TransportSocketParams>(
125 kHostHttps, NetworkAnonymizationKey(), secure_dns_policy,
126 OnHostResolutionCallback(),
127 /*supported_alpns=*/base::flat_set<std::string>({"h2", "http/1.1"}));
128 }
129
CreateProxyTransportSocketParams(SecureDnsPolicy secure_dns_policy) const130 scoped_refptr<TransportSocketParams> CreateProxyTransportSocketParams(
131 SecureDnsPolicy secure_dns_policy) const {
132 return base::MakeRefCounted<TransportSocketParams>(
133 kHttpProxyServer.host_port_pair(), NetworkAnonymizationKey(),
134 secure_dns_policy, OnHostResolutionCallback(),
135 /*supported_alpns=*/base::flat_set<std::string>({}));
136 }
137
CreateSOCKSSocketParams(SecureDnsPolicy secure_dns_policy)138 scoped_refptr<SOCKSSocketParams> CreateSOCKSSocketParams(
139 SecureDnsPolicy secure_dns_policy) {
140 return base::MakeRefCounted<SOCKSSocketParams>(
141 ConnectJobParams(CreateProxyTransportSocketParams(secure_dns_policy)),
142 kSocksProxyServer.scheme() == ProxyServer::SCHEME_SOCKS5,
143 kSocksProxyServer.host_port_pair(), NetworkAnonymizationKey(),
144 TRAFFIC_ANNOTATION_FOR_TESTS);
145 }
146
CreateHttpProxySocketParams(SecureDnsPolicy secure_dns_policy)147 scoped_refptr<HttpProxySocketParams> CreateHttpProxySocketParams(
148 SecureDnsPolicy secure_dns_policy) {
149 return base::MakeRefCounted<HttpProxySocketParams>(
150 ConnectJobParams(CreateProxyTransportSocketParams(secure_dns_policy)),
151 kHostHttp, kHttpProxyChain,
152 /*proxy_server_index=*/0,
153 /*tunnel=*/true, TRAFFIC_ANNOTATION_FOR_TESTS,
154 NetworkAnonymizationKey(), secure_dns_policy);
155 }
156
CreateConnectJob(TestConnectJobDelegate * test_delegate,ProxyChain proxy_chain=ProxyChain::Direct (),RequestPriority priority=DEFAULT_PRIORITY,SecureDnsPolicy secure_dns_policy=SecureDnsPolicy::kAllow)157 std::unique_ptr<ConnectJob> CreateConnectJob(
158 TestConnectJobDelegate* test_delegate,
159 ProxyChain proxy_chain = ProxyChain::Direct(),
160 RequestPriority priority = DEFAULT_PRIORITY,
161 SecureDnsPolicy secure_dns_policy = SecureDnsPolicy::kAllow) {
162 return std::make_unique<SSLConnectJob>(
163 priority, SocketTag(), &common_connect_job_params_,
164 CreateSSLSocketParams(proxy_chain, secure_dns_policy), test_delegate,
165 /*net_log=*/nullptr);
166 }
167
CreateSSLSocketParams(ProxyChain proxy_chain,SecureDnsPolicy secure_dns_policy)168 scoped_refptr<SSLSocketParams> CreateSSLSocketParams(
169 ProxyChain proxy_chain,
170 SecureDnsPolicy secure_dns_policy) {
171 return base::MakeRefCounted<SSLSocketParams>(
172 proxy_chain == ProxyChain::Direct()
173 ? ConnectJobParams(
174 CreateDirectTransportSocketParams(secure_dns_policy))
175 : proxy_chain.is_single_proxy() &&
176 proxy_chain.First().scheme() == ProxyServer::SCHEME_SOCKS5
177 ? ConnectJobParams(CreateSOCKSSocketParams(secure_dns_policy))
178 : proxy_chain.is_single_proxy() &&
179 proxy_chain.First().scheme() == ProxyServer::SCHEME_HTTP
180 ? ConnectJobParams(CreateHttpProxySocketParams(secure_dns_policy))
181 : ConnectJobParams(),
182 HostPortPair::FromSchemeHostPort(kHostHttps), SSLConfig(),
183 NetworkAnonymizationKey());
184 }
185
AddAuthToCache()186 void AddAuthToCache() {
187 const std::u16string kFoo(u"foo");
188 const std::u16string kBar(u"bar");
189 session_->http_auth_cache()->Add(
190 url::SchemeHostPort(GURL("http://proxy:443/")), HttpAuth::AUTH_PROXY,
191 "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
192 "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");
193 }
194
CreateNetworkSession()195 std::unique_ptr<HttpNetworkSession> CreateNetworkSession() {
196 HttpNetworkSessionContext session_context;
197 session_context.host_resolver = &host_resolver_;
198 session_context.cert_verifier = &cert_verifier_;
199 session_context.transport_security_state = &transport_security_state_;
200 session_context.proxy_resolution_service = proxy_resolution_service_.get();
201 session_context.client_socket_factory = &socket_factory_;
202 session_context.ssl_config_service = ssl_config_service_.get();
203 session_context.http_auth_handler_factory =
204 http_auth_handler_factory_.get();
205 session_context.http_server_properties = &http_server_properties_;
206 session_context.http_user_agent_settings = &http_user_agent_settings_;
207 session_context.quic_context = &quic_context_;
208 return std::make_unique<HttpNetworkSession>(HttpNetworkSessionParams(),
209 session_context);
210 }
211
212 protected:
213 MockClientSocketFactory socket_factory_;
214 MockHostResolver host_resolver_{/*default_result=*/MockHostResolverBase::
215 RuleResolver::GetLocalhostResult()};
216 MockCertVerifier cert_verifier_;
217 TransportSecurityState transport_security_state_;
218 const std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
219 const std::unique_ptr<TestSSLConfigService> ssl_config_service_;
220 const std::unique_ptr<HttpAuthHandlerFactory> http_auth_handler_factory_;
221 const StaticHttpUserAgentSettings http_user_agent_settings_ = {"*",
222 "test-ua"};
223 HttpServerProperties http_server_properties_;
224 QuicContext quic_context_;
225 const std::unique_ptr<HttpNetworkSession> session_;
226
227 const CommonConnectJobParams common_connect_job_params_;
228 };
229
TEST_F(SSLConnectJobTest,TCPFail)230 TEST_F(SSLConnectJobTest, TCPFail) {
231 for (IoMode io_mode : {SYNCHRONOUS, ASYNC}) {
232 SCOPED_TRACE(io_mode);
233 host_resolver_.set_synchronous_mode(io_mode == SYNCHRONOUS);
234 StaticSocketDataProvider data;
235 data.set_connect_data(MockConnect(io_mode, ERR_CONNECTION_FAILED));
236 socket_factory_.AddSocketDataProvider(&data);
237
238 TestConnectJobDelegate test_delegate;
239 std::unique_ptr<ConnectJob> ssl_connect_job =
240 CreateConnectJob(&test_delegate);
241 test_delegate.StartJobExpectingResult(
242 ssl_connect_job.get(), ERR_CONNECTION_FAILED, io_mode == SYNCHRONOUS);
243 EXPECT_FALSE(test_delegate.socket());
244 EXPECT_FALSE(ssl_connect_job->IsSSLError());
245 ConnectionAttempts connection_attempts =
246 ssl_connect_job->GetConnectionAttempts();
247 ASSERT_EQ(1u, connection_attempts.size());
248 EXPECT_THAT(connection_attempts[0].result,
249 test::IsError(ERR_CONNECTION_FAILED));
250 }
251 }
252
TEST_F(SSLConnectJobTest,TCPTimeout)253 TEST_F(SSLConnectJobTest, TCPTimeout) {
254 const base::TimeDelta kTinyTime = base::Microseconds(1);
255
256 // Make request hang.
257 host_resolver_.set_ondemand_mode(true);
258
259 TestConnectJobDelegate test_delegate;
260 std::unique_ptr<ConnectJob> ssl_connect_job =
261 CreateConnectJob(&test_delegate);
262 ASSERT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
263
264 // Right up until just before the TCP connection timeout, the job does not
265 // time out.
266 FastForwardBy(TransportConnectJob::ConnectionTimeout() - kTinyTime);
267 EXPECT_FALSE(test_delegate.has_result());
268
269 // But at the exact time of TCP connection timeout, the job fails.
270 FastForwardBy(kTinyTime);
271 EXPECT_TRUE(test_delegate.has_result());
272 EXPECT_THAT(test_delegate.WaitForResult(), test::IsError(ERR_TIMED_OUT));
273 }
274
TEST_F(SSLConnectJobTest,SSLTimeoutSyncConnect)275 TEST_F(SSLConnectJobTest, SSLTimeoutSyncConnect) {
276 const base::TimeDelta kTinyTime = base::Microseconds(1);
277
278 // DNS lookup and transport connect complete synchronously, but SSL
279 // negotiation hangs.
280 host_resolver_.set_synchronous_mode(true);
281 StaticSocketDataProvider data;
282 data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
283 socket_factory_.AddSocketDataProvider(&data);
284 SSLSocketDataProvider ssl(SYNCHRONOUS, ERR_IO_PENDING);
285 socket_factory_.AddSSLSocketDataProvider(&ssl);
286
287 // Make request hang.
288 TestConnectJobDelegate test_delegate;
289 std::unique_ptr<ConnectJob> ssl_connect_job =
290 CreateConnectJob(&test_delegate);
291 ASSERT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
292
293 // Right up until just before the SSL handshake timeout, the job does not time
294 // out.
295 FastForwardBy(SSLConnectJob::HandshakeTimeoutForTesting() - kTinyTime);
296 EXPECT_FALSE(test_delegate.has_result());
297
298 // But at the exact SSL handshake timeout time, the job fails.
299 FastForwardBy(kTinyTime);
300 EXPECT_TRUE(test_delegate.has_result());
301 EXPECT_THAT(test_delegate.WaitForResult(), test::IsError(ERR_TIMED_OUT));
302 }
303
TEST_F(SSLConnectJobTest,SSLTimeoutAsyncTcpConnect)304 TEST_F(SSLConnectJobTest, SSLTimeoutAsyncTcpConnect) {
305 const base::TimeDelta kTinyTime = base::Microseconds(1);
306
307 // DNS lookup is asynchronous, and later SSL negotiation hangs.
308 host_resolver_.set_ondemand_mode(true);
309 StaticSocketDataProvider data;
310 data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
311 socket_factory_.AddSocketDataProvider(&data);
312 SSLSocketDataProvider ssl(SYNCHRONOUS, ERR_IO_PENDING);
313 socket_factory_.AddSSLSocketDataProvider(&ssl);
314
315 TestConnectJobDelegate test_delegate;
316 std::unique_ptr<ConnectJob> ssl_connect_job =
317 CreateConnectJob(&test_delegate);
318 // Connecting should hand on the TransportConnectJob connect.
319 ASSERT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
320
321 // Right up until just before the TCP connection timeout, the job does not
322 // time out.
323 FastForwardBy(TransportConnectJob::ConnectionTimeout() - kTinyTime);
324 EXPECT_FALSE(test_delegate.has_result());
325
326 // The DNS lookup completes, and a TCP connection is immediately establshed,
327 // which cancels the TCP connection timer. The SSL handshake timer is started,
328 // and the SSL handshake hangs.
329 host_resolver_.ResolveOnlyRequestNow();
330 EXPECT_FALSE(test_delegate.has_result());
331
332 // Right up until just before the SSL handshake timeout, the job does not time
333 // out.
334 FastForwardBy(SSLConnectJob::HandshakeTimeoutForTesting() - kTinyTime);
335 EXPECT_FALSE(test_delegate.has_result());
336
337 // But at the exact SSL handshake timeout time, the job fails.
338 FastForwardBy(kTinyTime);
339 EXPECT_TRUE(test_delegate.has_result());
340 EXPECT_THAT(test_delegate.WaitForResult(), test::IsError(ERR_TIMED_OUT));
341 }
342
TEST_F(SSLConnectJobTest,BasicDirectSync)343 TEST_F(SSLConnectJobTest, BasicDirectSync) {
344 host_resolver_.set_synchronous_mode(true);
345 StaticSocketDataProvider data;
346 data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
347 socket_factory_.AddSocketDataProvider(&data);
348 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
349 socket_factory_.AddSSLSocketDataProvider(&ssl);
350
351 TestConnectJobDelegate test_delegate;
352 std::unique_ptr<ConnectJob> ssl_connect_job =
353 CreateConnectJob(&test_delegate, ProxyChain::Direct(), MEDIUM);
354
355 test_delegate.StartJobExpectingResult(ssl_connect_job.get(), OK,
356 true /* expect_sync_result */);
357 EXPECT_EQ(MEDIUM, host_resolver_.last_request_priority());
358
359 ConnectionAttempts connection_attempts =
360 ssl_connect_job->GetConnectionAttempts();
361 EXPECT_EQ(0u, connection_attempts.size());
362 CheckConnectTimesSet(ssl_connect_job->connect_timing());
363 }
364
TEST_F(SSLConnectJobTest,BasicDirectAsync)365 TEST_F(SSLConnectJobTest, BasicDirectAsync) {
366 host_resolver_.set_ondemand_mode(true);
367 base::TimeTicks start_time = base::TimeTicks::Now();
368 StaticSocketDataProvider data;
369 data.set_connect_data(MockConnect(ASYNC, OK));
370 socket_factory_.AddSocketDataProvider(&data);
371 SSLSocketDataProvider ssl(ASYNC, OK);
372 socket_factory_.AddSSLSocketDataProvider(&ssl);
373
374 TestConnectJobDelegate test_delegate;
375 std::unique_ptr<ConnectJob> ssl_connect_job =
376 CreateConnectJob(&test_delegate, ProxyChain::Direct(), MEDIUM);
377 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
378 EXPECT_TRUE(host_resolver_.has_pending_requests());
379 EXPECT_EQ(MEDIUM, host_resolver_.last_request_priority());
380 FastForwardBy(base::Seconds(5));
381
382 base::TimeTicks resolve_complete_time = base::TimeTicks::Now();
383 host_resolver_.ResolveAllPending();
384 EXPECT_THAT(test_delegate.WaitForResult(), test::IsOk());
385
386 ConnectionAttempts connection_attempts =
387 ssl_connect_job->GetConnectionAttempts();
388 EXPECT_EQ(0u, connection_attempts.size());
389
390 // Check times. Since time is mocked out, all times will be the same, except
391 // |dns_start|, which is the only one recorded before the FastForwardBy()
392 // call. The test classes don't allow any other phases to be triggered on
393 // demand, or delayed by a set interval.
394 EXPECT_EQ(start_time, ssl_connect_job->connect_timing().domain_lookup_start);
395 EXPECT_EQ(resolve_complete_time,
396 ssl_connect_job->connect_timing().domain_lookup_end);
397 EXPECT_EQ(resolve_complete_time,
398 ssl_connect_job->connect_timing().connect_start);
399 EXPECT_EQ(resolve_complete_time, ssl_connect_job->connect_timing().ssl_start);
400 EXPECT_EQ(resolve_complete_time, ssl_connect_job->connect_timing().ssl_end);
401 EXPECT_EQ(resolve_complete_time,
402 ssl_connect_job->connect_timing().connect_end);
403 }
404
TEST_F(SSLConnectJobTest,DirectHasEstablishedConnection)405 TEST_F(SSLConnectJobTest, DirectHasEstablishedConnection) {
406 host_resolver_.set_ondemand_mode(true);
407 StaticSocketDataProvider data;
408 data.set_connect_data(MockConnect(ASYNC, OK));
409 socket_factory_.AddSocketDataProvider(&data);
410
411 // SSL negotiation hangs. Value returned after SSL negotiation is complete
412 // doesn't matter, as HasEstablishedConnection() may only be used between job
413 // start and job complete.
414 SSLSocketDataProvider ssl(SYNCHRONOUS, ERR_IO_PENDING);
415 socket_factory_.AddSSLSocketDataProvider(&ssl);
416
417 TestConnectJobDelegate test_delegate;
418 std::unique_ptr<ConnectJob> ssl_connect_job =
419 CreateConnectJob(&test_delegate, ProxyChain::Direct(), MEDIUM);
420 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
421 EXPECT_TRUE(host_resolver_.has_pending_requests());
422 EXPECT_EQ(LOAD_STATE_RESOLVING_HOST, ssl_connect_job->GetLoadState());
423 EXPECT_FALSE(ssl_connect_job->HasEstablishedConnection());
424
425 // DNS resolution completes, and then the ConnectJob tries to connect the
426 // socket, which should succeed asynchronously.
427 host_resolver_.ResolveNow(1);
428 EXPECT_EQ(LOAD_STATE_CONNECTING, ssl_connect_job->GetLoadState());
429 EXPECT_FALSE(ssl_connect_job->HasEstablishedConnection());
430
431 // Spinning the message loop causes the socket to finish connecting. The SSL
432 // handshake should start and hang.
433 base::RunLoop().RunUntilIdle();
434 EXPECT_FALSE(test_delegate.has_result());
435 EXPECT_EQ(LOAD_STATE_SSL_HANDSHAKE, ssl_connect_job->GetLoadState());
436 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
437 }
438
TEST_F(SSLConnectJobTest,RequestPriority)439 TEST_F(SSLConnectJobTest, RequestPriority) {
440 host_resolver_.set_ondemand_mode(true);
441 for (int initial_priority = MINIMUM_PRIORITY;
442 initial_priority <= MAXIMUM_PRIORITY; ++initial_priority) {
443 SCOPED_TRACE(initial_priority);
444 for (int new_priority = MINIMUM_PRIORITY; new_priority <= MAXIMUM_PRIORITY;
445 ++new_priority) {
446 SCOPED_TRACE(new_priority);
447 if (initial_priority == new_priority) {
448 continue;
449 }
450 TestConnectJobDelegate test_delegate;
451 std::unique_ptr<ConnectJob> ssl_connect_job =
452 CreateConnectJob(&test_delegate, ProxyChain::Direct(),
453 static_cast<RequestPriority>(initial_priority));
454 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
455 EXPECT_TRUE(host_resolver_.has_pending_requests());
456 int request_id = host_resolver_.num_resolve();
457 EXPECT_EQ(initial_priority, host_resolver_.request_priority(request_id));
458
459 ssl_connect_job->ChangePriority(
460 static_cast<RequestPriority>(new_priority));
461 EXPECT_EQ(new_priority, host_resolver_.request_priority(request_id));
462
463 ssl_connect_job->ChangePriority(
464 static_cast<RequestPriority>(initial_priority));
465 EXPECT_EQ(initial_priority, host_resolver_.request_priority(request_id));
466 }
467 }
468 }
469
TEST_F(SSLConnectJobTest,SecureDnsPolicy)470 TEST_F(SSLConnectJobTest, SecureDnsPolicy) {
471 for (auto secure_dns_policy :
472 {SecureDnsPolicy::kAllow, SecureDnsPolicy::kDisable}) {
473 TestConnectJobDelegate test_delegate;
474 std::unique_ptr<ConnectJob> ssl_connect_job =
475 CreateConnectJob(&test_delegate, ProxyChain::Direct(), DEFAULT_PRIORITY,
476 secure_dns_policy);
477
478 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
479 EXPECT_EQ(secure_dns_policy, host_resolver_.last_secure_dns_policy());
480 }
481 }
482
TEST_F(SSLConnectJobTest,DirectHostResolutionFailure)483 TEST_F(SSLConnectJobTest, DirectHostResolutionFailure) {
484 host_resolver_.rules()->AddSimulatedTimeoutFailure("host");
485
486 TestConnectJobDelegate test_delegate;
487 std::unique_ptr<ConnectJob> ssl_connect_job =
488 CreateConnectJob(&test_delegate, ProxyChain::Direct());
489 test_delegate.StartJobExpectingResult(ssl_connect_job.get(),
490 ERR_NAME_NOT_RESOLVED,
491 false /* expect_sync_result */);
492 EXPECT_THAT(ssl_connect_job->GetResolveErrorInfo().error,
493 test::IsError(ERR_DNS_TIMED_OUT));
494 }
495
TEST_F(SSLConnectJobTest,DirectCertError)496 TEST_F(SSLConnectJobTest, DirectCertError) {
497 StaticSocketDataProvider data;
498 socket_factory_.AddSocketDataProvider(&data);
499 SSLSocketDataProvider ssl(ASYNC, ERR_CERT_COMMON_NAME_INVALID);
500 socket_factory_.AddSSLSocketDataProvider(&ssl);
501
502 TestConnectJobDelegate test_delegate(
503 TestConnectJobDelegate::SocketExpected::ALWAYS);
504 std::unique_ptr<ConnectJob> ssl_connect_job =
505 CreateConnectJob(&test_delegate);
506
507 test_delegate.StartJobExpectingResult(ssl_connect_job.get(),
508 ERR_CERT_COMMON_NAME_INVALID,
509 false /* expect_sync_result */);
510 EXPECT_TRUE(ssl_connect_job->IsSSLError());
511 ConnectionAttempts connection_attempts =
512 ssl_connect_job->GetConnectionAttempts();
513 ASSERT_EQ(1u, connection_attempts.size());
514 EXPECT_THAT(connection_attempts[0].result,
515 test::IsError(ERR_CERT_COMMON_NAME_INVALID));
516 CheckConnectTimesSet(ssl_connect_job->connect_timing());
517 }
518
TEST_F(SSLConnectJobTest,DirectIgnoreCertErrors)519 TEST_F(SSLConnectJobTest, DirectIgnoreCertErrors) {
520 session_->IgnoreCertificateErrorsForTesting();
521
522 StaticSocketDataProvider data;
523 socket_factory_.AddSocketDataProvider(&data);
524 SSLSocketDataProvider ssl(ASYNC, OK);
525 ssl.expected_ignore_certificate_errors = true;
526 socket_factory_.AddSSLSocketDataProvider(&ssl);
527
528 TestConnectJobDelegate test_delegate(
529 TestConnectJobDelegate::SocketExpected::ALWAYS);
530 std::unique_ptr<ConnectJob> ssl_connect_job =
531 CreateConnectJob(&test_delegate);
532
533 test_delegate.StartJobExpectingResult(ssl_connect_job.get(), OK,
534 /*expect_sync_result=*/false);
535 }
536
TEST_F(SSLConnectJobTest,DirectSSLError)537 TEST_F(SSLConnectJobTest, DirectSSLError) {
538 StaticSocketDataProvider data;
539 socket_factory_.AddSocketDataProvider(&data);
540 SSLSocketDataProvider ssl(ASYNC, ERR_BAD_SSL_CLIENT_AUTH_CERT);
541 socket_factory_.AddSSLSocketDataProvider(&ssl);
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(),
548 ERR_BAD_SSL_CLIENT_AUTH_CERT,
549 false /* expect_sync_result */);
550 ConnectionAttempts connection_attempts =
551 ssl_connect_job->GetConnectionAttempts();
552 ASSERT_EQ(1u, connection_attempts.size());
553 EXPECT_THAT(connection_attempts[0].result,
554 test::IsError(ERR_BAD_SSL_CLIENT_AUTH_CERT));
555 }
556
TEST_F(SSLConnectJobTest,DirectWithNPN)557 TEST_F(SSLConnectJobTest, DirectWithNPN) {
558 StaticSocketDataProvider data;
559 socket_factory_.AddSocketDataProvider(&data);
560 SSLSocketDataProvider ssl(ASYNC, OK);
561 ssl.next_proto = kProtoHTTP11;
562 socket_factory_.AddSSLSocketDataProvider(&ssl);
563
564 TestConnectJobDelegate test_delegate;
565 std::unique_ptr<ConnectJob> ssl_connect_job =
566 CreateConnectJob(&test_delegate);
567
568 test_delegate.StartJobExpectingResult(ssl_connect_job.get(), OK,
569 false /* expect_sync_result */);
570 CheckConnectTimesSet(ssl_connect_job->connect_timing());
571 }
572
TEST_F(SSLConnectJobTest,DirectGotHTTP2)573 TEST_F(SSLConnectJobTest, DirectGotHTTP2) {
574 StaticSocketDataProvider data;
575 socket_factory_.AddSocketDataProvider(&data);
576 SSLSocketDataProvider ssl(ASYNC, OK);
577 ssl.next_proto = kProtoHTTP2;
578 socket_factory_.AddSSLSocketDataProvider(&ssl);
579
580 TestConnectJobDelegate test_delegate;
581 std::unique_ptr<ConnectJob> ssl_connect_job =
582 CreateConnectJob(&test_delegate);
583
584 test_delegate.StartJobExpectingResult(ssl_connect_job.get(), OK,
585 false /* expect_sync_result */);
586 EXPECT_EQ(kProtoHTTP2, test_delegate.socket()->GetNegotiatedProtocol());
587 CheckConnectTimesSet(ssl_connect_job->connect_timing());
588 }
589
TEST_F(SSLConnectJobTest,SOCKSFail)590 TEST_F(SSLConnectJobTest, SOCKSFail) {
591 for (IoMode io_mode : {SYNCHRONOUS, ASYNC}) {
592 SCOPED_TRACE(io_mode);
593 host_resolver_.set_synchronous_mode(io_mode == SYNCHRONOUS);
594 StaticSocketDataProvider data;
595 data.set_connect_data(MockConnect(io_mode, ERR_CONNECTION_FAILED));
596 socket_factory_.AddSocketDataProvider(&data);
597
598 TestConnectJobDelegate test_delegate;
599 std::unique_ptr<ConnectJob> ssl_connect_job = CreateConnectJob(
600 &test_delegate, PacResultElementToProxyChain("SOCKS5 foo:333"));
601 test_delegate.StartJobExpectingResult(ssl_connect_job.get(),
602 ERR_PROXY_CONNECTION_FAILED,
603 io_mode == SYNCHRONOUS);
604 EXPECT_FALSE(ssl_connect_job->IsSSLError());
605
606 ConnectionAttempts connection_attempts =
607 ssl_connect_job->GetConnectionAttempts();
608 EXPECT_EQ(0u, connection_attempts.size());
609 }
610 }
611
TEST_F(SSLConnectJobTest,SOCKSHostResolutionFailure)612 TEST_F(SSLConnectJobTest, SOCKSHostResolutionFailure) {
613 host_resolver_.rules()->AddSimulatedTimeoutFailure("proxy");
614
615 TestConnectJobDelegate test_delegate;
616 std::unique_ptr<ConnectJob> ssl_connect_job = CreateConnectJob(
617 &test_delegate, PacResultElementToProxyChain("SOCKS5 foo:333"));
618 test_delegate.StartJobExpectingResult(ssl_connect_job.get(),
619 ERR_PROXY_CONNECTION_FAILED,
620 false /* expect_sync_result */);
621 EXPECT_THAT(ssl_connect_job->GetResolveErrorInfo().error,
622 test::IsError(ERR_DNS_TIMED_OUT));
623 }
624
TEST_F(SSLConnectJobTest,SOCKSBasic)625 TEST_F(SSLConnectJobTest, SOCKSBasic) {
626 for (IoMode io_mode : {SYNCHRONOUS, ASYNC}) {
627 SCOPED_TRACE(io_mode);
628 const uint8_t kSOCKS5Request[] = {0x05, 0x01, 0x00, 0x03, 0x09, 's',
629 'o', 'c', 'k', 's', 'h', 'o',
630 's', 't', 0x01, 0xBB};
631
632 MockWrite writes[] = {
633 MockWrite(io_mode, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength),
634 MockWrite(io_mode, reinterpret_cast<const char*>(kSOCKS5Request),
635 std::size(kSOCKS5Request)),
636 };
637
638 MockRead reads[] = {
639 MockRead(io_mode, kSOCKS5GreetResponse, kSOCKS5GreetResponseLength),
640 MockRead(io_mode, kSOCKS5OkResponse, kSOCKS5OkResponseLength),
641 };
642
643 host_resolver_.set_synchronous_mode(io_mode == SYNCHRONOUS);
644 StaticSocketDataProvider data(reads, writes);
645 data.set_connect_data(MockConnect(io_mode, OK));
646 socket_factory_.AddSocketDataProvider(&data);
647 SSLSocketDataProvider ssl(io_mode, OK);
648 socket_factory_.AddSSLSocketDataProvider(&ssl);
649
650 TestConnectJobDelegate test_delegate;
651 std::unique_ptr<ConnectJob> ssl_connect_job = CreateConnectJob(
652 &test_delegate, PacResultElementToProxyChain("SOCKS5 foo:333"));
653 test_delegate.StartJobExpectingResult(ssl_connect_job.get(), OK,
654 io_mode == SYNCHRONOUS);
655 CheckConnectTimesExceptDnsSet(ssl_connect_job->connect_timing());
656
657 // Proxies should not set any DNS aliases.
658 EXPECT_TRUE(test_delegate.socket()->GetDnsAliases().empty());
659 }
660 }
661
TEST_F(SSLConnectJobTest,SOCKSHasEstablishedConnection)662 TEST_F(SSLConnectJobTest, SOCKSHasEstablishedConnection) {
663 const uint8_t kSOCKS5Request[] = {0x05, 0x01, 0x00, 0x03, 0x09, 's',
664 'o', 'c', 'k', 's', 'h', 'o',
665 's', 't', 0x01, 0xBB};
666
667 MockWrite writes[] = {
668 MockWrite(SYNCHRONOUS, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength, 0),
669 MockWrite(SYNCHRONOUS, reinterpret_cast<const char*>(kSOCKS5Request),
670 std::size(kSOCKS5Request), 3),
671 };
672
673 MockRead reads[] = {
674 // Pause so can probe current state.
675 MockRead(ASYNC, ERR_IO_PENDING, 1),
676 MockRead(ASYNC, kSOCKS5GreetResponse, kSOCKS5GreetResponseLength, 2),
677 MockRead(SYNCHRONOUS, kSOCKS5OkResponse, kSOCKS5OkResponseLength, 4),
678 };
679
680 host_resolver_.set_ondemand_mode(true);
681 SequencedSocketData data(reads, writes);
682 data.set_connect_data(MockConnect(ASYNC, OK));
683 socket_factory_.AddSocketDataProvider(&data);
684
685 // SSL negotiation hangs. Value returned after SSL negotiation is complete
686 // doesn't matter, as HasEstablishedConnection() may only be used between job
687 // start and job complete.
688 SSLSocketDataProvider ssl(SYNCHRONOUS, ERR_IO_PENDING);
689 socket_factory_.AddSSLSocketDataProvider(&ssl);
690
691 TestConnectJobDelegate test_delegate;
692 std::unique_ptr<ConnectJob> ssl_connect_job = CreateConnectJob(
693 &test_delegate, PacResultElementToProxyChain("SOCKS5 foo:333"));
694 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
695 EXPECT_TRUE(host_resolver_.has_pending_requests());
696 EXPECT_EQ(LOAD_STATE_RESOLVING_HOST, ssl_connect_job->GetLoadState());
697 EXPECT_FALSE(ssl_connect_job->HasEstablishedConnection());
698
699 // DNS resolution completes, and then the ConnectJob tries to connect the
700 // socket, which should succeed asynchronously.
701 host_resolver_.ResolveNow(1);
702 EXPECT_EQ(LOAD_STATE_CONNECTING, ssl_connect_job->GetLoadState());
703 EXPECT_FALSE(ssl_connect_job->HasEstablishedConnection());
704
705 // Spin the message loop until the first read of the handshake.
706 // HasEstablishedConnection() should return true, as a TCP connection has been
707 // successfully established by this point.
708 data.RunUntilPaused();
709 EXPECT_FALSE(test_delegate.has_result());
710 EXPECT_EQ(LOAD_STATE_CONNECTING, ssl_connect_job->GetLoadState());
711 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
712
713 // Finish up the handshake, and spin the message loop until the SSL handshake
714 // starts and hang.
715 data.Resume();
716 base::RunLoop().RunUntilIdle();
717 EXPECT_FALSE(test_delegate.has_result());
718 EXPECT_EQ(LOAD_STATE_SSL_HANDSHAKE, ssl_connect_job->GetLoadState());
719 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
720 }
721
TEST_F(SSLConnectJobTest,SOCKSRequestPriority)722 TEST_F(SSLConnectJobTest, SOCKSRequestPriority) {
723 host_resolver_.set_ondemand_mode(true);
724 for (int initial_priority = MINIMUM_PRIORITY;
725 initial_priority <= MAXIMUM_PRIORITY; ++initial_priority) {
726 SCOPED_TRACE(initial_priority);
727 for (int new_priority = MINIMUM_PRIORITY; new_priority <= MAXIMUM_PRIORITY;
728 ++new_priority) {
729 SCOPED_TRACE(new_priority);
730 if (initial_priority == new_priority) {
731 continue;
732 }
733 TestConnectJobDelegate test_delegate;
734 std::unique_ptr<ConnectJob> ssl_connect_job = CreateConnectJob(
735 &test_delegate, PacResultElementToProxyChain("SOCKS5 foo:333"),
736 static_cast<RequestPriority>(initial_priority));
737 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
738 EXPECT_TRUE(host_resolver_.has_pending_requests());
739 int request_id = host_resolver_.num_resolve();
740 EXPECT_EQ(initial_priority, host_resolver_.request_priority(request_id));
741
742 ssl_connect_job->ChangePriority(
743 static_cast<RequestPriority>(new_priority));
744 EXPECT_EQ(new_priority, host_resolver_.request_priority(request_id));
745
746 ssl_connect_job->ChangePriority(
747 static_cast<RequestPriority>(initial_priority));
748 EXPECT_EQ(initial_priority, host_resolver_.request_priority(request_id));
749 }
750 }
751 }
752
TEST_F(SSLConnectJobTest,HttpProxyFail)753 TEST_F(SSLConnectJobTest, HttpProxyFail) {
754 for (IoMode io_mode : {SYNCHRONOUS, ASYNC}) {
755 SCOPED_TRACE(io_mode);
756 host_resolver_.set_synchronous_mode(io_mode == SYNCHRONOUS);
757 StaticSocketDataProvider data;
758 data.set_connect_data(MockConnect(io_mode, ERR_CONNECTION_FAILED));
759 socket_factory_.AddSocketDataProvider(&data);
760
761 TestConnectJobDelegate test_delegate;
762 std::unique_ptr<ConnectJob> ssl_connect_job = CreateConnectJob(
763 &test_delegate, PacResultElementToProxyChain("PROXY foo:444"));
764 test_delegate.StartJobExpectingResult(ssl_connect_job.get(),
765 ERR_PROXY_CONNECTION_FAILED,
766 io_mode == SYNCHRONOUS);
767
768 EXPECT_FALSE(ssl_connect_job->IsSSLError());
769 ConnectionAttempts connection_attempts =
770 ssl_connect_job->GetConnectionAttempts();
771 EXPECT_EQ(0u, connection_attempts.size());
772 }
773 }
774
TEST_F(SSLConnectJobTest,HttpProxyHostResolutionFailure)775 TEST_F(SSLConnectJobTest, HttpProxyHostResolutionFailure) {
776 host_resolver_.rules()->AddSimulatedTimeoutFailure("proxy");
777
778 TestConnectJobDelegate test_delegate;
779 std::unique_ptr<ConnectJob> ssl_connect_job = CreateConnectJob(
780 &test_delegate, PacResultElementToProxyChain("PROXY foo:444"));
781 test_delegate.StartJobExpectingResult(ssl_connect_job.get(),
782 ERR_PROXY_CONNECTION_FAILED,
783 false /* expect_sync_result */);
784 EXPECT_THAT(ssl_connect_job->GetResolveErrorInfo().error,
785 test::IsError(ERR_DNS_TIMED_OUT));
786 }
787
TEST_F(SSLConnectJobTest,HttpProxyAuthChallenge)788 TEST_F(SSLConnectJobTest, HttpProxyAuthChallenge) {
789 MockWrite writes[] = {
790 MockWrite(ASYNC, 0,
791 "CONNECT host:80 HTTP/1.1\r\n"
792 "Host: host:80\r\n"
793 "Proxy-Connection: keep-alive\r\n"
794 "User-Agent: test-ua\r\n\r\n"),
795 MockWrite(ASYNC, 5,
796 "CONNECT host:80 HTTP/1.1\r\n"
797 "Host: host:80\r\n"
798 "Proxy-Connection: keep-alive\r\n"
799 "User-Agent: test-ua\r\n"
800 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
801 };
802 MockRead reads[] = {
803 MockRead(ASYNC, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"),
804 MockRead(ASYNC, 2, "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
805 MockRead(ASYNC, 3, "Content-Length: 10\r\n\r\n"),
806 MockRead(ASYNC, 4, "0123456789"),
807 MockRead(ASYNC, 6, "HTTP/1.1 200 Connection Established\r\n\r\n"),
808 };
809 StaticSocketDataProvider data(reads, writes);
810 socket_factory_.AddSocketDataProvider(&data);
811 SSLSocketDataProvider ssl(ASYNC, OK);
812 socket_factory_.AddSSLSocketDataProvider(&ssl);
813
814 TestConnectJobDelegate test_delegate;
815 std::unique_ptr<ConnectJob> ssl_connect_job = CreateConnectJob(
816 &test_delegate, PacResultElementToProxyChain("PROXY foo:444"));
817 ASSERT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
818 test_delegate.WaitForAuthChallenge(1);
819
820 EXPECT_EQ(407, test_delegate.auth_response_info().headers->response_code());
821 std::string proxy_authenticate;
822 ASSERT_TRUE(test_delegate.auth_response_info().headers->EnumerateHeader(
823 nullptr, "Proxy-Authenticate", &proxy_authenticate));
824 EXPECT_EQ(proxy_authenticate, "Basic realm=\"MyRealm1\"");
825
826 // While waiting for auth credentials to be provided, the Job should not time
827 // out.
828 FastForwardBy(base::Days(1));
829 test_delegate.WaitForAuthChallenge(1);
830 EXPECT_FALSE(test_delegate.has_result());
831
832 // Respond to challenge.
833 test_delegate.auth_controller()->ResetAuth(AuthCredentials(u"foo", u"bar"));
834 test_delegate.RunAuthCallback();
835
836 EXPECT_THAT(test_delegate.WaitForResult(), test::IsOk());
837
838 // Proxies should not set any DNS aliases.
839 EXPECT_TRUE(test_delegate.socket()->GetDnsAliases().empty());
840 }
841
TEST_F(SSLConnectJobTest,HttpProxyAuthWithCachedCredentials)842 TEST_F(SSLConnectJobTest, HttpProxyAuthWithCachedCredentials) {
843 for (IoMode io_mode : {SYNCHRONOUS, ASYNC}) {
844 SCOPED_TRACE(io_mode);
845 host_resolver_.set_synchronous_mode(io_mode == SYNCHRONOUS);
846 MockWrite writes[] = {
847 MockWrite(io_mode,
848 "CONNECT host:80 HTTP/1.1\r\n"
849 "Host: host:80\r\n"
850 "Proxy-Connection: keep-alive\r\n"
851 "User-Agent: test-ua\r\n"
852 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
853 };
854 MockRead reads[] = {
855 MockRead(io_mode, "HTTP/1.1 200 Connection Established\r\n\r\n"),
856 };
857 StaticSocketDataProvider data(reads, writes);
858 data.set_connect_data(MockConnect(io_mode, OK));
859 socket_factory_.AddSocketDataProvider(&data);
860 AddAuthToCache();
861 SSLSocketDataProvider ssl(io_mode, OK);
862 socket_factory_.AddSSLSocketDataProvider(&ssl);
863
864 TestConnectJobDelegate test_delegate;
865 std::unique_ptr<ConnectJob> ssl_connect_job = CreateConnectJob(
866 &test_delegate, PacResultElementToProxyChain("PROXY foo:444"));
867 test_delegate.StartJobExpectingResult(ssl_connect_job.get(), OK,
868 io_mode == SYNCHRONOUS);
869 CheckConnectTimesExceptDnsSet(ssl_connect_job->connect_timing());
870 EXPECT_TRUE(test_delegate.socket()->GetDnsAliases().empty());
871 }
872 }
873
TEST_F(SSLConnectJobTest,HttpProxyRequestPriority)874 TEST_F(SSLConnectJobTest, HttpProxyRequestPriority) {
875 host_resolver_.set_ondemand_mode(true);
876 for (int initial_priority = MINIMUM_PRIORITY;
877 initial_priority <= MAXIMUM_PRIORITY; ++initial_priority) {
878 SCOPED_TRACE(initial_priority);
879 for (int new_priority = MINIMUM_PRIORITY; new_priority <= MAXIMUM_PRIORITY;
880 ++new_priority) {
881 SCOPED_TRACE(new_priority);
882 if (initial_priority == new_priority) {
883 continue;
884 }
885 TestConnectJobDelegate test_delegate;
886 std::unique_ptr<ConnectJob> ssl_connect_job = CreateConnectJob(
887 &test_delegate, PacResultElementToProxyChain("PROXY foo:444"),
888 static_cast<RequestPriority>(initial_priority));
889 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
890 EXPECT_TRUE(host_resolver_.has_pending_requests());
891 int request_id = host_resolver_.num_resolve();
892 EXPECT_EQ(initial_priority, host_resolver_.request_priority(request_id));
893
894 ssl_connect_job->ChangePriority(
895 static_cast<RequestPriority>(new_priority));
896 EXPECT_EQ(new_priority, host_resolver_.request_priority(request_id));
897
898 ssl_connect_job->ChangePriority(
899 static_cast<RequestPriority>(initial_priority));
900 EXPECT_EQ(initial_priority, host_resolver_.request_priority(request_id));
901 }
902 }
903 }
904
TEST_F(SSLConnectJobTest,HttpProxyAuthHasEstablishedConnection)905 TEST_F(SSLConnectJobTest, HttpProxyAuthHasEstablishedConnection) {
906 host_resolver_.set_ondemand_mode(true);
907 MockWrite writes[] = {
908 MockWrite(ASYNC, 0,
909 "CONNECT host:80 HTTP/1.1\r\n"
910 "Host: host:80\r\n"
911 "Proxy-Connection: keep-alive\r\n"
912 "User-Agent: test-ua\r\n\r\n"),
913 MockWrite(ASYNC, 3,
914 "CONNECT host:80 HTTP/1.1\r\n"
915 "Host: host:80\r\n"
916 "Proxy-Connection: keep-alive\r\n"
917 "User-Agent: test-ua\r\n"
918 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
919 };
920 MockRead reads[] = {
921 // Pause reading.
922 MockRead(ASYNC, ERR_IO_PENDING, 1),
923 MockRead(ASYNC, 2,
924 "HTTP/1.1 407 Proxy Authentication Required\r\n"
925 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
926 "Content-Length: 0\r\n\r\n"),
927 // Pause reading.
928 MockRead(ASYNC, ERR_IO_PENDING, 4),
929 MockRead(ASYNC, 5, "HTTP/1.1 200 Connection Established\r\n\r\n"),
930 };
931 SequencedSocketData data(reads, writes);
932 socket_factory_.AddSocketDataProvider(&data);
933 SSLSocketDataProvider ssl(ASYNC, OK);
934 socket_factory_.AddSSLSocketDataProvider(&ssl);
935
936 TestConnectJobDelegate test_delegate;
937 std::unique_ptr<ConnectJob> ssl_connect_job = CreateConnectJob(
938 &test_delegate, PacResultElementToProxyChain("PROXY foo:444"));
939 ASSERT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
940 EXPECT_TRUE(host_resolver_.has_pending_requests());
941 EXPECT_EQ(LOAD_STATE_RESOLVING_HOST, ssl_connect_job->GetLoadState());
942 EXPECT_FALSE(ssl_connect_job->HasEstablishedConnection());
943
944 // DNS resolution completes, and then the ConnectJob tries to connect the
945 // socket, which should succeed asynchronously.
946 host_resolver_.ResolveOnlyRequestNow();
947 EXPECT_EQ(LOAD_STATE_CONNECTING, ssl_connect_job->GetLoadState());
948 EXPECT_FALSE(ssl_connect_job->HasEstablishedConnection());
949
950 // Spinning the message loop causes the connection to be established and the
951 // nested HttpProxyConnectJob to start establishing a tunnel.
952 base::RunLoop().RunUntilIdle();
953 EXPECT_FALSE(test_delegate.has_result());
954 EXPECT_EQ(LOAD_STATE_ESTABLISHING_PROXY_TUNNEL,
955 ssl_connect_job->GetLoadState());
956 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
957
958 // Receive the auth challenge.
959 data.Resume();
960 test_delegate.WaitForAuthChallenge(1);
961 EXPECT_FALSE(test_delegate.has_result());
962 EXPECT_EQ(LOAD_STATE_IDLE, ssl_connect_job->GetLoadState());
963 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
964
965 // Respond to challenge.
966 test_delegate.auth_controller()->ResetAuth(AuthCredentials(u"foo", u"bar"));
967 test_delegate.RunAuthCallback();
968 EXPECT_FALSE(test_delegate.has_result());
969 EXPECT_EQ(LOAD_STATE_ESTABLISHING_PROXY_TUNNEL,
970 ssl_connect_job->GetLoadState());
971 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
972
973 // Run until the next read pauses.
974 base::RunLoop().RunUntilIdle();
975 EXPECT_FALSE(test_delegate.has_result());
976 EXPECT_EQ(LOAD_STATE_ESTABLISHING_PROXY_TUNNEL,
977 ssl_connect_job->GetLoadState());
978 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
979
980 // Receive the connection established response, at which point SSL negotiation
981 // finally starts.
982 data.Resume();
983 EXPECT_FALSE(test_delegate.has_result());
984 EXPECT_EQ(LOAD_STATE_SSL_HANDSHAKE, ssl_connect_job->GetLoadState());
985 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
986
987 EXPECT_THAT(test_delegate.WaitForResult(), test::IsOk());
988 }
989
TEST_F(SSLConnectJobTest,HttpProxyAuthHasEstablishedConnectionWithProxyConnectionClose)990 TEST_F(SSLConnectJobTest,
991 HttpProxyAuthHasEstablishedConnectionWithProxyConnectionClose) {
992 host_resolver_.set_ondemand_mode(true);
993 MockWrite writes1[] = {
994 MockWrite(ASYNC, 0,
995 "CONNECT host:80 HTTP/1.1\r\n"
996 "Host: host:80\r\n"
997 "Proxy-Connection: keep-alive\r\n"
998 "User-Agent: test-ua\r\n\r\n"),
999 };
1000 MockRead reads1[] = {
1001 // Pause reading.
1002 MockRead(ASYNC, ERR_IO_PENDING, 1),
1003 MockRead(ASYNC, 2,
1004 "HTTP/1.1 407 Proxy Authentication Required\r\n"
1005 "Proxy-Connection: Close\r\n"
1006 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
1007 "Content-Length: 0\r\n\r\n"),
1008 };
1009 SequencedSocketData data1(reads1, writes1);
1010 socket_factory_.AddSocketDataProvider(&data1);
1011
1012 MockWrite writes2[] = {
1013 MockWrite(ASYNC, 0,
1014 "CONNECT host:80 HTTP/1.1\r\n"
1015 "Host: host:80\r\n"
1016 "Proxy-Connection: keep-alive\r\n"
1017 "User-Agent: test-ua\r\n"
1018 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1019 };
1020 MockRead reads2[] = {
1021 // Pause reading.
1022 MockRead(ASYNC, ERR_IO_PENDING, 1),
1023 MockRead(ASYNC, 2, "HTTP/1.1 200 Connection Established\r\n\r\n"),
1024 };
1025 SequencedSocketData data2(reads2, writes2);
1026 socket_factory_.AddSocketDataProvider(&data2);
1027 SSLSocketDataProvider ssl(ASYNC, OK);
1028 socket_factory_.AddSSLSocketDataProvider(&ssl);
1029
1030 TestConnectJobDelegate test_delegate;
1031 std::unique_ptr<ConnectJob> ssl_connect_job = CreateConnectJob(
1032 &test_delegate, PacResultElementToProxyChain("PROXY foo:444"));
1033 ASSERT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
1034 EXPECT_TRUE(host_resolver_.has_pending_requests());
1035 EXPECT_EQ(LOAD_STATE_RESOLVING_HOST, ssl_connect_job->GetLoadState());
1036 EXPECT_FALSE(ssl_connect_job->HasEstablishedConnection());
1037
1038 // DNS resolution completes, and then the ConnectJob tries to connect the
1039 // socket, which should succeed asynchronously.
1040 host_resolver_.ResolveOnlyRequestNow();
1041 EXPECT_EQ(LOAD_STATE_CONNECTING, ssl_connect_job->GetLoadState());
1042 EXPECT_FALSE(ssl_connect_job->HasEstablishedConnection());
1043
1044 // Spinning the message loop causes the connection to be established and the
1045 // nested HttpProxyConnectJob to start establishing a tunnel.
1046 base::RunLoop().RunUntilIdle();
1047 EXPECT_FALSE(test_delegate.has_result());
1048 EXPECT_EQ(LOAD_STATE_ESTABLISHING_PROXY_TUNNEL,
1049 ssl_connect_job->GetLoadState());
1050 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
1051
1052 // Receive the auth challenge.
1053 data1.Resume();
1054 test_delegate.WaitForAuthChallenge(1);
1055 EXPECT_FALSE(test_delegate.has_result());
1056 EXPECT_EQ(LOAD_STATE_IDLE, ssl_connect_job->GetLoadState());
1057 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
1058
1059 // Respond to challenge.
1060 test_delegate.auth_controller()->ResetAuth(AuthCredentials(u"foo", u"bar"));
1061 test_delegate.RunAuthCallback();
1062 EXPECT_FALSE(test_delegate.has_result());
1063 EXPECT_EQ(LOAD_STATE_ESTABLISHING_PROXY_TUNNEL,
1064 ssl_connect_job->GetLoadState());
1065 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
1066
1067 // Run until the next DNS lookup.
1068 base::RunLoop().RunUntilIdle();
1069 EXPECT_TRUE(host_resolver_.has_pending_requests());
1070 EXPECT_EQ(LOAD_STATE_RESOLVING_HOST, ssl_connect_job->GetLoadState());
1071 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
1072
1073 // DNS resolution completes, and then the ConnectJob tries to connect the
1074 // socket, which should succeed asynchronously.
1075 host_resolver_.ResolveOnlyRequestNow();
1076 EXPECT_EQ(LOAD_STATE_CONNECTING, ssl_connect_job->GetLoadState());
1077 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
1078
1079 // Spinning the message loop causes the connection to be established and the
1080 // nested HttpProxyConnectJob to start establishing a tunnel.
1081 base::RunLoop().RunUntilIdle();
1082 EXPECT_FALSE(test_delegate.has_result());
1083 EXPECT_EQ(LOAD_STATE_ESTABLISHING_PROXY_TUNNEL,
1084 ssl_connect_job->GetLoadState());
1085 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
1086
1087 // Receive the connection established response, at which point SSL negotiation
1088 // finally starts.
1089 data2.Resume();
1090 EXPECT_FALSE(test_delegate.has_result());
1091 EXPECT_EQ(LOAD_STATE_SSL_HANDSHAKE, ssl_connect_job->GetLoadState());
1092 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
1093
1094 EXPECT_THAT(test_delegate.WaitForResult(), test::IsOk());
1095 }
1096
TEST_F(SSLConnectJobTest,DnsAliases)1097 TEST_F(SSLConnectJobTest, DnsAliases) {
1098 host_resolver_.set_synchronous_mode(true);
1099
1100 // Resolve an AddressList with DNS aliases.
1101 std::vector<std::string> aliases({"alias1", "alias2", "host"});
1102 host_resolver_.rules()->AddIPLiteralRuleWithDnsAliases("host", "2.2.2.2",
1103 std::move(aliases));
1104 StaticSocketDataProvider data;
1105 data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1106 socket_factory_.AddSocketDataProvider(&data);
1107 SSLSocketDataProvider ssl(ASYNC, OK);
1108 socket_factory_.AddSSLSocketDataProvider(&ssl);
1109 TestConnectJobDelegate test_delegate;
1110
1111 std::unique_ptr<ConnectJob> ssl_connect_job =
1112 CreateConnectJob(&test_delegate, ProxyChain::Direct(), MEDIUM);
1113
1114 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
1115
1116 base::RunLoop().RunUntilIdle();
1117
1118 // Verify that the elements of the alias list are those from the
1119 // parameter vector.
1120 EXPECT_THAT(test_delegate.socket()->GetDnsAliases(),
1121 testing::ElementsAre("alias1", "alias2", "host"));
1122 }
1123
TEST_F(SSLConnectJobTest,NoAdditionalDnsAliases)1124 TEST_F(SSLConnectJobTest, NoAdditionalDnsAliases) {
1125 host_resolver_.set_synchronous_mode(true);
1126
1127 // Resolve an AddressList without additional DNS aliases. (The parameter
1128 // is an empty vector.)
1129 std::vector<std::string> aliases;
1130 host_resolver_.rules()->AddIPLiteralRuleWithDnsAliases("host", "2.2.2.2",
1131 std::move(aliases));
1132 StaticSocketDataProvider data;
1133 data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1134 socket_factory_.AddSocketDataProvider(&data);
1135 SSLSocketDataProvider ssl(ASYNC, OK);
1136 socket_factory_.AddSSLSocketDataProvider(&ssl);
1137 TestConnectJobDelegate test_delegate;
1138
1139 std::unique_ptr<ConnectJob> ssl_connect_job =
1140 CreateConnectJob(&test_delegate, ProxyChain::Direct(), MEDIUM);
1141
1142 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
1143
1144 base::RunLoop().RunUntilIdle();
1145
1146 // Verify that the alias list only contains "host".
1147 EXPECT_THAT(test_delegate.socket()->GetDnsAliases(),
1148 testing::ElementsAre("host"));
1149 }
1150
1151 // Test that `SSLConnectJob` passes the ECHConfigList from DNS to
1152 // `SSLClientSocket`.
TEST_F(SSLConnectJobTest,EncryptedClientHello)1153 TEST_F(SSLConnectJobTest, EncryptedClientHello) {
1154 std::vector<uint8_t> ech_config_list1, ech_config_list2;
1155 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1156 &ech_config_list1));
1157 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1158 &ech_config_list2));
1159
1160 // Configure two HTTPS RR routes, to test we pass the correct one.
1161 HostResolverEndpointResult endpoint1, endpoint2;
1162 endpoint1.ip_endpoints = {IPEndPoint(ParseIP("1::"), 8441)};
1163 endpoint1.metadata.supported_protocol_alpns = {"http/1.1"};
1164 endpoint1.metadata.ech_config_list = ech_config_list1;
1165 endpoint2.ip_endpoints = {IPEndPoint(ParseIP("2::"), 8442)};
1166 endpoint2.metadata.supported_protocol_alpns = {"http/1.1"};
1167 endpoint2.metadata.ech_config_list = ech_config_list2;
1168 host_resolver_.rules()->AddRule(
1169 "host", MockHostResolverBase::RuleResolver::RuleResult(
1170 std::vector{endpoint1, endpoint2}));
1171
1172 for (bool ech_enabled : {true, false}) {
1173 SCOPED_TRACE(ech_enabled);
1174 SSLContextConfig config;
1175 config.ech_enabled = ech_enabled;
1176 ssl_config_service_->UpdateSSLConfigAndNotify(config);
1177
1178 // The first connection attempt will be to `endpoint1`, which will fail.
1179 StaticSocketDataProvider data1;
1180 data1.set_expected_addresses(AddressList(endpoint1.ip_endpoints));
1181 data1.set_connect_data(MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED));
1182 socket_factory_.AddSocketDataProvider(&data1);
1183 // The second connection attempt will be to `endpoint2`, which will succeed.
1184 StaticSocketDataProvider data2;
1185 data2.set_expected_addresses(AddressList(endpoint2.ip_endpoints));
1186 data2.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1187 socket_factory_.AddSocketDataProvider(&data2);
1188 // The handshake then succeeds.
1189 SSLSocketDataProvider ssl2(ASYNC, OK);
1190 // The ECH configuration should be passed if and only if the feature is
1191 // enabled.
1192 ssl2.expected_ech_config_list =
1193 ech_enabled ? ech_config_list2 : std::vector<uint8_t>{};
1194 socket_factory_.AddSSLSocketDataProvider(&ssl2);
1195
1196 // The connection should ultimately succeed.
1197 base::HistogramTester histogram_tester;
1198 TestConnectJobDelegate test_delegate;
1199 std::unique_ptr<ConnectJob> ssl_connect_job =
1200 CreateConnectJob(&test_delegate, ProxyChain::Direct(), MEDIUM);
1201 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
1202 EXPECT_THAT(test_delegate.WaitForResult(), test::IsOk());
1203
1204 // Whether or not the feature is enabled, we should record data for the
1205 // ECH-capable server.
1206 histogram_tester.ExpectUniqueSample("Net.SSL_Connection_Error_ECH", OK, 1);
1207 histogram_tester.ExpectTotalCount("Net.SSL_Connection_Latency_ECH", 1);
1208 // The ECH result should only be recorded if ECH was actually enabled.
1209 if (ech_enabled) {
1210 histogram_tester.ExpectUniqueSample("Net.SSL.ECHResult",
1211 0 /* kSuccessInitial */, 1);
1212 } else {
1213 histogram_tester.ExpectTotalCount("Net.SSL.ECHResult", 0);
1214 }
1215 }
1216 }
1217
1218 // Test that `SSLConnectJob` retries the connection if there was a stale ECH
1219 // configuration.
TEST_F(SSLConnectJobTest,ECHStaleConfig)1220 TEST_F(SSLConnectJobTest, ECHStaleConfig) {
1221 std::vector<uint8_t> ech_config_list1, ech_config_list2, ech_config_list3;
1222 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1223 &ech_config_list1));
1224 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1225 &ech_config_list2));
1226 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1227 &ech_config_list3));
1228
1229 // Configure two HTTPS RR routes, to test the retry uses the correct one.
1230 HostResolverEndpointResult endpoint1, endpoint2;
1231 endpoint1.ip_endpoints = {IPEndPoint(ParseIP("1::"), 8441)};
1232 endpoint1.metadata.supported_protocol_alpns = {"http/1.1"};
1233 endpoint1.metadata.ech_config_list = ech_config_list1;
1234 endpoint2.ip_endpoints = {IPEndPoint(ParseIP("2::"), 8442)};
1235 endpoint2.metadata.supported_protocol_alpns = {"http/1.1"};
1236 endpoint2.metadata.ech_config_list = ech_config_list2;
1237 host_resolver_.rules()->AddRule(
1238 "host", MockHostResolverBase::RuleResolver::RuleResult(
1239 std::vector{endpoint1, endpoint2}));
1240
1241 // The first connection attempt will be to `endpoint1`, which will fail.
1242 StaticSocketDataProvider data1;
1243 data1.set_expected_addresses(AddressList(endpoint1.ip_endpoints));
1244 data1.set_connect_data(MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED));
1245 socket_factory_.AddSocketDataProvider(&data1);
1246 // The second connection attempt will be to `endpoint2`, which will succeed.
1247 StaticSocketDataProvider data2;
1248 data2.set_expected_addresses(AddressList(endpoint2.ip_endpoints));
1249 data2.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1250 socket_factory_.AddSocketDataProvider(&data2);
1251 // The handshake will then fail, but then provide retry configs.
1252 SSLSocketDataProvider ssl2(ASYNC, ERR_ECH_NOT_NEGOTIATED);
1253 ssl2.expected_ech_config_list = ech_config_list2;
1254 ssl2.ech_retry_configs = ech_config_list3;
1255 socket_factory_.AddSSLSocketDataProvider(&ssl2);
1256 // The third connection attempt should skip `endpoint1` and retry with only
1257 // `endpoint2`.
1258 StaticSocketDataProvider data3;
1259 data3.set_expected_addresses(AddressList(endpoint2.ip_endpoints));
1260 data3.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1261 socket_factory_.AddSocketDataProvider(&data3);
1262 // The handshake should be passed the retry configs.
1263 SSLSocketDataProvider ssl3(ASYNC, OK);
1264 ssl3.expected_ech_config_list = ech_config_list3;
1265 socket_factory_.AddSSLSocketDataProvider(&ssl3);
1266
1267 // The connection should ultimately succeed.
1268 base::HistogramTester histogram_tester;
1269 TestConnectJobDelegate test_delegate;
1270 std::unique_ptr<ConnectJob> ssl_connect_job =
1271 CreateConnectJob(&test_delegate, ProxyChain::Direct(), MEDIUM);
1272 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
1273 EXPECT_THAT(test_delegate.WaitForResult(), test::IsOk());
1274
1275 histogram_tester.ExpectUniqueSample("Net.SSL.ECHResult",
1276 2 /* kSuccessRetry */, 1);
1277 }
1278
1279 // Test that `SSLConnectJob` retries the connection given a secure rollback
1280 // signal.
TEST_F(SSLConnectJobTest,ECHRollback)1281 TEST_F(SSLConnectJobTest, ECHRollback) {
1282 std::vector<uint8_t> ech_config_list1, ech_config_list2;
1283 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1284 &ech_config_list1));
1285 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1286 &ech_config_list2));
1287
1288 // Configure two HTTPS RR routes, to test the retry uses the correct one.
1289 HostResolverEndpointResult endpoint1, endpoint2;
1290 endpoint1.ip_endpoints = {IPEndPoint(ParseIP("1::"), 8441)};
1291 endpoint1.metadata.supported_protocol_alpns = {"http/1.1"};
1292 endpoint1.metadata.ech_config_list = ech_config_list1;
1293 endpoint2.ip_endpoints = {IPEndPoint(ParseIP("2::"), 8442)};
1294 endpoint2.metadata.supported_protocol_alpns = {"http/1.1"};
1295 endpoint2.metadata.ech_config_list = ech_config_list2;
1296 host_resolver_.rules()->AddRule(
1297 "host", MockHostResolverBase::RuleResolver::RuleResult(
1298 std::vector{endpoint1, endpoint2}));
1299
1300 // The first connection attempt will be to `endpoint1`, which will fail.
1301 StaticSocketDataProvider data1;
1302 data1.set_expected_addresses(AddressList(endpoint1.ip_endpoints));
1303 data1.set_connect_data(MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED));
1304 socket_factory_.AddSocketDataProvider(&data1);
1305 // The second connection attempt will be to `endpoint2`, which will succeed.
1306 StaticSocketDataProvider data2;
1307 data2.set_expected_addresses(AddressList(endpoint2.ip_endpoints));
1308 data2.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1309 socket_factory_.AddSocketDataProvider(&data2);
1310 // The handshake will then fail, and provide no retry configs.
1311 SSLSocketDataProvider ssl2(ASYNC, ERR_ECH_NOT_NEGOTIATED);
1312 ssl2.expected_ech_config_list = ech_config_list2;
1313 ssl2.ech_retry_configs = std::vector<uint8_t>();
1314 socket_factory_.AddSSLSocketDataProvider(&ssl2);
1315 // The third connection attempt should skip `endpoint1` and retry with only
1316 // `endpoint2`.
1317 StaticSocketDataProvider data3;
1318 data3.set_expected_addresses(AddressList(endpoint2.ip_endpoints));
1319 data3.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1320 socket_factory_.AddSocketDataProvider(&data3);
1321 // The handshake should not be passed ECH configs.
1322 SSLSocketDataProvider ssl3(ASYNC, OK);
1323 ssl3.expected_ech_config_list = std::vector<uint8_t>();
1324 socket_factory_.AddSSLSocketDataProvider(&ssl3);
1325
1326 // The connection should ultimately succeed.
1327 base::HistogramTester histogram_tester;
1328 TestConnectJobDelegate test_delegate;
1329 std::unique_ptr<ConnectJob> ssl_connect_job =
1330 CreateConnectJob(&test_delegate, ProxyChain::Direct(), MEDIUM);
1331 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
1332 EXPECT_THAT(test_delegate.WaitForResult(), test::IsOk());
1333
1334 histogram_tester.ExpectUniqueSample("Net.SSL.ECHResult",
1335 4 /* kSuccessRollback */, 1);
1336 }
1337
1338 // Test that `SSLConnectJob` will not retry more than once.
TEST_F(SSLConnectJobTest,ECHTooManyRetries)1339 TEST_F(SSLConnectJobTest, ECHTooManyRetries) {
1340 std::vector<uint8_t> ech_config_list1, ech_config_list2, ech_config_list3;
1341 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1342 &ech_config_list1));
1343 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1344 &ech_config_list2));
1345 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1346 &ech_config_list3));
1347
1348 HostResolverEndpointResult endpoint;
1349 endpoint.ip_endpoints = {IPEndPoint(ParseIP("1::"), 8441)};
1350 endpoint.metadata.supported_protocol_alpns = {"http/1.1"};
1351 endpoint.metadata.ech_config_list = ech_config_list1;
1352 host_resolver_.rules()->AddRule(
1353 "host",
1354 MockHostResolverBase::RuleResolver::RuleResult(std::vector{endpoint}));
1355
1356 // The first connection attempt will succeed.
1357 StaticSocketDataProvider data1;
1358 data1.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1359 socket_factory_.AddSocketDataProvider(&data1);
1360 // The handshake will then fail, but provide retry configs.
1361 SSLSocketDataProvider ssl1(ASYNC, ERR_ECH_NOT_NEGOTIATED);
1362 ssl1.expected_ech_config_list = ech_config_list1;
1363 ssl1.ech_retry_configs = ech_config_list2;
1364 socket_factory_.AddSSLSocketDataProvider(&ssl1);
1365 // The second connection attempt will succeed.
1366 StaticSocketDataProvider data2;
1367 data2.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1368 socket_factory_.AddSocketDataProvider(&data2);
1369 // The handshake will then fail, but provide new retry configs.
1370 SSLSocketDataProvider ssl2(ASYNC, ERR_ECH_NOT_NEGOTIATED);
1371 ssl2.expected_ech_config_list = ech_config_list2;
1372 ssl2.ech_retry_configs = ech_config_list3;
1373 socket_factory_.AddSSLSocketDataProvider(&ssl2);
1374 // There will be no third connection attempt.
1375
1376 base::HistogramTester histogram_tester;
1377 TestConnectJobDelegate test_delegate;
1378 std::unique_ptr<ConnectJob> ssl_connect_job =
1379 CreateConnectJob(&test_delegate, ProxyChain::Direct(), MEDIUM);
1380 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
1381 EXPECT_THAT(test_delegate.WaitForResult(),
1382 test::IsError(ERR_ECH_NOT_NEGOTIATED));
1383
1384 histogram_tester.ExpectUniqueSample("Net.SSL.ECHResult", 3 /* kErrorRetry */,
1385 1);
1386 }
1387
1388 // Test that `SSLConnectJob` will not retry for ECH given the wrong error.
TEST_F(SSLConnectJobTest,ECHWrongRetryError)1389 TEST_F(SSLConnectJobTest, ECHWrongRetryError) {
1390 std::vector<uint8_t> ech_config_list1, ech_config_list2;
1391 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1392 &ech_config_list1));
1393 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1394 &ech_config_list2));
1395
1396 HostResolverEndpointResult endpoint;
1397 endpoint.ip_endpoints = {IPEndPoint(ParseIP("1::"), 8441)};
1398 endpoint.metadata.supported_protocol_alpns = {"http/1.1"};
1399 endpoint.metadata.ech_config_list = ech_config_list1;
1400 host_resolver_.rules()->AddRule(
1401 "host",
1402 MockHostResolverBase::RuleResolver::RuleResult(std::vector{endpoint}));
1403
1404 // The first connection attempt will succeed.
1405 StaticSocketDataProvider data1;
1406 data1.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1407 socket_factory_.AddSocketDataProvider(&data1);
1408 // The handshake will then fail, but provide retry configs.
1409 SSLSocketDataProvider ssl1(ASYNC, ERR_FAILED);
1410 ssl1.expected_ech_config_list = ech_config_list1;
1411 ssl1.ech_retry_configs = ech_config_list2;
1412 socket_factory_.AddSSLSocketDataProvider(&ssl1);
1413 // There will be no second connection attempt.
1414
1415 base::HistogramTester histogram_tester;
1416 TestConnectJobDelegate test_delegate;
1417 std::unique_ptr<ConnectJob> ssl_connect_job =
1418 CreateConnectJob(&test_delegate, ProxyChain::Direct(), MEDIUM);
1419 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
1420 EXPECT_THAT(test_delegate.WaitForResult(), test::IsError(ERR_FAILED));
1421
1422 histogram_tester.ExpectUniqueSample("Net.SSL.ECHResult",
1423 1 /* kErrorInitial */, 1);
1424 }
1425
1426 // Test the legacy crypto callback can trigger after the ECH recovery flow.
TEST_F(SSLConnectJobTest,ECHRecoveryThenLegacyCrypto)1427 TEST_F(SSLConnectJobTest, ECHRecoveryThenLegacyCrypto) {
1428 std::vector<uint8_t> ech_config_list1, ech_config_list2, ech_config_list3;
1429 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1430 &ech_config_list1));
1431 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1432 &ech_config_list2));
1433 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1434 &ech_config_list3));
1435
1436 // Configure two HTTPS RR routes, to test the retry uses the correct one.
1437 HostResolverEndpointResult endpoint1, endpoint2;
1438 endpoint1.ip_endpoints = {IPEndPoint(ParseIP("1::"), 8441)};
1439 endpoint1.metadata.supported_protocol_alpns = {"http/1.1"};
1440 endpoint1.metadata.ech_config_list = ech_config_list1;
1441 endpoint2.ip_endpoints = {IPEndPoint(ParseIP("2::"), 8442)};
1442 endpoint2.metadata.supported_protocol_alpns = {"http/1.1"};
1443 endpoint2.metadata.ech_config_list = ech_config_list2;
1444 host_resolver_.rules()->AddRule(
1445 "host", MockHostResolverBase::RuleResolver::RuleResult(
1446 std::vector{endpoint1, endpoint2}));
1447
1448 // The first connection attempt will be to `endpoint1`, which will fail.
1449 StaticSocketDataProvider data1;
1450 data1.set_expected_addresses(AddressList(endpoint1.ip_endpoints));
1451 data1.set_connect_data(MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED));
1452 socket_factory_.AddSocketDataProvider(&data1);
1453 // The second connection attempt will be to `endpoint2`, which will succeed.
1454 StaticSocketDataProvider data2;
1455 data2.set_expected_addresses(AddressList(endpoint2.ip_endpoints));
1456 data2.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1457 socket_factory_.AddSocketDataProvider(&data2);
1458 // The handshake will then fail, and provide retry configs.
1459 SSLSocketDataProvider ssl2(ASYNC, ERR_ECH_NOT_NEGOTIATED);
1460 ssl2.expected_ech_config_list = ech_config_list2;
1461 ssl2.ech_retry_configs = ech_config_list3;
1462 socket_factory_.AddSSLSocketDataProvider(&ssl2);
1463 // The third connection attempt should skip `endpoint1` and retry with only
1464 // `endpoint2`.
1465 StaticSocketDataProvider data3;
1466 data3.set_expected_addresses(AddressList(endpoint2.ip_endpoints));
1467 data3.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1468 socket_factory_.AddSocketDataProvider(&data3);
1469 // The handshake should be passed the retry configs. This will progress
1470 // further but trigger the legacy crypto fallback.
1471 SSLSocketDataProvider ssl3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
1472 ssl3.expected_ech_config_list = ech_config_list3;
1473 socket_factory_.AddSSLSocketDataProvider(&ssl3);
1474 // The third connection attempt should still skip `endpoint1` and retry with
1475 // only `endpoint2`.
1476 StaticSocketDataProvider data4;
1477 data4.set_expected_addresses(AddressList(endpoint2.ip_endpoints));
1478 data4.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1479 socket_factory_.AddSocketDataProvider(&data4);
1480 // The handshake should still be passed ECH retry configs. This time, the
1481 // connection enables legacy crypto and succeeds.
1482 SSLSocketDataProvider ssl4(ASYNC, OK);
1483 ssl4.expected_ech_config_list = ech_config_list3;
1484 socket_factory_.AddSSLSocketDataProvider(&ssl4);
1485
1486 // The connection should ultimately succeed.
1487 base::HistogramTester histogram_tester;
1488 TestConnectJobDelegate test_delegate;
1489 std::unique_ptr<ConnectJob> ssl_connect_job =
1490 CreateConnectJob(&test_delegate, ProxyChain::Direct(), MEDIUM);
1491 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
1492 EXPECT_THAT(test_delegate.WaitForResult(), test::IsOk());
1493
1494 histogram_tester.ExpectUniqueSample("Net.SSL.ECHResult",
1495 2 /* kSuccessRetry */, 1);
1496 }
1497
1498 // Test the ECH recovery flow can trigger after the legacy crypto fallback.
TEST_F(SSLConnectJobTest,LegacyCryptoThenECHRecovery)1499 TEST_F(SSLConnectJobTest, LegacyCryptoThenECHRecovery) {
1500 std::vector<uint8_t> ech_config_list1, ech_config_list2, ech_config_list3;
1501 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1502 &ech_config_list1));
1503 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1504 &ech_config_list2));
1505 ASSERT_TRUE(MakeTestEchKeys("public.example", /*max_name_len=*/128,
1506 &ech_config_list3));
1507
1508 // Configure two HTTPS RR routes, to test the retry uses the correct one.
1509 HostResolverEndpointResult endpoint1, endpoint2;
1510 endpoint1.ip_endpoints = {IPEndPoint(ParseIP("1::"), 8441)};
1511 endpoint1.metadata.supported_protocol_alpns = {"http/1.1"};
1512 endpoint1.metadata.ech_config_list = ech_config_list1;
1513 endpoint2.ip_endpoints = {IPEndPoint(ParseIP("2::"), 8442)};
1514 endpoint2.metadata.supported_protocol_alpns = {"http/1.1"};
1515 endpoint2.metadata.ech_config_list = ech_config_list2;
1516 host_resolver_.rules()->AddRule(
1517 "host", MockHostResolverBase::RuleResolver::RuleResult(
1518 std::vector{endpoint1, endpoint2}));
1519
1520 // The first connection attempt will be to `endpoint1`, which will fail.
1521 StaticSocketDataProvider data1;
1522 data1.set_expected_addresses(AddressList(endpoint1.ip_endpoints));
1523 data1.set_connect_data(MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED));
1524 socket_factory_.AddSocketDataProvider(&data1);
1525 // The second connection attempt will be to `endpoint2`, which will succeed.
1526 StaticSocketDataProvider data2;
1527 data2.set_expected_addresses(AddressList(endpoint2.ip_endpoints));
1528 data2.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1529 socket_factory_.AddSocketDataProvider(&data2);
1530 // The handshake will then fail, and trigger the legacy cryptography fallback.
1531 SSLSocketDataProvider ssl2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
1532 ssl2.expected_ech_config_list = ech_config_list2;
1533 socket_factory_.AddSSLSocketDataProvider(&ssl2);
1534 // The third and fourth connection attempts proceed as before, but with legacy
1535 // cryptography enabled.
1536 StaticSocketDataProvider data3;
1537 data3.set_expected_addresses(AddressList(endpoint1.ip_endpoints));
1538 data3.set_connect_data(MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED));
1539 socket_factory_.AddSocketDataProvider(&data3);
1540 StaticSocketDataProvider data4;
1541 data4.set_expected_addresses(AddressList(endpoint2.ip_endpoints));
1542 data4.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1543 socket_factory_.AddSocketDataProvider(&data4);
1544 // The handshake enables legacy crypto. Now ECH fails with retry configs.
1545 SSLSocketDataProvider ssl4(ASYNC, ERR_ECH_NOT_NEGOTIATED);
1546 ssl4.expected_ech_config_list = ech_config_list2;
1547 ssl4.ech_retry_configs = ech_config_list3;
1548 socket_factory_.AddSSLSocketDataProvider(&ssl4);
1549 // The fourth connection attempt should still skip `endpoint1` and retry with
1550 // only `endpoint2`.
1551 StaticSocketDataProvider data5;
1552 data5.set_expected_addresses(AddressList(endpoint2.ip_endpoints));
1553 data5.set_connect_data(MockConnect(SYNCHRONOUS, OK));
1554 socket_factory_.AddSocketDataProvider(&data5);
1555 // The handshake will now succeed with ECH retry configs and legacy
1556 // cryptography.
1557 SSLSocketDataProvider ssl5(ASYNC, OK);
1558 ssl5.expected_ech_config_list = ech_config_list3;
1559 socket_factory_.AddSSLSocketDataProvider(&ssl5);
1560
1561 // The connection should ultimately succeed.
1562 base::HistogramTester histogram_tester;
1563 TestConnectJobDelegate test_delegate;
1564 std::unique_ptr<ConnectJob> ssl_connect_job =
1565 CreateConnectJob(&test_delegate, ProxyChain::Direct(), MEDIUM);
1566 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
1567 EXPECT_THAT(test_delegate.WaitForResult(), test::IsOk());
1568
1569 histogram_tester.ExpectUniqueSample("Net.SSL.ECHResult",
1570 2 /* kSuccessRetry */, 1);
1571 }
1572
1573 } // namespace
1574 } // namespace net
1575