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