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