blob: 94932d4d2ac28be1a8874e31bca5523bcf177c4a [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"
12#include "base/stl_util.h"
13#include "base/strings/string_util.h"
14#include "base/strings/utf_string_conversions.h"
David Benjamin07a07d652020-02-26 22:26:5915#include "base/test/metrics/histogram_tester.h"
16#include "base/test/scoped_feature_list.h"
Gabriel Charettec7108742019-08-23 03:31:4017#include "base/test/task_environment.h"
Matt Menke7b5051072019-01-27 21:22:4918#include "base/time/time.h"
19#include "net/base/auth.h"
David Benjamin07a07d652020-02-26 22:26:5920#include "net/base/features.h"
Matt Menke7b5051072019-01-27 21:22:4921#include "net/base/load_timing_info.h"
22#include "net/base/net_errors.h"
Matt Menkeae58eeb2019-05-24 21:09:5023#include "net/base/network_isolation_key.h"
Matt Menke7b5051072019-01-27 21:22:4924#include "net/cert/ct_policy_enforcer.h"
25#include "net/cert/mock_cert_verifier.h"
26#include "net/cert/multi_log_ct_verifier.h"
27#include "net/dns/mock_host_resolver.h"
Eric Ortha093b092020-09-24 23:13:0228#include "net/dns/public/secure_dns_mode.h"
Matt Menke7b5051072019-01-27 21:22:4929#include "net/http/http_auth_handler_factory.h"
30#include "net/http/http_network_session.h"
Matt Menke0754b5d02019-02-10 21:46:4331#include "net/http/http_proxy_connect_job.h"
Matt Menke7b5051072019-01-27 21:22:4932#include "net/http/http_request_headers.h"
33#include "net/http/http_response_headers.h"
Matt Menke609160742019-08-02 18:47:2634#include "net/http/http_server_properties.h"
Matt Menke7b5051072019-01-27 21:22:4935#include "net/http/transport_security_state.h"
36#include "net/log/net_log_source.h"
37#include "net/log/net_log_with_source.h"
Nicolas Arciniegad2013f92020-02-07 23:00:5638#include "net/proxy_resolution/configured_proxy_resolution_service.h"
Victor Vasiliev7752898d2019-11-14 21:30:2239#include "net/quic/quic_context.h"
Matt Menke7b5051072019-01-27 21:22:4940#include "net/socket/connect_job_test_util.h"
Matt Menke6030ed9f2019-04-11 20:25:5541#include "net/socket/connection_attempts.h"
Matt Menke7b5051072019-01-27 21:22:4942#include "net/socket/next_proto.h"
43#include "net/socket/socket_tag.h"
44#include "net/socket/socket_test_util.h"
45#include "net/socket/socks_connect_job.h"
Matt Menke7b5051072019-01-27 21:22:4946#include "net/socket/transport_connect_job.h"
47#include "net/ssl/ssl_config_service_defaults.h"
David Benjamin07a07d652020-02-26 22:26:5948#include "net/ssl/ssl_connection_status_flags.h"
49#include "net/ssl/ssl_legacy_crypto_fallback.h"
50#include "net/test/cert_test_util.h"
Matt Menke7b5051072019-01-27 21:22:4951#include "net/test/gtest_util.h"
52#include "net/test/test_certificate_data.h"
David Benjamin07a07d652020-02-26 22:26:5953#include "net/test/test_data_directory.h"
Gabriel Charettec7108742019-08-23 03:31:4054#include "net/test/test_with_task_environment.h"
Matt Menke7b5051072019-01-27 21:22:4955#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
56#include "testing/gtest/include/gtest/gtest.h"
David Benjamin07a07d652020-02-26 22:26:5957#include "third_party/boringssl/src/include/openssl/ssl.h"
Matt Menke7b5051072019-01-27 21:22:4958
59namespace net {
60namespace {
61
Matt Menke7b5051072019-01-27 21:22:4962// Just check that all connect times are set to base::TimeTicks::Now(), for
63// tests that don't update the mocked out time.
64void CheckConnectTimesSet(const LoadTimingInfo::ConnectTiming& connect_timing) {
65 EXPECT_EQ(base::TimeTicks::Now(), connect_timing.dns_start);
66 EXPECT_EQ(base::TimeTicks::Now(), connect_timing.dns_end);
67 EXPECT_EQ(base::TimeTicks::Now(), connect_timing.connect_start);
68 EXPECT_EQ(base::TimeTicks::Now(), connect_timing.ssl_start);
69 EXPECT_EQ(base::TimeTicks::Now(), connect_timing.ssl_end);
70 EXPECT_EQ(base::TimeTicks::Now(), connect_timing.connect_end);
71}
72
73// Just check that all connect times are set to base::TimeTicks::Now(), except
74// for DNS times, for tests that don't update the mocked out time and use a
75// proxy.
76void CheckConnectTimesExceptDnsSet(
77 const LoadTimingInfo::ConnectTiming& connect_timing) {
78 EXPECT_TRUE(connect_timing.dns_start.is_null());
79 EXPECT_TRUE(connect_timing.dns_end.is_null());
80 EXPECT_EQ(base::TimeTicks::Now(), connect_timing.connect_start);
81 EXPECT_EQ(base::TimeTicks::Now(), connect_timing.ssl_start);
82 EXPECT_EQ(base::TimeTicks::Now(), connect_timing.ssl_end);
83 EXPECT_EQ(base::TimeTicks::Now(), connect_timing.connect_end);
84}
85
Gabriel Charette694c3c332019-08-19 14:53:0586class SSLConnectJobTest : public WithTaskEnvironment, public testing::Test {
Matt Menke7b5051072019-01-27 21:22:4987 public:
88 SSLConnectJobTest()
Gabriel Charette694c3c332019-08-19 14:53:0589 : WithTaskEnvironment(base::test::TaskEnvironment::TimeSource::MOCK_TIME),
Nicolas Arciniegad2013f92020-02-07 23:00:5690 proxy_resolution_service_(
91 ConfiguredProxyResolutionService::CreateDirect()),
Matt Menke7b5051072019-01-27 21:22:4992 ssl_config_service_(new SSLConfigServiceDefaults),
Eric Orthbe2efac2019-03-06 01:11:1193 http_auth_handler_factory_(HttpAuthHandlerFactory::CreateDefault()),
Matt Menke7b5051072019-01-27 21:22:4994 session_(CreateNetworkSession()),
Matt Menke7b5051072019-01-27 21:22:4995 direct_transport_socket_params_(
96 new TransportSocketParams(HostPortPair("host", 443),
Matt Menkecd439232019-11-05 15:15:3397 NetworkIsolationKey(),
dalyk5f48a132019-10-14 15:20:1998 false /* disable_secure_dns */,
Matt Menke7b5051072019-01-27 21:22:4999 OnHostResolutionCallback())),
Matt Menke7b5051072019-01-27 21:22:49100 proxy_transport_socket_params_(
101 new TransportSocketParams(HostPortPair("proxy", 443),
Matt Menkecd439232019-11-05 15:15:33102 NetworkIsolationKey(),
dalyk5f48a132019-10-14 15:20:19103 false /* disable_secure_dns */,
Matt Menke7b5051072019-01-27 21:22:49104 OnHostResolutionCallback())),
105 socks_socket_params_(
106 new SOCKSSocketParams(proxy_transport_socket_params_,
107 true,
108 HostPortPair("sockshost", 443),
Matt Menke166710e2019-11-06 03:35:51109 NetworkIsolationKey(),
Matt Menke7b5051072019-01-27 21:22:49110 TRAFFIC_ANNOTATION_FOR_TESTS)),
111 http_proxy_socket_params_(
112 new HttpProxySocketParams(proxy_transport_socket_params_,
113 nullptr /* ssl_params */,
Matt Menkeb5fb42b2019-03-22 17:26:13114 false /* is_quic */,
Matt Menke7b5051072019-01-27 21:22:49115 HostPortPair("host", 80),
Matt Menke7b5051072019-01-27 21:22:49116 /*is_trusted_proxy=*/false,
117 /*tunnel=*/true,
Matt Menkeae58eeb2019-05-24 21:09:50118 TRAFFIC_ANNOTATION_FOR_TESTS,
119 NetworkIsolationKey())),
Gabriel Charette694c3c332019-08-19 14:53:05120 common_connect_job_params_(session_->CreateCommonConnectJobParams()) {}
Matt Menke7b5051072019-01-27 21:22:49121
122 ~SSLConnectJobTest() override = default;
123
124 std::unique_ptr<ConnectJob> CreateConnectJob(
125 TestConnectJobDelegate* test_delegate,
126 ProxyServer::Scheme proxy_scheme = ProxyServer::SCHEME_DIRECT,
127 RequestPriority priority = DEFAULT_PRIORITY) {
128 return std::make_unique<SSLConnectJob>(
Matt Menkea6f99ad2019-03-08 02:26:43129 priority, SocketTag(), &common_connect_job_params_,
Matt Menke14819512019-03-02 16:59:58130 SSLParams(proxy_scheme), test_delegate, nullptr /* net_log */);
Matt Menke7b5051072019-01-27 21:22:49131 }
132
133 scoped_refptr<SSLSocketParams> SSLParams(ProxyServer::Scheme proxy) {
134 return base::MakeRefCounted<SSLSocketParams>(
135 proxy == ProxyServer::SCHEME_DIRECT ? direct_transport_socket_params_
136 : nullptr,
137 proxy == ProxyServer::SCHEME_SOCKS5 ? socks_socket_params_ : nullptr,
138 proxy == ProxyServer::SCHEME_HTTP ? http_proxy_socket_params_ : nullptr,
David Benjamin151ec6b2019-08-02 19:38:52139 HostPortPair("host", 443), SSLConfig(), PRIVACY_MODE_DISABLED,
David Benjamin6f2da652019-06-26 23:36:35140 NetworkIsolationKey());
Matt Menke7b5051072019-01-27 21:22:49141 }
142
143 void AddAuthToCache() {
144 const base::string16 kFoo(base::ASCIIToUTF16("foo"));
145 const base::string16 kBar(base::ASCIIToUTF16("bar"));
146 session_->http_auth_cache()->Add(
Matt Menke96092e62019-10-18 04:09:33147 GURL("http://proxy:443/"), HttpAuth::AUTH_PROXY, "MyRealm1",
Matt Menkebe090422019-10-18 20:25:26148 HttpAuth::AUTH_SCHEME_BASIC, NetworkIsolationKey(),
149 "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");
Matt Menke7b5051072019-01-27 21:22:49150 }
151
152 HttpNetworkSession* CreateNetworkSession() {
153 HttpNetworkSession::Context session_context;
154 session_context.host_resolver = &host_resolver_;
155 session_context.cert_verifier = &cert_verifier_;
156 session_context.transport_security_state = &transport_security_state_;
157 session_context.cert_transparency_verifier = &ct_verifier_;
158 session_context.ct_policy_enforcer = &ct_policy_enforcer_;
159 session_context.proxy_resolution_service = proxy_resolution_service_.get();
160 session_context.client_socket_factory = &socket_factory_;
161 session_context.ssl_config_service = ssl_config_service_.get();
162 session_context.http_auth_handler_factory =
163 http_auth_handler_factory_.get();
164 session_context.http_server_properties = &http_server_properties_;
Victor Vasiliev7752898d2019-11-14 21:30:22165 session_context.quic_context = &quic_context_;
Matt Menke7b5051072019-01-27 21:22:49166 return new HttpNetworkSession(HttpNetworkSession::Params(),
167 session_context);
168 }
169
170 protected:
171 MockClientSocketFactory socket_factory_;
Matt Menkeaade5812019-03-02 13:38:00172 MockHostResolver host_resolver_;
Matt Menke7b5051072019-01-27 21:22:49173 MockCertVerifier cert_verifier_;
174 TransportSecurityState transport_security_state_;
175 MultiLogCTVerifier ct_verifier_;
176 DefaultCTPolicyEnforcer ct_policy_enforcer_;
Nicolas Arciniega8ec5bfa2020-03-20 05:07:26177 const std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
Matt Menke7b5051072019-01-27 21:22:49178 const std::unique_ptr<SSLConfigService> ssl_config_service_;
179 const std::unique_ptr<HttpAuthHandlerFactory> http_auth_handler_factory_;
Matt Menke609160742019-08-02 18:47:26180 HttpServerProperties http_server_properties_;
Victor Vasiliev7752898d2019-11-14 21:30:22181 QuicContext quic_context_;
Matt Menke7b5051072019-01-27 21:22:49182 const std::unique_ptr<HttpNetworkSession> session_;
Matt Menke7b5051072019-01-27 21:22:49183
184 scoped_refptr<TransportSocketParams> direct_transport_socket_params_;
Matt Menke7b5051072019-01-27 21:22:49185
186 scoped_refptr<TransportSocketParams> proxy_transport_socket_params_;
187 scoped_refptr<SOCKSSocketParams> socks_socket_params_;
188 scoped_refptr<HttpProxySocketParams> http_proxy_socket_params_;
189
Matt Menkea6f99ad2019-03-08 02:26:43190 const CommonConnectJobParams common_connect_job_params_;
Matt Menke7b5051072019-01-27 21:22:49191};
192
193TEST_F(SSLConnectJobTest, TCPFail) {
194 for (IoMode io_mode : {SYNCHRONOUS, ASYNC}) {
195 SCOPED_TRACE(io_mode);
196 host_resolver_.set_synchronous_mode(io_mode == SYNCHRONOUS);
197 StaticSocketDataProvider data;
198 data.set_connect_data(MockConnect(io_mode, ERR_CONNECTION_FAILED));
199 socket_factory_.AddSocketDataProvider(&data);
200
201 TestConnectJobDelegate test_delegate;
202 std::unique_ptr<ConnectJob> ssl_connect_job =
203 CreateConnectJob(&test_delegate);
204 test_delegate.StartJobExpectingResult(
205 ssl_connect_job.get(), ERR_CONNECTION_FAILED, io_mode == SYNCHRONOUS);
206 EXPECT_FALSE(test_delegate.socket());
Matt Menke6f84d1f12019-04-11 19:26:47207 EXPECT_FALSE(ssl_connect_job->IsSSLError());
Matt Menke6030ed9f2019-04-11 20:25:55208 ConnectionAttempts connection_attempts =
209 ssl_connect_job->GetConnectionAttempts();
210 ASSERT_EQ(1u, connection_attempts.size());
211 EXPECT_THAT(connection_attempts[0].result,
Matt Menke7b5051072019-01-27 21:22:49212 test::IsError(ERR_CONNECTION_FAILED));
213 }
214}
215
Matt Menke36eaf5c2019-04-02 16:15:52216TEST_F(SSLConnectJobTest, TCPTimeout) {
217 const base::TimeDelta kTinyTime = base::TimeDelta::FromMicroseconds(1);
218
219 // Make request hang.
220 host_resolver_.set_ondemand_mode(true);
221
222 TestConnectJobDelegate test_delegate;
223 std::unique_ptr<ConnectJob> ssl_connect_job =
224 CreateConnectJob(&test_delegate);
225 ASSERT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
226
227 // Right up until just before the TCP connection timeout, the job does not
228 // time out.
229 FastForwardBy(TransportConnectJob::ConnectionTimeout() - kTinyTime);
230 EXPECT_FALSE(test_delegate.has_result());
231
232 // But at the exact time of TCP connection timeout, the job fails.
233 FastForwardBy(kTinyTime);
234 EXPECT_TRUE(test_delegate.has_result());
235 EXPECT_THAT(test_delegate.WaitForResult(), test::IsError(ERR_TIMED_OUT));
236}
237
238TEST_F(SSLConnectJobTest, SSLTimeoutSyncConnect) {
239 const base::TimeDelta kTinyTime = base::TimeDelta::FromMicroseconds(1);
240
241 // DNS lookup and transport connect complete synchronously, but SSL
242 // negotiation hangs.
243 host_resolver_.set_synchronous_mode(true);
244 StaticSocketDataProvider data;
245 data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
246 socket_factory_.AddSocketDataProvider(&data);
247 SSLSocketDataProvider ssl(SYNCHRONOUS, ERR_IO_PENDING);
248 socket_factory_.AddSSLSocketDataProvider(&ssl);
249
250 // Make request hang.
251 TestConnectJobDelegate test_delegate;
252 std::unique_ptr<ConnectJob> ssl_connect_job =
253 CreateConnectJob(&test_delegate);
254 ASSERT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
255
256 // Right up until just before the SSL handshake timeout, the job does not time
257 // out.
258 FastForwardBy(SSLConnectJob::HandshakeTimeoutForTesting() - kTinyTime);
259 EXPECT_FALSE(test_delegate.has_result());
260
261 // But at the exact SSL handshake timeout time, the job fails.
262 FastForwardBy(kTinyTime);
263 EXPECT_TRUE(test_delegate.has_result());
264 EXPECT_THAT(test_delegate.WaitForResult(), test::IsError(ERR_TIMED_OUT));
265}
266
267TEST_F(SSLConnectJobTest, SSLTimeoutAsyncTcpConnect) {
268 const base::TimeDelta kTinyTime = base::TimeDelta::FromMicroseconds(1);
269
270 // DNS lookup is asynchronous, and later SSL negotiation hangs.
271 host_resolver_.set_ondemand_mode(true);
272 StaticSocketDataProvider data;
273 data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
274 socket_factory_.AddSocketDataProvider(&data);
275 SSLSocketDataProvider ssl(SYNCHRONOUS, ERR_IO_PENDING);
276 socket_factory_.AddSSLSocketDataProvider(&ssl);
277
278 TestConnectJobDelegate test_delegate;
279 std::unique_ptr<ConnectJob> ssl_connect_job =
280 CreateConnectJob(&test_delegate);
281 // Connecting should hand on the TransportConnectJob connect.
282 ASSERT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
283
284 // Right up until just before the TCP connection timeout, the job does not
285 // time out.
286 FastForwardBy(TransportConnectJob::ConnectionTimeout() - kTinyTime);
287 EXPECT_FALSE(test_delegate.has_result());
288
289 // The DNS lookup completes, and a TCP connection is immediately establshed,
290 // which cancels the TCP connection timer. The SSL handshake timer is started,
291 // and the SSL handshake hangs.
292 host_resolver_.ResolveOnlyRequestNow();
293 EXPECT_FALSE(test_delegate.has_result());
294
295 // Right up until just before the SSL handshake timeout, the job does not time
296 // out.
297 FastForwardBy(SSLConnectJob::HandshakeTimeoutForTesting() - kTinyTime);
298 EXPECT_FALSE(test_delegate.has_result());
299
300 // But at the exact SSL handshake timeout time, the job fails.
301 FastForwardBy(kTinyTime);
302 EXPECT_TRUE(test_delegate.has_result());
303 EXPECT_THAT(test_delegate.WaitForResult(), test::IsError(ERR_TIMED_OUT));
304}
305
Matt Menke7b5051072019-01-27 21:22:49306TEST_F(SSLConnectJobTest, BasicDirectSync) {
307 host_resolver_.set_synchronous_mode(true);
308 StaticSocketDataProvider data;
309 data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
310 socket_factory_.AddSocketDataProvider(&data);
311 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
312 socket_factory_.AddSSLSocketDataProvider(&ssl);
313
314 TestConnectJobDelegate test_delegate;
315 std::unique_ptr<ConnectJob> ssl_connect_job =
316 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_DIRECT, MEDIUM);
317
318 test_delegate.StartJobExpectingResult(ssl_connect_job.get(), OK,
319 true /* expect_sync_result */);
320 EXPECT_EQ(MEDIUM, host_resolver_.last_request_priority());
321
Matt Menke6030ed9f2019-04-11 20:25:55322 ConnectionAttempts connection_attempts =
323 ssl_connect_job->GetConnectionAttempts();
324 EXPECT_EQ(0u, connection_attempts.size());
Matt Menke7b5051072019-01-27 21:22:49325 CheckConnectTimesSet(ssl_connect_job->connect_timing());
326}
327
328TEST_F(SSLConnectJobTest, BasicDirectAsync) {
329 host_resolver_.set_ondemand_mode(true);
330 base::TimeTicks start_time = base::TimeTicks::Now();
331 StaticSocketDataProvider data;
332 data.set_connect_data(MockConnect(ASYNC, OK));
333 socket_factory_.AddSocketDataProvider(&data);
334 SSLSocketDataProvider ssl(ASYNC, OK);
335 socket_factory_.AddSSLSocketDataProvider(&ssl);
336
337 TestConnectJobDelegate test_delegate;
338 std::unique_ptr<ConnectJob> ssl_connect_job =
339 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_DIRECT, MEDIUM);
340 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
341 EXPECT_TRUE(host_resolver_.has_pending_requests());
342 EXPECT_EQ(MEDIUM, host_resolver_.last_request_priority());
343 FastForwardBy(base::TimeDelta::FromSeconds(5));
344
345 base::TimeTicks resolve_complete_time = base::TimeTicks::Now();
346 host_resolver_.ResolveAllPending();
347 EXPECT_THAT(test_delegate.WaitForResult(), test::IsOk());
348
Matt Menke6030ed9f2019-04-11 20:25:55349 ConnectionAttempts connection_attempts =
350 ssl_connect_job->GetConnectionAttempts();
351 EXPECT_EQ(0u, connection_attempts.size());
Matt Menke7b5051072019-01-27 21:22:49352
353 // Check times. Since time is mocked out, all times will be the same, except
354 // |dns_start|, which is the only one recorded before the FastForwardBy()
355 // call. The test classes don't allow any other phases to be triggered on
356 // demand, or delayed by a set interval.
357 EXPECT_EQ(start_time, ssl_connect_job->connect_timing().dns_start);
358 EXPECT_EQ(resolve_complete_time, ssl_connect_job->connect_timing().dns_end);
359 EXPECT_EQ(resolve_complete_time,
360 ssl_connect_job->connect_timing().connect_start);
361 EXPECT_EQ(resolve_complete_time, ssl_connect_job->connect_timing().ssl_start);
362 EXPECT_EQ(resolve_complete_time, ssl_connect_job->connect_timing().ssl_end);
363 EXPECT_EQ(resolve_complete_time,
364 ssl_connect_job->connect_timing().connect_end);
365}
366
Matt Menke9d5e2c92019-02-05 01:42:23367TEST_F(SSLConnectJobTest, DirectHasEstablishedConnection) {
368 host_resolver_.set_ondemand_mode(true);
369 StaticSocketDataProvider data;
370 data.set_connect_data(MockConnect(ASYNC, OK));
371 socket_factory_.AddSocketDataProvider(&data);
372
373 // SSL negotiation hangs. Value returned after SSL negotiation is complete
374 // doesn't matter, as HasEstablishedConnection() may only be used between job
375 // start and job complete.
376 SSLSocketDataProvider ssl(SYNCHRONOUS, ERR_IO_PENDING);
377 socket_factory_.AddSSLSocketDataProvider(&ssl);
378
379 TestConnectJobDelegate test_delegate;
380 std::unique_ptr<ConnectJob> ssl_connect_job =
381 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_DIRECT, MEDIUM);
382 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
383 EXPECT_TRUE(host_resolver_.has_pending_requests());
384 EXPECT_EQ(LOAD_STATE_RESOLVING_HOST, ssl_connect_job->GetLoadState());
385 EXPECT_FALSE(ssl_connect_job->HasEstablishedConnection());
386
387 // DNS resolution completes, and then the ConnectJob tries to connect the
388 // socket, which should succeed asynchronously.
389 host_resolver_.ResolveNow(1);
390 EXPECT_EQ(LOAD_STATE_CONNECTING, ssl_connect_job->GetLoadState());
391 EXPECT_FALSE(ssl_connect_job->HasEstablishedConnection());
392
393 // Spinning the message loop causes the socket to finish connecting. The SSL
394 // handshake should start and hang.
395 base::RunLoop().RunUntilIdle();
396 EXPECT_FALSE(test_delegate.has_result());
397 EXPECT_EQ(LOAD_STATE_SSL_HANDSHAKE, ssl_connect_job->GetLoadState());
398 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
399}
400
Matt Menke7b5051072019-01-27 21:22:49401TEST_F(SSLConnectJobTest, RequestPriority) {
402 host_resolver_.set_ondemand_mode(true);
Matt Menke7b5051072019-01-27 21:22:49403 for (int initial_priority = MINIMUM_PRIORITY;
404 initial_priority <= MAXIMUM_PRIORITY; ++initial_priority) {
405 SCOPED_TRACE(initial_priority);
406 for (int new_priority = MINIMUM_PRIORITY; new_priority <= MAXIMUM_PRIORITY;
407 ++new_priority) {
408 SCOPED_TRACE(new_priority);
409 if (initial_priority == new_priority)
410 continue;
411 TestConnectJobDelegate test_delegate;
412 std::unique_ptr<ConnectJob> ssl_connect_job =
413 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_DIRECT,
414 static_cast<RequestPriority>(initial_priority));
415 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
416 EXPECT_TRUE(host_resolver_.has_pending_requests());
417 int request_id = host_resolver_.num_resolve();
418 EXPECT_EQ(initial_priority, host_resolver_.request_priority(request_id));
419
420 ssl_connect_job->ChangePriority(
421 static_cast<RequestPriority>(new_priority));
422 EXPECT_EQ(new_priority, host_resolver_.request_priority(request_id));
423
424 ssl_connect_job->ChangePriority(
425 static_cast<RequestPriority>(initial_priority));
426 EXPECT_EQ(initial_priority, host_resolver_.request_priority(request_id));
Matt Menke7b5051072019-01-27 21:22:49427 }
428 }
429}
430
dalyk5f48a132019-10-14 15:20:19431TEST_F(SSLConnectJobTest, DisableSecureDns) {
432 for (bool disable_secure_dns : {false, true}) {
433 TestConnectJobDelegate test_delegate;
434 direct_transport_socket_params_ =
Matt Menkecd439232019-11-05 15:15:33435 base::MakeRefCounted<TransportSocketParams>(
436 HostPortPair("host", 443), NetworkIsolationKey(),
437 disable_secure_dns, OnHostResolutionCallback());
dalyk5f48a132019-10-14 15:20:19438 auto common_connect_job_params = session_->CreateCommonConnectJobParams();
439 std::unique_ptr<ConnectJob> ssl_connect_job =
440 std::make_unique<SSLConnectJob>(DEFAULT_PRIORITY, SocketTag(),
441 &common_connect_job_params,
442 SSLParams(ProxyServer::SCHEME_DIRECT),
443 &test_delegate, nullptr /* net_log */);
444
445 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
446 EXPECT_EQ(disable_secure_dns,
447 host_resolver_.last_secure_dns_mode_override().has_value());
448 if (disable_secure_dns) {
Eric Ortha093b092020-09-24 23:13:02449 EXPECT_EQ(net::SecureDnsMode::kOff,
dalyk5f48a132019-10-14 15:20:19450 host_resolver_.last_secure_dns_mode_override().value());
451 }
452 }
453}
454
dalykedd30d982019-12-16 15:31:10455TEST_F(SSLConnectJobTest, DirectHostResolutionFailure) {
456 host_resolver_.rules()->AddSimulatedTimeoutFailure("host");
457
458 TestConnectJobDelegate test_delegate;
459 std::unique_ptr<ConnectJob> ssl_connect_job =
460 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_DIRECT);
461 test_delegate.StartJobExpectingResult(ssl_connect_job.get(),
462 ERR_NAME_NOT_RESOLVED,
463 false /* expect_sync_result */);
464 EXPECT_THAT(ssl_connect_job->GetResolveErrorInfo().error,
465 test::IsError(ERR_DNS_TIMED_OUT));
466}
467
Matt Menke7b5051072019-01-27 21:22:49468TEST_F(SSLConnectJobTest, DirectCertError) {
469 StaticSocketDataProvider data;
470 socket_factory_.AddSocketDataProvider(&data);
471 SSLSocketDataProvider ssl(ASYNC, ERR_CERT_COMMON_NAME_INVALID);
472 socket_factory_.AddSSLSocketDataProvider(&ssl);
473
474 TestConnectJobDelegate test_delegate(
475 TestConnectJobDelegate::SocketExpected::ALWAYS);
476 std::unique_ptr<ConnectJob> ssl_connect_job =
477 CreateConnectJob(&test_delegate);
478
479 test_delegate.StartJobExpectingResult(ssl_connect_job.get(),
480 ERR_CERT_COMMON_NAME_INVALID,
481 false /* expect_sync_result */);
Matt Menke6f84d1f12019-04-11 19:26:47482 EXPECT_TRUE(ssl_connect_job->IsSSLError());
Matt Menke6030ed9f2019-04-11 20:25:55483 ConnectionAttempts connection_attempts =
484 ssl_connect_job->GetConnectionAttempts();
485 ASSERT_EQ(1u, connection_attempts.size());
486 EXPECT_THAT(connection_attempts[0].result,
Matt Menke7b5051072019-01-27 21:22:49487 test::IsError(ERR_CERT_COMMON_NAME_INVALID));
488 CheckConnectTimesSet(ssl_connect_job->connect_timing());
489}
490
491TEST_F(SSLConnectJobTest, DirectSSLError) {
492 StaticSocketDataProvider data;
493 socket_factory_.AddSocketDataProvider(&data);
David Benjamin07a07d652020-02-26 22:26:59494 SSLSocketDataProvider ssl(ASYNC, ERR_BAD_SSL_CLIENT_AUTH_CERT);
Matt Menke7b5051072019-01-27 21:22:49495 socket_factory_.AddSSLSocketDataProvider(&ssl);
496
497 TestConnectJobDelegate test_delegate;
498 std::unique_ptr<ConnectJob> ssl_connect_job =
499 CreateConnectJob(&test_delegate);
500
501 test_delegate.StartJobExpectingResult(ssl_connect_job.get(),
David Benjamin07a07d652020-02-26 22:26:59502 ERR_BAD_SSL_CLIENT_AUTH_CERT,
Matt Menke7b5051072019-01-27 21:22:49503 false /* expect_sync_result */);
Matt Menke6030ed9f2019-04-11 20:25:55504 ConnectionAttempts connection_attempts =
505 ssl_connect_job->GetConnectionAttempts();
506 ASSERT_EQ(1u, connection_attempts.size());
507 EXPECT_THAT(connection_attempts[0].result,
David Benjamin07a07d652020-02-26 22:26:59508 test::IsError(ERR_BAD_SSL_CLIENT_AUTH_CERT));
509}
510
511// Test that the legacy crypto fallback is triggered on applicable error codes.
512TEST_F(SSLConnectJobTest, DirectLegacyCryptoFallback) {
513 for (Error error :
514 {ERR_CONNECTION_CLOSED, ERR_CONNECTION_RESET, ERR_SSL_PROTOCOL_ERROR,
515 ERR_SSL_VERSION_OR_CIPHER_MISMATCH}) {
516 SCOPED_TRACE(error);
517
518 for (bool second_attempt_ok : {true, false}) {
519 SCOPED_TRACE(second_attempt_ok);
520
521 StaticSocketDataProvider data;
522 socket_factory_.AddSocketDataProvider(&data);
523 SSLSocketDataProvider ssl(ASYNC, error);
524 socket_factory_.AddSSLSocketDataProvider(&ssl);
525 ssl.expected_disable_legacy_crypto = true;
526
527 Error error2 = second_attempt_ok ? OK : error;
528 StaticSocketDataProvider data2;
529 socket_factory_.AddSocketDataProvider(&data2);
530 SSLSocketDataProvider ssl2(ASYNC, error2);
531 socket_factory_.AddSSLSocketDataProvider(&ssl2);
532 ssl2.expected_disable_legacy_crypto = false;
533
534 TestConnectJobDelegate test_delegate;
535 std::unique_ptr<ConnectJob> ssl_connect_job =
536 CreateConnectJob(&test_delegate);
537
538 test_delegate.StartJobExpectingResult(ssl_connect_job.get(), error2,
539 /*expect_sync_result=*/false);
540 ConnectionAttempts connection_attempts =
541 ssl_connect_job->GetConnectionAttempts();
542 if (second_attempt_ok) {
543 ASSERT_EQ(1u, connection_attempts.size());
544 EXPECT_THAT(connection_attempts[0].result, test::IsError(error));
545 } else {
546 ASSERT_EQ(2u, connection_attempts.size());
547 EXPECT_THAT(connection_attempts[0].result, test::IsError(error));
548 EXPECT_THAT(connection_attempts[1].result, test::IsError(error));
549 }
550 }
551 }
552}
553
554// Test that the feature flag disables the legacy crypto fallback.
555TEST_F(SSLConnectJobTest, LegacyCryptoFallbackDisabled) {
556 base::test::ScopedFeatureList feature_list;
557 feature_list.InitAndDisableFeature(
558 features::kTLSLegacyCryptoFallbackForMetrics);
559 for (Error error :
560 {ERR_CONNECTION_CLOSED, ERR_CONNECTION_RESET, ERR_SSL_PROTOCOL_ERROR,
561 ERR_SSL_VERSION_OR_CIPHER_MISMATCH}) {
562 SCOPED_TRACE(error);
563
564 StaticSocketDataProvider data;
565 socket_factory_.AddSocketDataProvider(&data);
566 SSLSocketDataProvider ssl(ASYNC, error);
567 socket_factory_.AddSSLSocketDataProvider(&ssl);
568 ssl.expected_disable_legacy_crypto = false;
569
570 TestConnectJobDelegate test_delegate;
571 std::unique_ptr<ConnectJob> ssl_connect_job =
572 CreateConnectJob(&test_delegate);
573
574 test_delegate.StartJobExpectingResult(ssl_connect_job.get(), error,
575 /*expect_sync_result=*/false);
576 ConnectionAttempts connection_attempts =
577 ssl_connect_job->GetConnectionAttempts();
578 ASSERT_EQ(1u, connection_attempts.size());
579 EXPECT_THAT(connection_attempts[0].result, test::IsError(error));
580 }
581}
582
583TEST_F(SSLConnectJobTest, LegacyCryptoFallbackHistograms) {
584 base::FilePath certs_dir = GetTestCertsDirectory();
585
586 scoped_refptr<X509Certificate> sha1_leaf =
587 ImportCertFromFile(certs_dir, "sha1_leaf.pem");
588 ASSERT_TRUE(sha1_leaf);
589
590 scoped_refptr<X509Certificate> ok_cert =
591 ImportCertFromFile(certs_dir, "ok_cert.pem");
592 ASSERT_TRUE(ok_cert);
593
594 // Make a copy of |ok_cert| with an unused |sha1_leaf| in the intermediate
595 // list.
596 std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> intermediates;
597 for (const auto& cert : ok_cert->intermediate_buffers()) {
598 intermediates.push_back(bssl::UpRef(cert));
599 }
600 intermediates.push_back(bssl::UpRef(sha1_leaf->cert_buffer()));
601 scoped_refptr<X509Certificate> ok_with_unused_sha1 =
602 X509Certificate::CreateFromBuffer(bssl::UpRef(ok_cert->cert_buffer()),
603 std::move(intermediates));
604 ASSERT_TRUE(ok_with_unused_sha1);
605
606 // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
607 const uint16_t kModernCipher = 0xc02f;
608 // TLS_RSA_WITH_3DES_EDE_CBC_SHA
609 const uint16_t k3DESCipher = 0x000a;
610
611 struct HistogramTest {
612 SSLLegacyCryptoFallback expected;
613 Error first_attempt;
614 uint16_t cipher_suite;
615 uint16_t peer_signature_algorithm;
616 scoped_refptr<X509Certificate> unverified_cert;
617 };
618
619 const HistogramTest kHistogramTests[] = {
620 // Connections not using the fallback map to kNoFallback.
621 {SSLLegacyCryptoFallback::kNoFallback, OK, kModernCipher,
622 SSL_SIGN_RSA_PSS_RSAE_SHA256, ok_cert},
623 {SSLLegacyCryptoFallback::kNoFallback, OK, kModernCipher,
624 SSL_SIGN_RSA_PSS_RSAE_SHA256, sha1_leaf},
625 {SSLLegacyCryptoFallback::kNoFallback, OK, kModernCipher,
626 SSL_SIGN_RSA_PSS_RSAE_SHA256, ok_with_unused_sha1},
627
628 // Connections using 3DES map to kUsed3DES or kSentSHA1CertAndUsed3DES.
629 // Note our only supported 3DES cipher suite does not include a server
630 // signature, so |peer_signature_algorithm| would always be zero.
631 {SSLLegacyCryptoFallback::kUsed3DES, ERR_SSL_PROTOCOL_ERROR, k3DESCipher,
632 0, ok_cert},
633 {SSLLegacyCryptoFallback::kSentSHA1CertAndUsed3DES,
634 ERR_SSL_PROTOCOL_ERROR, k3DESCipher, 0, sha1_leaf},
635 {SSLLegacyCryptoFallback::kSentSHA1CertAndUsed3DES,
636 ERR_SSL_PROTOCOL_ERROR, k3DESCipher, 0, ok_with_unused_sha1},
637
638 // Connections using SHA-1 map to kUsedSHA1 or kSentSHA1CertAndUsedSHA1.
639 {SSLLegacyCryptoFallback::kUsedSHA1, ERR_SSL_PROTOCOL_ERROR,
640 kModernCipher, SSL_SIGN_RSA_PKCS1_SHA1, ok_cert},
641 {SSLLegacyCryptoFallback::kSentSHA1CertAndUsedSHA1,
642 ERR_SSL_PROTOCOL_ERROR, kModernCipher, SSL_SIGN_RSA_PKCS1_SHA1,
643 sha1_leaf},
644 {SSLLegacyCryptoFallback::kSentSHA1CertAndUsedSHA1,
645 ERR_SSL_PROTOCOL_ERROR, kModernCipher, SSL_SIGN_RSA_PKCS1_SHA1,
646 ok_with_unused_sha1},
647
648 // Connections using neither map to kUnknownReason or kSentSHA1Cert.
649 {SSLLegacyCryptoFallback::kUnknownReason, ERR_SSL_PROTOCOL_ERROR,
650 kModernCipher, SSL_SIGN_RSA_PSS_RSAE_SHA256, ok_cert},
651 {SSLLegacyCryptoFallback::kSentSHA1Cert, ERR_SSL_PROTOCOL_ERROR,
652 kModernCipher, SSL_SIGN_RSA_PSS_RSAE_SHA256, sha1_leaf},
653 {SSLLegacyCryptoFallback::kSentSHA1Cert, ERR_SSL_PROTOCOL_ERROR,
654 kModernCipher, SSL_SIGN_RSA_PSS_RSAE_SHA256, ok_with_unused_sha1},
655 };
656 for (size_t i = 0; i < base::size(kHistogramTests); i++) {
657 SCOPED_TRACE(i);
658 const auto& test = kHistogramTests[i];
659
660 base::HistogramTester tester;
661
662 SSLInfo ssl_info;
663 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_TLS1_2,
664 &ssl_info.connection_status);
665 SSLConnectionStatusSetCipherSuite(test.cipher_suite,
666 &ssl_info.connection_status);
667 ssl_info.peer_signature_algorithm = test.peer_signature_algorithm;
668 ssl_info.unverified_cert = test.unverified_cert;
669
670 StaticSocketDataProvider data;
671 socket_factory_.AddSocketDataProvider(&data);
672 SSLSocketDataProvider ssl(ASYNC, test.first_attempt);
673 socket_factory_.AddSSLSocketDataProvider(&ssl);
674 ssl.expected_disable_legacy_crypto = true;
675
676 StaticSocketDataProvider data2;
677 SSLSocketDataProvider ssl2(ASYNC, OK);
678 if (test.first_attempt != OK) {
679 socket_factory_.AddSocketDataProvider(&data2);
680 socket_factory_.AddSSLSocketDataProvider(&ssl2);
681 ssl2.ssl_info = ssl_info;
682 ssl2.expected_disable_legacy_crypto = false;
683 } else {
684 ssl.ssl_info = ssl_info;
685 }
686
687 TestConnectJobDelegate test_delegate;
688 std::unique_ptr<ConnectJob> ssl_connect_job =
689 CreateConnectJob(&test_delegate);
690
691 test_delegate.StartJobExpectingResult(ssl_connect_job.get(), OK,
692 /*expect_sync_result=*/false);
693
694 tester.ExpectUniqueSample("Net.SSLLegacyCryptoFallback", test.expected, 1);
695 }
Matt Menke7b5051072019-01-27 21:22:49696}
697
698TEST_F(SSLConnectJobTest, DirectWithNPN) {
699 StaticSocketDataProvider data;
700 socket_factory_.AddSocketDataProvider(&data);
701 SSLSocketDataProvider ssl(ASYNC, OK);
702 ssl.next_proto = kProtoHTTP11;
703 socket_factory_.AddSSLSocketDataProvider(&ssl);
704
705 TestConnectJobDelegate test_delegate;
706 std::unique_ptr<ConnectJob> ssl_connect_job =
707 CreateConnectJob(&test_delegate);
708
709 test_delegate.StartJobExpectingResult(ssl_connect_job.get(), OK,
710 false /* expect_sync_result */);
711 EXPECT_TRUE(test_delegate.socket()->WasAlpnNegotiated());
712 CheckConnectTimesSet(ssl_connect_job->connect_timing());
713}
714
715TEST_F(SSLConnectJobTest, DirectGotHTTP2) {
716 StaticSocketDataProvider data;
717 socket_factory_.AddSocketDataProvider(&data);
718 SSLSocketDataProvider ssl(ASYNC, OK);
719 ssl.next_proto = kProtoHTTP2;
720 socket_factory_.AddSSLSocketDataProvider(&ssl);
721
722 TestConnectJobDelegate test_delegate;
723 std::unique_ptr<ConnectJob> ssl_connect_job =
724 CreateConnectJob(&test_delegate);
725
726 test_delegate.StartJobExpectingResult(ssl_connect_job.get(), OK,
727 false /* expect_sync_result */);
728 EXPECT_TRUE(test_delegate.socket()->WasAlpnNegotiated());
729 EXPECT_EQ(kProtoHTTP2, test_delegate.socket()->GetNegotiatedProtocol());
730 CheckConnectTimesSet(ssl_connect_job->connect_timing());
731}
732
733TEST_F(SSLConnectJobTest, SOCKSFail) {
734 for (IoMode io_mode : {SYNCHRONOUS, ASYNC}) {
735 SCOPED_TRACE(io_mode);
736 host_resolver_.set_synchronous_mode(io_mode == SYNCHRONOUS);
737 StaticSocketDataProvider data;
738 data.set_connect_data(MockConnect(io_mode, ERR_CONNECTION_FAILED));
739 socket_factory_.AddSocketDataProvider(&data);
740
741 TestConnectJobDelegate test_delegate;
742 std::unique_ptr<ConnectJob> ssl_connect_job =
743 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_SOCKS5);
744 test_delegate.StartJobExpectingResult(ssl_connect_job.get(),
745 ERR_PROXY_CONNECTION_FAILED,
746 io_mode == SYNCHRONOUS);
Matt Menke6f84d1f12019-04-11 19:26:47747 EXPECT_FALSE(ssl_connect_job->IsSSLError());
Matt Menke7b5051072019-01-27 21:22:49748
Matt Menke6030ed9f2019-04-11 20:25:55749 ConnectionAttempts connection_attempts =
750 ssl_connect_job->GetConnectionAttempts();
751 EXPECT_EQ(0u, connection_attempts.size());
Matt Menke7b5051072019-01-27 21:22:49752 }
753}
754
dalykedd30d982019-12-16 15:31:10755TEST_F(SSLConnectJobTest, SOCKSHostResolutionFailure) {
756 host_resolver_.rules()->AddSimulatedTimeoutFailure("proxy");
757
758 TestConnectJobDelegate test_delegate;
759 std::unique_ptr<ConnectJob> ssl_connect_job =
760 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_SOCKS5);
761 test_delegate.StartJobExpectingResult(ssl_connect_job.get(),
762 ERR_PROXY_CONNECTION_FAILED,
763 false /* expect_sync_result */);
764 EXPECT_THAT(ssl_connect_job->GetResolveErrorInfo().error,
765 test::IsError(ERR_DNS_TIMED_OUT));
766}
767
Matt Menke7b5051072019-01-27 21:22:49768TEST_F(SSLConnectJobTest, SOCKSBasic) {
769 for (IoMode io_mode : {SYNCHRONOUS, ASYNC}) {
770 SCOPED_TRACE(io_mode);
771 const char kSOCKS5Request[] = {0x05, 0x01, 0x00, 0x03, 0x09, 's',
772 'o', 'c', 'k', 's', 'h', 'o',
773 's', 't', 0x01, 0xBB};
774
775 MockWrite writes[] = {
776 MockWrite(io_mode, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength),
Matt Menke628d624f2019-02-09 00:40:24777 MockWrite(io_mode, kSOCKS5Request, base::size(kSOCKS5Request)),
778 };
Matt Menke7b5051072019-01-27 21:22:49779
780 MockRead reads[] = {
781 MockRead(io_mode, kSOCKS5GreetResponse, kSOCKS5GreetResponseLength),
Matt Menke628d624f2019-02-09 00:40:24782 MockRead(io_mode, kSOCKS5OkResponse, kSOCKS5OkResponseLength),
783 };
Matt Menke7b5051072019-01-27 21:22:49784
785 host_resolver_.set_synchronous_mode(io_mode == SYNCHRONOUS);
786 StaticSocketDataProvider data(reads, writes);
787 data.set_connect_data(MockConnect(io_mode, OK));
788 socket_factory_.AddSocketDataProvider(&data);
789 SSLSocketDataProvider ssl(io_mode, OK);
790 socket_factory_.AddSSLSocketDataProvider(&ssl);
791
792 TestConnectJobDelegate test_delegate;
793 std::unique_ptr<ConnectJob> ssl_connect_job =
794 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_SOCKS5);
795 test_delegate.StartJobExpectingResult(ssl_connect_job.get(), OK,
796 io_mode == SYNCHRONOUS);
797 CheckConnectTimesExceptDnsSet(ssl_connect_job->connect_timing());
798 }
799}
800
Matt Menke628d624f2019-02-09 00:40:24801TEST_F(SSLConnectJobTest, SOCKSHasEstablishedConnection) {
802 const char kSOCKS5Request[] = {0x05, 0x01, 0x00, 0x03, 0x09, 's', 'o', 'c',
803 'k', 's', 'h', 'o', 's', 't', 0x01, 0xBB};
804
805 MockWrite writes[] = {
806 MockWrite(SYNCHRONOUS, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength, 0),
807 MockWrite(SYNCHRONOUS, kSOCKS5Request, base::size(kSOCKS5Request), 3),
808 };
809
810 MockRead reads[] = {
811 // Pause so can probe current state.
812 MockRead(ASYNC, ERR_IO_PENDING, 1),
813 MockRead(ASYNC, kSOCKS5GreetResponse, kSOCKS5GreetResponseLength, 2),
814 MockRead(SYNCHRONOUS, kSOCKS5OkResponse, kSOCKS5OkResponseLength, 4),
815 };
816
817 host_resolver_.set_ondemand_mode(true);
818 SequencedSocketData data(reads, writes);
819 data.set_connect_data(MockConnect(ASYNC, OK));
820 socket_factory_.AddSocketDataProvider(&data);
821
822 // SSL negotiation hangs. Value returned after SSL negotiation is complete
823 // doesn't matter, as HasEstablishedConnection() may only be used between job
824 // start and job complete.
825 SSLSocketDataProvider ssl(SYNCHRONOUS, ERR_IO_PENDING);
826 socket_factory_.AddSSLSocketDataProvider(&ssl);
827
828 TestConnectJobDelegate test_delegate;
829 std::unique_ptr<ConnectJob> ssl_connect_job =
830 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_SOCKS5);
831 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
832 EXPECT_TRUE(host_resolver_.has_pending_requests());
833 EXPECT_EQ(LOAD_STATE_RESOLVING_HOST, ssl_connect_job->GetLoadState());
834 EXPECT_FALSE(ssl_connect_job->HasEstablishedConnection());
835
836 // DNS resolution completes, and then the ConnectJob tries to connect the
837 // socket, which should succeed asynchronously.
838 host_resolver_.ResolveNow(1);
839 EXPECT_EQ(LOAD_STATE_CONNECTING, ssl_connect_job->GetLoadState());
840 EXPECT_FALSE(ssl_connect_job->HasEstablishedConnection());
841
842 // Spin the message loop until the first read of the handshake.
843 // HasEstablishedConnection() should return true, as a TCP connection has been
844 // successfully established by this point.
845 data.RunUntilPaused();
846 EXPECT_FALSE(test_delegate.has_result());
847 EXPECT_EQ(LOAD_STATE_CONNECTING, ssl_connect_job->GetLoadState());
848 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
849
850 // Finish up the handshake, and spin the message loop until the SSL handshake
851 // starts and hang.
852 data.Resume();
853 base::RunLoop().RunUntilIdle();
854 EXPECT_FALSE(test_delegate.has_result());
855 EXPECT_EQ(LOAD_STATE_SSL_HANDSHAKE, ssl_connect_job->GetLoadState());
856 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
857}
858
Matt Menke7b5051072019-01-27 21:22:49859TEST_F(SSLConnectJobTest, SOCKSRequestPriority) {
860 host_resolver_.set_ondemand_mode(true);
Matt Menke7b5051072019-01-27 21:22:49861 for (int initial_priority = MINIMUM_PRIORITY;
862 initial_priority <= MAXIMUM_PRIORITY; ++initial_priority) {
863 SCOPED_TRACE(initial_priority);
864 for (int new_priority = MINIMUM_PRIORITY; new_priority <= MAXIMUM_PRIORITY;
865 ++new_priority) {
866 SCOPED_TRACE(new_priority);
867 if (initial_priority == new_priority)
868 continue;
869 TestConnectJobDelegate test_delegate;
870 std::unique_ptr<ConnectJob> ssl_connect_job =
871 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_SOCKS5,
872 static_cast<RequestPriority>(initial_priority));
873 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
874 EXPECT_TRUE(host_resolver_.has_pending_requests());
875 int request_id = host_resolver_.num_resolve();
876 EXPECT_EQ(initial_priority, host_resolver_.request_priority(request_id));
877
878 ssl_connect_job->ChangePriority(
879 static_cast<RequestPriority>(new_priority));
880 EXPECT_EQ(new_priority, host_resolver_.request_priority(request_id));
881
882 ssl_connect_job->ChangePriority(
883 static_cast<RequestPriority>(initial_priority));
884 EXPECT_EQ(initial_priority, host_resolver_.request_priority(request_id));
Matt Menke7b5051072019-01-27 21:22:49885 }
886 }
887}
888
889TEST_F(SSLConnectJobTest, HttpProxyFail) {
890 for (IoMode io_mode : {SYNCHRONOUS, ASYNC}) {
891 SCOPED_TRACE(io_mode);
892 host_resolver_.set_synchronous_mode(io_mode == SYNCHRONOUS);
893 StaticSocketDataProvider data;
894 data.set_connect_data(MockConnect(io_mode, ERR_CONNECTION_FAILED));
895 socket_factory_.AddSocketDataProvider(&data);
896
897 TestConnectJobDelegate test_delegate;
898 std::unique_ptr<ConnectJob> ssl_connect_job =
899 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_HTTP);
900 test_delegate.StartJobExpectingResult(ssl_connect_job.get(),
901 ERR_PROXY_CONNECTION_FAILED,
902 io_mode == SYNCHRONOUS);
903
Matt Menke6f84d1f12019-04-11 19:26:47904 EXPECT_FALSE(ssl_connect_job->IsSSLError());
Matt Menke6030ed9f2019-04-11 20:25:55905 ConnectionAttempts connection_attempts =
906 ssl_connect_job->GetConnectionAttempts();
907 EXPECT_EQ(0u, connection_attempts.size());
Matt Menke7b5051072019-01-27 21:22:49908 }
909}
910
dalykedd30d982019-12-16 15:31:10911TEST_F(SSLConnectJobTest, HttpProxyHostResolutionFailure) {
912 host_resolver_.rules()->AddSimulatedTimeoutFailure("proxy");
913
914 TestConnectJobDelegate test_delegate;
915 std::unique_ptr<ConnectJob> ssl_connect_job =
916 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_HTTP);
917 test_delegate.StartJobExpectingResult(ssl_connect_job.get(),
918 ERR_PROXY_CONNECTION_FAILED,
919 false /* expect_sync_result */);
920 EXPECT_THAT(ssl_connect_job->GetResolveErrorInfo().error,
921 test::IsError(ERR_DNS_TIMED_OUT));
922}
923
Matt Menkeb57663b32019-03-01 17:17:10924TEST_F(SSLConnectJobTest, HttpProxyAuthChallenge) {
925 MockWrite writes[] = {
926 MockWrite(ASYNC, 0,
927 "CONNECT host:80 HTTP/1.1\r\n"
928 "Host: host:80\r\n"
929 "Proxy-Connection: keep-alive\r\n\r\n"),
930 MockWrite(ASYNC, 5,
931 "CONNECT host:80 HTTP/1.1\r\n"
932 "Host: host:80\r\n"
933 "Proxy-Connection: keep-alive\r\n"
934 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
935 };
936 MockRead reads[] = {
937 MockRead(ASYNC, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"),
938 MockRead(ASYNC, 2, "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
939 MockRead(ASYNC, 3, "Content-Length: 10\r\n\r\n"),
940 MockRead(ASYNC, 4, "0123456789"),
941 MockRead(ASYNC, 6, "HTTP/1.1 200 Connection Established\r\n\r\n"),
942 };
943 StaticSocketDataProvider data(reads, writes);
944 socket_factory_.AddSocketDataProvider(&data);
945 SSLSocketDataProvider ssl(ASYNC, OK);
946 socket_factory_.AddSSLSocketDataProvider(&ssl);
947
Matt Menkeb57663b32019-03-01 17:17:10948 TestConnectJobDelegate test_delegate;
949 std::unique_ptr<ConnectJob> ssl_connect_job =
950 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_HTTP);
951 ASSERT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
952 test_delegate.WaitForAuthChallenge(1);
953
954 EXPECT_EQ(407, test_delegate.auth_response_info().headers->response_code());
955 std::string proxy_authenticate;
956 ASSERT_TRUE(test_delegate.auth_response_info().headers->EnumerateHeader(
957 nullptr, "Proxy-Authenticate", &proxy_authenticate));
958 EXPECT_EQ(proxy_authenticate, "Basic realm=\"MyRealm1\"");
959
960 // While waiting for auth credentials to be provided, the Job should not time
961 // out.
962 FastForwardBy(base::TimeDelta::FromDays(1));
963 test_delegate.WaitForAuthChallenge(1);
964 EXPECT_FALSE(test_delegate.has_result());
965
966 // Respond to challenge.
967 test_delegate.auth_controller()->ResetAuth(
968 AuthCredentials(base::ASCIIToUTF16("foo"), base::ASCIIToUTF16("bar")));
969 test_delegate.RunAuthCallback();
970
971 EXPECT_THAT(test_delegate.WaitForResult(), test::IsOk());
972}
973
974TEST_F(SSLConnectJobTest, HttpProxyAuthWithCachedCredentials) {
Matt Menke7b5051072019-01-27 21:22:49975 for (IoMode io_mode : {SYNCHRONOUS, ASYNC}) {
976 SCOPED_TRACE(io_mode);
977 host_resolver_.set_synchronous_mode(io_mode == SYNCHRONOUS);
978 MockWrite writes[] = {
979 MockWrite(io_mode,
980 "CONNECT host:80 HTTP/1.1\r\n"
981 "Host: host:80\r\n"
982 "Proxy-Connection: keep-alive\r\n"
983 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
984 };
985 MockRead reads[] = {
986 MockRead(io_mode, "HTTP/1.1 200 Connection Established\r\n\r\n"),
987 };
988 StaticSocketDataProvider data(reads, writes);
989 data.set_connect_data(MockConnect(io_mode, OK));
990 socket_factory_.AddSocketDataProvider(&data);
991 AddAuthToCache();
992 SSLSocketDataProvider ssl(io_mode, OK);
993 socket_factory_.AddSSLSocketDataProvider(&ssl);
994
995 TestConnectJobDelegate test_delegate;
996 std::unique_ptr<ConnectJob> ssl_connect_job =
997 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_HTTP);
998 test_delegate.StartJobExpectingResult(ssl_connect_job.get(), OK,
999 io_mode == SYNCHRONOUS);
1000 CheckConnectTimesExceptDnsSet(ssl_connect_job->connect_timing());
1001 }
1002}
1003
1004TEST_F(SSLConnectJobTest, HttpProxyRequestPriority) {
1005 host_resolver_.set_ondemand_mode(true);
Matt Menke7b5051072019-01-27 21:22:491006 for (int initial_priority = MINIMUM_PRIORITY;
1007 initial_priority <= MAXIMUM_PRIORITY; ++initial_priority) {
1008 SCOPED_TRACE(initial_priority);
1009 for (int new_priority = MINIMUM_PRIORITY; new_priority <= MAXIMUM_PRIORITY;
1010 ++new_priority) {
1011 SCOPED_TRACE(new_priority);
1012 if (initial_priority == new_priority)
1013 continue;
1014 TestConnectJobDelegate test_delegate;
1015 std::unique_ptr<ConnectJob> ssl_connect_job =
1016 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_HTTP,
1017 static_cast<RequestPriority>(initial_priority));
1018 EXPECT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
1019 EXPECT_TRUE(host_resolver_.has_pending_requests());
1020 int request_id = host_resolver_.num_resolve();
1021 EXPECT_EQ(initial_priority, host_resolver_.request_priority(request_id));
1022
1023 ssl_connect_job->ChangePriority(
1024 static_cast<RequestPriority>(new_priority));
1025 EXPECT_EQ(new_priority, host_resolver_.request_priority(request_id));
1026
1027 ssl_connect_job->ChangePriority(
1028 static_cast<RequestPriority>(initial_priority));
1029 EXPECT_EQ(initial_priority, host_resolver_.request_priority(request_id));
Matt Menke7b5051072019-01-27 21:22:491030 }
1031 }
1032}
1033
Matt Menkeaade5812019-03-02 13:38:001034TEST_F(SSLConnectJobTest, HttpProxyAuthHasEstablishedConnection) {
1035 host_resolver_.set_ondemand_mode(true);
1036 MockWrite writes[] = {
1037 MockWrite(ASYNC, 0,
1038 "CONNECT host:80 HTTP/1.1\r\n"
1039 "Host: host:80\r\n"
1040 "Proxy-Connection: keep-alive\r\n\r\n"),
1041 MockWrite(ASYNC, 3,
1042 "CONNECT host:80 HTTP/1.1\r\n"
1043 "Host: host:80\r\n"
1044 "Proxy-Connection: keep-alive\r\n"
1045 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1046 };
1047 MockRead reads[] = {
1048 // Pause reading.
1049 MockRead(ASYNC, ERR_IO_PENDING, 1),
1050 MockRead(ASYNC, 2,
1051 "HTTP/1.1 407 Proxy Authentication Required\r\n"
1052 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
1053 "Content-Length: 0\r\n\r\n"),
1054 // Pause reading.
1055 MockRead(ASYNC, ERR_IO_PENDING, 4),
1056 MockRead(ASYNC, 5, "HTTP/1.1 200 Connection Established\r\n\r\n"),
1057 };
1058 SequencedSocketData data(reads, writes);
1059 socket_factory_.AddSocketDataProvider(&data);
1060 SSLSocketDataProvider ssl(ASYNC, OK);
1061 socket_factory_.AddSSLSocketDataProvider(&ssl);
1062
Matt Menkeaade5812019-03-02 13:38:001063 TestConnectJobDelegate test_delegate;
1064 std::unique_ptr<ConnectJob> ssl_connect_job =
1065 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_HTTP);
1066 ASSERT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
1067 EXPECT_TRUE(host_resolver_.has_pending_requests());
1068 EXPECT_EQ(LOAD_STATE_RESOLVING_HOST, ssl_connect_job->GetLoadState());
1069 EXPECT_FALSE(ssl_connect_job->HasEstablishedConnection());
1070
1071 // DNS resolution completes, and then the ConnectJob tries to connect the
1072 // socket, which should succeed asynchronously.
1073 host_resolver_.ResolveOnlyRequestNow();
1074 EXPECT_EQ(LOAD_STATE_CONNECTING, ssl_connect_job->GetLoadState());
1075 EXPECT_FALSE(ssl_connect_job->HasEstablishedConnection());
1076
1077 // Spinning the message loop causes the connection to be established and the
1078 // nested HttpProxyConnectJob to start establishing a tunnel.
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 auth challenge.
1086 data.Resume();
1087 test_delegate.WaitForAuthChallenge(1);
1088 EXPECT_FALSE(test_delegate.has_result());
1089 EXPECT_EQ(LOAD_STATE_IDLE, ssl_connect_job->GetLoadState());
1090 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
1091
1092 // Respond to challenge.
1093 test_delegate.auth_controller()->ResetAuth(
1094 AuthCredentials(base::ASCIIToUTF16("foo"), base::ASCIIToUTF16("bar")));
1095 test_delegate.RunAuthCallback();
1096 EXPECT_FALSE(test_delegate.has_result());
1097 EXPECT_EQ(LOAD_STATE_ESTABLISHING_PROXY_TUNNEL,
1098 ssl_connect_job->GetLoadState());
1099 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
1100
1101 // Run until the next read pauses.
1102 base::RunLoop().RunUntilIdle();
1103 EXPECT_FALSE(test_delegate.has_result());
1104 EXPECT_EQ(LOAD_STATE_ESTABLISHING_PROXY_TUNNEL,
1105 ssl_connect_job->GetLoadState());
1106 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
1107
1108 // Receive the connection established response, at which point SSL negotiation
1109 // finally starts.
1110 data.Resume();
1111 EXPECT_FALSE(test_delegate.has_result());
1112 EXPECT_EQ(LOAD_STATE_SSL_HANDSHAKE, ssl_connect_job->GetLoadState());
1113 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
1114
1115 EXPECT_THAT(test_delegate.WaitForResult(), test::IsOk());
1116}
1117
1118TEST_F(SSLConnectJobTest,
1119 HttpProxyAuthHasEstablishedConnectionWithProxyConnectionClose) {
1120 host_resolver_.set_ondemand_mode(true);
1121 MockWrite writes1[] = {
1122 MockWrite(ASYNC, 0,
1123 "CONNECT host:80 HTTP/1.1\r\n"
1124 "Host: host:80\r\n"
1125 "Proxy-Connection: keep-alive\r\n\r\n"),
1126 };
1127 MockRead reads1[] = {
1128 // Pause reading.
1129 MockRead(ASYNC, ERR_IO_PENDING, 1),
1130 MockRead(ASYNC, 2,
1131 "HTTP/1.1 407 Proxy Authentication Required\r\n"
1132 "Proxy-Connection: Close\r\n"
1133 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
1134 "Content-Length: 0\r\n\r\n"),
1135 };
1136 SequencedSocketData data1(reads1, writes1);
1137 socket_factory_.AddSocketDataProvider(&data1);
1138
1139 MockWrite writes2[] = {
1140 MockWrite(ASYNC, 0,
1141 "CONNECT host:80 HTTP/1.1\r\n"
1142 "Host: host:80\r\n"
1143 "Proxy-Connection: keep-alive\r\n"
1144 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1145 };
1146 MockRead reads2[] = {
1147 // Pause reading.
1148 MockRead(ASYNC, ERR_IO_PENDING, 1),
1149 MockRead(ASYNC, 2, "HTTP/1.1 200 Connection Established\r\n\r\n"),
1150 };
1151 SequencedSocketData data2(reads2, writes2);
1152 socket_factory_.AddSocketDataProvider(&data2);
1153 SSLSocketDataProvider ssl(ASYNC, OK);
1154 socket_factory_.AddSSLSocketDataProvider(&ssl);
1155
Matt Menkeaade5812019-03-02 13:38:001156 TestConnectJobDelegate test_delegate;
1157 std::unique_ptr<ConnectJob> ssl_connect_job =
1158 CreateConnectJob(&test_delegate, ProxyServer::SCHEME_HTTP);
1159 ASSERT_THAT(ssl_connect_job->Connect(), test::IsError(ERR_IO_PENDING));
1160 EXPECT_TRUE(host_resolver_.has_pending_requests());
1161 EXPECT_EQ(LOAD_STATE_RESOLVING_HOST, ssl_connect_job->GetLoadState());
1162 EXPECT_FALSE(ssl_connect_job->HasEstablishedConnection());
1163
1164 // DNS resolution completes, and then the ConnectJob tries to connect the
1165 // socket, which should succeed asynchronously.
1166 host_resolver_.ResolveOnlyRequestNow();
1167 EXPECT_EQ(LOAD_STATE_CONNECTING, ssl_connect_job->GetLoadState());
1168 EXPECT_FALSE(ssl_connect_job->HasEstablishedConnection());
1169
1170 // Spinning the message loop causes the connection to be established and the
1171 // nested HttpProxyConnectJob to start establishing a tunnel.
1172 base::RunLoop().RunUntilIdle();
1173 EXPECT_FALSE(test_delegate.has_result());
1174 EXPECT_EQ(LOAD_STATE_ESTABLISHING_PROXY_TUNNEL,
1175 ssl_connect_job->GetLoadState());
1176 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
1177
1178 // Receive the auth challenge.
1179 data1.Resume();
1180 test_delegate.WaitForAuthChallenge(1);
1181 EXPECT_FALSE(test_delegate.has_result());
1182 EXPECT_EQ(LOAD_STATE_IDLE, ssl_connect_job->GetLoadState());
1183 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
1184
1185 // Respond to challenge.
1186 test_delegate.auth_controller()->ResetAuth(
1187 AuthCredentials(base::ASCIIToUTF16("foo"), base::ASCIIToUTF16("bar")));
1188 test_delegate.RunAuthCallback();
1189 EXPECT_FALSE(test_delegate.has_result());
1190 EXPECT_EQ(LOAD_STATE_ESTABLISHING_PROXY_TUNNEL,
1191 ssl_connect_job->GetLoadState());
1192 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
1193
1194 // Run until the next DNS lookup.
1195 base::RunLoop().RunUntilIdle();
1196 EXPECT_TRUE(host_resolver_.has_pending_requests());
1197 EXPECT_EQ(LOAD_STATE_RESOLVING_HOST, ssl_connect_job->GetLoadState());
1198 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
1199
1200 // DNS resolution completes, and then the ConnectJob tries to connect the
1201 // socket, which should succeed asynchronously.
1202 host_resolver_.ResolveOnlyRequestNow();
1203 EXPECT_EQ(LOAD_STATE_CONNECTING, ssl_connect_job->GetLoadState());
1204 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
1205
1206 // Spinning the message loop causes the connection to be established and the
1207 // nested HttpProxyConnectJob to start establishing a tunnel.
1208 base::RunLoop().RunUntilIdle();
1209 EXPECT_FALSE(test_delegate.has_result());
1210 EXPECT_EQ(LOAD_STATE_ESTABLISHING_PROXY_TUNNEL,
1211 ssl_connect_job->GetLoadState());
1212 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
1213
1214 // Receive the connection established response, at which point SSL negotiation
1215 // finally starts.
1216 data2.Resume();
1217 EXPECT_FALSE(test_delegate.has_result());
1218 EXPECT_EQ(LOAD_STATE_SSL_HANDSHAKE, ssl_connect_job->GetLoadState());
1219 EXPECT_TRUE(ssl_connect_job->HasEstablishedConnection());
1220
1221 EXPECT_THAT(test_delegate.WaitForResult(), test::IsOk());
1222}
1223
Matt Menke7b5051072019-01-27 21:22:491224} // namespace
1225} // namespace net