ssl_client_socket_pool_unittest.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
1// Copyright (c) 2012 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/http/http_proxy_client_socket_pool.h"
6
7#include "base/callback.h"
8#include "base/compiler_specific.h"
9#include "base/string_util.h"
10#include "base/time.h"
11#include "base/utf_string_conversions.h"
12#include "net/base/auth.h"
13#include "net/base/load_timing_info.h"
14#include "net/base/load_timing_info_test_util.h"
15#include "net/base/net_errors.h"
16#include "net/base/test_completion_callback.h"
17#include "net/cert/cert_verifier.h"
18#include "net/dns/mock_host_resolver.h"
19#include "net/http/http_auth_handler_factory.h"
20#include "net/http/http_network_session.h"
21#include "net/http/http_request_headers.h"
22#include "net/http/http_response_headers.h"
23#include "net/http/http_server_properties_impl.h"
24#include "net/proxy/proxy_service.h"
25#include "net/socket/client_socket_handle.h"
26#include "net/socket/client_socket_pool_histograms.h"
27#include "net/socket/socket_test_util.h"
28#include "net/spdy/spdy_session.h"
29#include "net/spdy/spdy_session_pool.h"
30#include "net/spdy/spdy_test_util_spdy2.h"
31#include "net/ssl/ssl_config_service_defaults.h"
32#include "net/test/test_certificate_data.h"
33#include "testing/gtest/include/gtest/gtest.h"
34
35using namespace net::test_spdy2;
36
37namespace net {
38
39namespace {
40
41const int kMaxSockets = 32;
42const int kMaxSocketsPerGroup = 6;
43
44// Make sure |handle|'s load times are set correctly.  DNS and connect start
45// times comes from mock client sockets in these tests, so primarily serves to
46// check those times were copied, and ssl times / connect end are set correctly.
47void TestLoadTimingInfo(const ClientSocketHandle& handle) {
48  LoadTimingInfo load_timing_info;
49  EXPECT_TRUE(handle.GetLoadTimingInfo(false, &load_timing_info));
50
51  EXPECT_FALSE(load_timing_info.socket_reused);
52  // None of these tests use a NetLog.
53  EXPECT_EQ(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
54
55  ExpectConnectTimingHasTimes(
56      load_timing_info.connect_timing,
57      CONNECT_TIMING_HAS_SSL_TIMES | CONNECT_TIMING_HAS_DNS_TIMES);
58  ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
59}
60
61// Just like TestLoadTimingInfo, except DNS times are expected to be null, for
62// tests over proxies that do DNS lookups themselves.
63void TestLoadTimingInfoNoDns(const ClientSocketHandle& handle) {
64  LoadTimingInfo load_timing_info;
65  EXPECT_TRUE(handle.GetLoadTimingInfo(false, &load_timing_info));
66
67  // None of these tests use a NetLog.
68  EXPECT_EQ(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
69
70  EXPECT_FALSE(load_timing_info.socket_reused);
71
72  ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
73                              CONNECT_TIMING_HAS_SSL_TIMES);
74  ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
75}
76
77class SSLClientSocketPoolTest : public testing::Test {
78 protected:
79  SSLClientSocketPoolTest()
80      : proxy_service_(ProxyService::CreateDirect()),
81        ssl_config_service_(new SSLConfigServiceDefaults),
82        http_auth_handler_factory_(
83            HttpAuthHandlerFactory::CreateDefault(&host_resolver_)),
84        session_(CreateNetworkSession()),
85        direct_transport_socket_params_(
86            new TransportSocketParams(HostPortPair("host", 443),
87                                      MEDIUM,
88                                      false,
89                                      false,
90                                      OnHostResolutionCallback())),
91        transport_histograms_("MockTCP"),
92        transport_socket_pool_(kMaxSockets,
93                               kMaxSocketsPerGroup,
94                               &transport_histograms_,
95                               &socket_factory_),
96        proxy_transport_socket_params_(
97            new TransportSocketParams(HostPortPair("proxy", 443),
98                                      MEDIUM,
99                                      false,
100                                      false,
101                                      OnHostResolutionCallback())),
102        socks_socket_params_(
103            new SOCKSSocketParams(proxy_transport_socket_params_,
104                                  true,
105                                  HostPortPair("sockshost", 443),
106                                  MEDIUM)),
107        socks_histograms_("MockSOCKS"),
108        socks_socket_pool_(kMaxSockets,
109                           kMaxSocketsPerGroup,
110                           &socks_histograms_,
111                           &transport_socket_pool_),
112        http_proxy_socket_params_(
113            new HttpProxySocketParams(proxy_transport_socket_params_,
114                                      NULL,
115                                      GURL("http://host"),
116                                      std::string(),
117                                      HostPortPair("host", 80),
118                                      session_->http_auth_cache(),
119                                      session_->http_auth_handler_factory(),
120                                      session_->spdy_session_pool(),
121                                      true)),
122        http_proxy_histograms_("MockHttpProxy"),
123        http_proxy_socket_pool_(kMaxSockets,
124                                kMaxSocketsPerGroup,
125                                &http_proxy_histograms_,
126                                &host_resolver_,
127                                &transport_socket_pool_,
128                                NULL,
129                                NULL) {
130    scoped_refptr<SSLConfigService> ssl_config_service(
131        new SSLConfigServiceDefaults);
132    ssl_config_service->GetSSLConfig(&ssl_config_);
133  }
134
135  void CreatePool(bool transport_pool, bool http_proxy_pool, bool socks_pool) {
136    ssl_histograms_.reset(new ClientSocketPoolHistograms("SSLUnitTest"));
137    pool_.reset(new SSLClientSocketPool(
138        kMaxSockets,
139        kMaxSocketsPerGroup,
140        ssl_histograms_.get(),
141        NULL /* host_resolver */,
142        NULL /* cert_verifier */,
143        NULL /* server_bound_cert_service */,
144        NULL /* transport_security_state */,
145        std::string() /* ssl_session_cache_shard */,
146        &socket_factory_,
147        transport_pool ? &transport_socket_pool_ : NULL,
148        socks_pool ? &socks_socket_pool_ : NULL,
149        http_proxy_pool ? &http_proxy_socket_pool_ : NULL,
150        NULL,
151        NULL));
152  }
153
154  scoped_refptr<SSLSocketParams> SSLParams(ProxyServer::Scheme proxy,
155                                           bool want_spdy_over_npn) {
156    return make_scoped_refptr(new SSLSocketParams(
157        proxy == ProxyServer::SCHEME_DIRECT ?
158            direct_transport_socket_params_ : NULL,
159        proxy == ProxyServer::SCHEME_SOCKS5 ? socks_socket_params_ : NULL,
160        proxy == ProxyServer::SCHEME_HTTP ? http_proxy_socket_params_ : NULL,
161        proxy,
162        HostPortPair("host", 443),
163        ssl_config_,
164        0,
165        false,
166        want_spdy_over_npn));
167  }
168
169  void AddAuthToCache() {
170    const base::string16 kFoo(ASCIIToUTF16("foo"));
171    const base::string16 kBar(ASCIIToUTF16("bar"));
172    session_->http_auth_cache()->Add(GURL("http://proxy:443/"),
173                                     "MyRealm1",
174                                     HttpAuth::AUTH_SCHEME_BASIC,
175                                     "Basic realm=MyRealm1",
176                                     AuthCredentials(kFoo, kBar),
177                                     "/");
178  }
179
180  HttpNetworkSession* CreateNetworkSession() {
181    HttpNetworkSession::Params params;
182    params.host_resolver = &host_resolver_;
183    params.cert_verifier = cert_verifier_.get();
184    params.proxy_service = proxy_service_.get();
185    params.client_socket_factory = &socket_factory_;
186    params.ssl_config_service = ssl_config_service_;
187    params.http_auth_handler_factory = http_auth_handler_factory_.get();
188    params.http_server_properties = &http_server_properties_;
189    params.enable_spdy_compression = false;
190    return new HttpNetworkSession(params);
191  }
192
193  void TestIPPoolingDisabled(SSLSocketDataProvider* ssl);
194
195  MockClientSocketFactory socket_factory_;
196  MockCachingHostResolver host_resolver_;
197  scoped_ptr<CertVerifier> cert_verifier_;
198  const scoped_ptr<ProxyService> proxy_service_;
199  const scoped_refptr<SSLConfigService> ssl_config_service_;
200  const scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory_;
201  HttpServerPropertiesImpl http_server_properties_;
202  const scoped_refptr<HttpNetworkSession> session_;
203
204  scoped_refptr<TransportSocketParams> direct_transport_socket_params_;
205  ClientSocketPoolHistograms transport_histograms_;
206  MockTransportClientSocketPool transport_socket_pool_;
207
208  scoped_refptr<TransportSocketParams> proxy_transport_socket_params_;
209
210  scoped_refptr<SOCKSSocketParams> socks_socket_params_;
211  ClientSocketPoolHistograms socks_histograms_;
212  MockSOCKSClientSocketPool socks_socket_pool_;
213
214  scoped_refptr<HttpProxySocketParams> http_proxy_socket_params_;
215  ClientSocketPoolHistograms http_proxy_histograms_;
216  HttpProxyClientSocketPool http_proxy_socket_pool_;
217
218  SSLConfig ssl_config_;
219  scoped_ptr<ClientSocketPoolHistograms> ssl_histograms_;
220  scoped_ptr<SSLClientSocketPool> pool_;
221};
222
223TEST_F(SSLClientSocketPoolTest, TCPFail) {
224  StaticSocketDataProvider data;
225  data.set_connect_data(MockConnect(SYNCHRONOUS, ERR_CONNECTION_FAILED));
226  socket_factory_.AddSocketDataProvider(&data);
227
228  CreatePool(true /* tcp pool */, false, false);
229  scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT,
230                                                    false);
231
232  ClientSocketHandle handle;
233  int rv = handle.Init("a", params, MEDIUM, CompletionCallback(), pool_.get(),
234                       BoundNetLog());
235  EXPECT_EQ(ERR_CONNECTION_FAILED, rv);
236  EXPECT_FALSE(handle.is_initialized());
237  EXPECT_FALSE(handle.socket());
238  EXPECT_FALSE(handle.is_ssl_error());
239}
240
241TEST_F(SSLClientSocketPoolTest, TCPFailAsync) {
242  StaticSocketDataProvider data;
243  data.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_FAILED));
244  socket_factory_.AddSocketDataProvider(&data);
245
246  CreatePool(true /* tcp pool */, false, false);
247  scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT,
248                                                    false);
249
250  ClientSocketHandle handle;
251  TestCompletionCallback callback;
252  int rv = handle.Init(
253      "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
254  EXPECT_EQ(ERR_IO_PENDING, rv);
255  EXPECT_FALSE(handle.is_initialized());
256  EXPECT_FALSE(handle.socket());
257
258  EXPECT_EQ(ERR_CONNECTION_FAILED, callback.WaitForResult());
259  EXPECT_FALSE(handle.is_initialized());
260  EXPECT_FALSE(handle.socket());
261  EXPECT_FALSE(handle.is_ssl_error());
262}
263
264TEST_F(SSLClientSocketPoolTest, BasicDirect) {
265  StaticSocketDataProvider data;
266  data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
267  socket_factory_.AddSocketDataProvider(&data);
268  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
269  socket_factory_.AddSSLSocketDataProvider(&ssl);
270
271  CreatePool(true /* tcp pool */, false, false);
272  scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT,
273                                                    false);
274
275  ClientSocketHandle handle;
276  TestCompletionCallback callback;
277  int rv = handle.Init(
278      "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
279  EXPECT_EQ(OK, rv);
280  EXPECT_TRUE(handle.is_initialized());
281  EXPECT_TRUE(handle.socket());
282  TestLoadTimingInfo(handle);
283}
284
285TEST_F(SSLClientSocketPoolTest, BasicDirectAsync) {
286  StaticSocketDataProvider data;
287  socket_factory_.AddSocketDataProvider(&data);
288  SSLSocketDataProvider ssl(ASYNC, OK);
289  socket_factory_.AddSSLSocketDataProvider(&ssl);
290
291  CreatePool(true /* tcp pool */, false, false);
292  scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT,
293                                                    false);
294
295  ClientSocketHandle handle;
296  TestCompletionCallback callback;
297  int rv = handle.Init(
298      "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
299  EXPECT_EQ(ERR_IO_PENDING, rv);
300  EXPECT_FALSE(handle.is_initialized());
301  EXPECT_FALSE(handle.socket());
302
303  EXPECT_EQ(OK, callback.WaitForResult());
304  EXPECT_TRUE(handle.is_initialized());
305  EXPECT_TRUE(handle.socket());
306  TestLoadTimingInfo(handle);
307}
308
309TEST_F(SSLClientSocketPoolTest, DirectCertError) {
310  StaticSocketDataProvider data;
311  socket_factory_.AddSocketDataProvider(&data);
312  SSLSocketDataProvider ssl(ASYNC, ERR_CERT_COMMON_NAME_INVALID);
313  socket_factory_.AddSSLSocketDataProvider(&ssl);
314
315  CreatePool(true /* tcp pool */, false, false);
316  scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT,
317                                                    false);
318
319  ClientSocketHandle handle;
320  TestCompletionCallback callback;
321  int rv = handle.Init(
322      "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
323  EXPECT_EQ(ERR_IO_PENDING, rv);
324  EXPECT_FALSE(handle.is_initialized());
325  EXPECT_FALSE(handle.socket());
326
327  EXPECT_EQ(ERR_CERT_COMMON_NAME_INVALID, callback.WaitForResult());
328  EXPECT_TRUE(handle.is_initialized());
329  EXPECT_TRUE(handle.socket());
330  TestLoadTimingInfo(handle);
331}
332
333TEST_F(SSLClientSocketPoolTest, DirectSSLError) {
334  StaticSocketDataProvider data;
335  socket_factory_.AddSocketDataProvider(&data);
336  SSLSocketDataProvider ssl(ASYNC, ERR_SSL_PROTOCOL_ERROR);
337  socket_factory_.AddSSLSocketDataProvider(&ssl);
338
339  CreatePool(true /* tcp pool */, false, false);
340  scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT,
341                                                    false);
342
343  ClientSocketHandle handle;
344  TestCompletionCallback callback;
345  int rv = handle.Init(
346      "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
347  EXPECT_EQ(ERR_IO_PENDING, rv);
348  EXPECT_FALSE(handle.is_initialized());
349  EXPECT_FALSE(handle.socket());
350
351  EXPECT_EQ(ERR_SSL_PROTOCOL_ERROR, callback.WaitForResult());
352  EXPECT_FALSE(handle.is_initialized());
353  EXPECT_FALSE(handle.socket());
354  EXPECT_TRUE(handle.is_ssl_error());
355}
356
357TEST_F(SSLClientSocketPoolTest, DirectWithNPN) {
358  StaticSocketDataProvider data;
359  socket_factory_.AddSocketDataProvider(&data);
360  SSLSocketDataProvider ssl(ASYNC, OK);
361  ssl.SetNextProto(kProtoHTTP11);
362  socket_factory_.AddSSLSocketDataProvider(&ssl);
363
364  CreatePool(true /* tcp pool */, false, false);
365  scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT,
366                                                    false);
367
368  ClientSocketHandle handle;
369  TestCompletionCallback callback;
370  int rv = handle.Init(
371      "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
372  EXPECT_EQ(ERR_IO_PENDING, rv);
373  EXPECT_FALSE(handle.is_initialized());
374  EXPECT_FALSE(handle.socket());
375
376  EXPECT_EQ(OK, callback.WaitForResult());
377  EXPECT_TRUE(handle.is_initialized());
378  EXPECT_TRUE(handle.socket());
379  TestLoadTimingInfo(handle);
380  SSLClientSocket* ssl_socket = static_cast<SSLClientSocket*>(handle.socket());
381  EXPECT_TRUE(ssl_socket->WasNpnNegotiated());
382}
383
384TEST_F(SSLClientSocketPoolTest, DirectNoSPDY) {
385  StaticSocketDataProvider data;
386  socket_factory_.AddSocketDataProvider(&data);
387  SSLSocketDataProvider ssl(ASYNC, OK);
388  ssl.SetNextProto(kProtoHTTP11);
389  socket_factory_.AddSSLSocketDataProvider(&ssl);
390
391  CreatePool(true /* tcp pool */, false, false);
392  scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT,
393                                                    true);
394
395  ClientSocketHandle handle;
396  TestCompletionCallback callback;
397  int rv = handle.Init(
398      "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
399  EXPECT_EQ(ERR_IO_PENDING, rv);
400  EXPECT_FALSE(handle.is_initialized());
401  EXPECT_FALSE(handle.socket());
402
403  EXPECT_EQ(ERR_NPN_NEGOTIATION_FAILED, callback.WaitForResult());
404  EXPECT_FALSE(handle.is_initialized());
405  EXPECT_FALSE(handle.socket());
406  EXPECT_TRUE(handle.is_ssl_error());
407}
408
409TEST_F(SSLClientSocketPoolTest, DirectGotSPDY) {
410  StaticSocketDataProvider data;
411  socket_factory_.AddSocketDataProvider(&data);
412  SSLSocketDataProvider ssl(ASYNC, OK);
413  ssl.SetNextProto(kProtoSPDY2);
414  socket_factory_.AddSSLSocketDataProvider(&ssl);
415
416  CreatePool(true /* tcp pool */, false, false);
417  scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT,
418                                                    true);
419
420  ClientSocketHandle handle;
421  TestCompletionCallback callback;
422  int rv = handle.Init(
423      "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
424  EXPECT_EQ(ERR_IO_PENDING, rv);
425  EXPECT_FALSE(handle.is_initialized());
426  EXPECT_FALSE(handle.socket());
427
428  EXPECT_EQ(OK, callback.WaitForResult());
429  EXPECT_TRUE(handle.is_initialized());
430  EXPECT_TRUE(handle.socket());
431  TestLoadTimingInfo(handle);
432
433  SSLClientSocket* ssl_socket = static_cast<SSLClientSocket*>(handle.socket());
434  EXPECT_TRUE(ssl_socket->WasNpnNegotiated());
435  std::string proto;
436  std::string server_protos;
437  ssl_socket->GetNextProto(&proto, &server_protos);
438  EXPECT_EQ(SSLClientSocket::NextProtoFromString(proto),
439            kProtoSPDY2);
440}
441
442TEST_F(SSLClientSocketPoolTest, DirectGotBonusSPDY) {
443  StaticSocketDataProvider data;
444  socket_factory_.AddSocketDataProvider(&data);
445  SSLSocketDataProvider ssl(ASYNC, OK);
446  ssl.SetNextProto(kProtoSPDY2);
447  socket_factory_.AddSSLSocketDataProvider(&ssl);
448
449  CreatePool(true /* tcp pool */, false, false);
450  scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT,
451                                                    true);
452
453  ClientSocketHandle handle;
454  TestCompletionCallback callback;
455  int rv = handle.Init(
456      "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
457  EXPECT_EQ(ERR_IO_PENDING, rv);
458  EXPECT_FALSE(handle.is_initialized());
459  EXPECT_FALSE(handle.socket());
460
461  EXPECT_EQ(OK, callback.WaitForResult());
462  EXPECT_TRUE(handle.is_initialized());
463  EXPECT_TRUE(handle.socket());
464  TestLoadTimingInfo(handle);
465
466  SSLClientSocket* ssl_socket = static_cast<SSLClientSocket*>(handle.socket());
467  EXPECT_TRUE(ssl_socket->WasNpnNegotiated());
468  std::string proto;
469  std::string server_protos;
470  ssl_socket->GetNextProto(&proto, &server_protos);
471  EXPECT_EQ(SSLClientSocket::NextProtoFromString(proto),
472            kProtoSPDY2);
473}
474
475TEST_F(SSLClientSocketPoolTest, SOCKSFail) {
476  StaticSocketDataProvider data;
477  data.set_connect_data(MockConnect(SYNCHRONOUS, ERR_CONNECTION_FAILED));
478  socket_factory_.AddSocketDataProvider(&data);
479
480  CreatePool(false, true /* http proxy pool */, true /* socks pool */);
481  scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_SOCKS5,
482                                                    false);
483
484  ClientSocketHandle handle;
485  TestCompletionCallback callback;
486  int rv = handle.Init(
487      "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
488  EXPECT_EQ(ERR_CONNECTION_FAILED, rv);
489  EXPECT_FALSE(handle.is_initialized());
490  EXPECT_FALSE(handle.socket());
491  EXPECT_FALSE(handle.is_ssl_error());
492}
493
494TEST_F(SSLClientSocketPoolTest, SOCKSFailAsync) {
495  StaticSocketDataProvider data;
496  data.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_FAILED));
497  socket_factory_.AddSocketDataProvider(&data);
498
499  CreatePool(false, true /* http proxy pool */, true /* socks pool */);
500  scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_SOCKS5,
501                                                    false);
502
503  ClientSocketHandle handle;
504  TestCompletionCallback callback;
505  int rv = handle.Init(
506      "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
507  EXPECT_EQ(ERR_IO_PENDING, rv);
508  EXPECT_FALSE(handle.is_initialized());
509  EXPECT_FALSE(handle.socket());
510
511  EXPECT_EQ(ERR_CONNECTION_FAILED, callback.WaitForResult());
512  EXPECT_FALSE(handle.is_initialized());
513  EXPECT_FALSE(handle.socket());
514  EXPECT_FALSE(handle.is_ssl_error());
515}
516
517TEST_F(SSLClientSocketPoolTest, SOCKSBasic) {
518  StaticSocketDataProvider data;
519  data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
520  socket_factory_.AddSocketDataProvider(&data);
521  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
522  socket_factory_.AddSSLSocketDataProvider(&ssl);
523
524  CreatePool(false, true /* http proxy pool */, true /* socks pool */);
525  scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_SOCKS5,
526                                                    false);
527
528  ClientSocketHandle handle;
529  TestCompletionCallback callback;
530  int rv = handle.Init(
531      "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
532  EXPECT_EQ(OK, rv);
533  EXPECT_TRUE(handle.is_initialized());
534  EXPECT_TRUE(handle.socket());
535  // SOCKS5 generally has no DNS times, but the mock SOCKS5 sockets used here
536  // don't go through the real logic, unlike in the HTTP proxy tests.
537  TestLoadTimingInfo(handle);
538}
539
540TEST_F(SSLClientSocketPoolTest, SOCKSBasicAsync) {
541  StaticSocketDataProvider data;
542  socket_factory_.AddSocketDataProvider(&data);
543  SSLSocketDataProvider ssl(ASYNC, OK);
544  socket_factory_.AddSSLSocketDataProvider(&ssl);
545
546  CreatePool(false, true /* http proxy pool */, true /* socks pool */);
547  scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_SOCKS5,
548                                                    false);
549
550  ClientSocketHandle handle;
551  TestCompletionCallback callback;
552  int rv = handle.Init(
553      "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
554  EXPECT_EQ(ERR_IO_PENDING, rv);
555  EXPECT_FALSE(handle.is_initialized());
556  EXPECT_FALSE(handle.socket());
557
558  EXPECT_EQ(OK, callback.WaitForResult());
559  EXPECT_TRUE(handle.is_initialized());
560  EXPECT_TRUE(handle.socket());
561  // SOCKS5 generally has no DNS times, but the mock SOCKS5 sockets used here
562  // don't go through the real logic, unlike in the HTTP proxy tests.
563  TestLoadTimingInfo(handle);
564}
565
566TEST_F(SSLClientSocketPoolTest, HttpProxyFail) {
567  StaticSocketDataProvider data;
568  data.set_connect_data(MockConnect(SYNCHRONOUS, ERR_CONNECTION_FAILED));
569  socket_factory_.AddSocketDataProvider(&data);
570
571  CreatePool(false, true /* http proxy pool */, true /* socks pool */);
572  scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_HTTP,
573                                                    false);
574
575  ClientSocketHandle handle;
576  TestCompletionCallback callback;
577  int rv = handle.Init(
578      "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
579  EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
580  EXPECT_FALSE(handle.is_initialized());
581  EXPECT_FALSE(handle.socket());
582  EXPECT_FALSE(handle.is_ssl_error());
583}
584
585TEST_F(SSLClientSocketPoolTest, HttpProxyFailAsync) {
586  StaticSocketDataProvider data;
587  data.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_FAILED));
588  socket_factory_.AddSocketDataProvider(&data);
589
590  CreatePool(false, true /* http proxy pool */, true /* socks pool */);
591  scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_HTTP,
592                                                    false);
593
594  ClientSocketHandle handle;
595  TestCompletionCallback callback;
596  int rv = handle.Init(
597      "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
598  EXPECT_EQ(ERR_IO_PENDING, rv);
599  EXPECT_FALSE(handle.is_initialized());
600  EXPECT_FALSE(handle.socket());
601
602  EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, callback.WaitForResult());
603  EXPECT_FALSE(handle.is_initialized());
604  EXPECT_FALSE(handle.socket());
605  EXPECT_FALSE(handle.is_ssl_error());
606}
607
608TEST_F(SSLClientSocketPoolTest, HttpProxyBasic) {
609  MockWrite writes[] = {
610      MockWrite(SYNCHRONOUS,
611                "CONNECT host:80 HTTP/1.1\r\n"
612                "Host: host\r\n"
613                "Proxy-Connection: keep-alive\r\n"
614                "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
615  };
616  MockRead reads[] = {
617      MockRead(SYNCHRONOUS, "HTTP/1.1 200 Connection Established\r\n\r\n"),
618  };
619  StaticSocketDataProvider data(reads, arraysize(reads), writes,
620                                arraysize(writes));
621  data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
622  socket_factory_.AddSocketDataProvider(&data);
623  AddAuthToCache();
624  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
625  socket_factory_.AddSSLSocketDataProvider(&ssl);
626
627  CreatePool(false, true /* http proxy pool */, true /* socks pool */);
628  scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_HTTP,
629                                                    false);
630
631  ClientSocketHandle handle;
632  TestCompletionCallback callback;
633  int rv = handle.Init(
634      "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
635  EXPECT_EQ(OK, rv);
636  EXPECT_TRUE(handle.is_initialized());
637  EXPECT_TRUE(handle.socket());
638  TestLoadTimingInfoNoDns(handle);
639}
640
641TEST_F(SSLClientSocketPoolTest, HttpProxyBasicAsync) {
642  MockWrite writes[] = {
643      MockWrite("CONNECT host:80 HTTP/1.1\r\n"
644                "Host: host\r\n"
645                "Proxy-Connection: keep-alive\r\n"
646                "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
647  };
648  MockRead reads[] = {
649      MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
650  };
651  StaticSocketDataProvider data(reads, arraysize(reads), writes,
652                                arraysize(writes));
653  socket_factory_.AddSocketDataProvider(&data);
654  AddAuthToCache();
655  SSLSocketDataProvider ssl(ASYNC, OK);
656  socket_factory_.AddSSLSocketDataProvider(&ssl);
657
658  CreatePool(false, true /* http proxy pool */, true /* socks pool */);
659  scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_HTTP,
660                                                    false);
661
662  ClientSocketHandle handle;
663  TestCompletionCallback callback;
664  int rv = handle.Init(
665      "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
666  EXPECT_EQ(ERR_IO_PENDING, rv);
667  EXPECT_FALSE(handle.is_initialized());
668  EXPECT_FALSE(handle.socket());
669
670  EXPECT_EQ(OK, callback.WaitForResult());
671  EXPECT_TRUE(handle.is_initialized());
672  EXPECT_TRUE(handle.socket());
673  TestLoadTimingInfoNoDns(handle);
674}
675
676TEST_F(SSLClientSocketPoolTest, NeedProxyAuth) {
677  MockWrite writes[] = {
678      MockWrite("CONNECT host:80 HTTP/1.1\r\n"
679                "Host: host\r\n"
680                "Proxy-Connection: keep-alive\r\n\r\n"),
681  };
682  MockRead reads[] = {
683      MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
684      MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
685      MockRead("Content-Length: 10\r\n\r\n"),
686      MockRead("0123456789"),
687  };
688  StaticSocketDataProvider data(reads, arraysize(reads), writes,
689                                arraysize(writes));
690  socket_factory_.AddSocketDataProvider(&data);
691  SSLSocketDataProvider ssl(ASYNC, OK);
692  socket_factory_.AddSSLSocketDataProvider(&ssl);
693
694  CreatePool(false, true /* http proxy pool */, true /* socks pool */);
695  scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_HTTP,
696                                                    false);
697
698  ClientSocketHandle handle;
699  TestCompletionCallback callback;
700  int rv = handle.Init(
701      "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
702  EXPECT_EQ(ERR_IO_PENDING, rv);
703  EXPECT_FALSE(handle.is_initialized());
704  EXPECT_FALSE(handle.socket());
705
706  EXPECT_EQ(ERR_PROXY_AUTH_REQUESTED, callback.WaitForResult());
707  EXPECT_FALSE(handle.is_initialized());
708  EXPECT_FALSE(handle.socket());
709  EXPECT_FALSE(handle.is_ssl_error());
710  const HttpResponseInfo& tunnel_info = handle.ssl_error_response_info();
711  EXPECT_EQ(tunnel_info.headers->response_code(), 407);
712  scoped_ptr<ClientSocketHandle> tunnel_handle(
713      handle.release_pending_http_proxy_connection());
714  EXPECT_TRUE(tunnel_handle->socket());
715  EXPECT_FALSE(tunnel_handle->socket()->IsConnected());
716}
717
718TEST_F(SSLClientSocketPoolTest, IPPooling) {
719  const int kTestPort = 80;
720  struct TestHosts {
721    std::string name;
722    std::string iplist;
723    SpdySessionKey key;
724    AddressList addresses;
725  } test_hosts[] = {
726    { "www.webkit.org",    "192.0.2.33,192.168.0.1,192.168.0.5" },
727    { "code.google.com",   "192.168.0.2,192.168.0.3,192.168.0.5" },
728    { "js.webkit.org",     "192.168.0.4,192.168.0.1,192.0.2.33" },
729  };
730
731  host_resolver_.set_synchronous_mode(true);
732  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_hosts); i++) {
733    host_resolver_.rules()->AddIPLiteralRule(
734        test_hosts[i].name, test_hosts[i].iplist, std::string());
735
736    // This test requires that the HostResolver cache be populated.  Normal
737    // code would have done this already, but we do it manually.
738    HostResolver::RequestInfo info(HostPortPair(test_hosts[i].name, kTestPort));
739    host_resolver_.Resolve(info, &test_hosts[i].addresses, CompletionCallback(),
740                           NULL, BoundNetLog());
741
742    // Setup a SpdySessionKey
743    test_hosts[i].key = SpdySessionKey(
744        HostPortPair(test_hosts[i].name, kTestPort), ProxyServer::Direct(),
745        kPrivacyModeDisabled);
746  }
747
748  MockRead reads[] = {
749      MockRead(ASYNC, ERR_IO_PENDING),
750  };
751  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
752  socket_factory_.AddSocketDataProvider(&data);
753  SSLSocketDataProvider ssl(ASYNC, OK);
754  ssl.cert = X509Certificate::CreateFromBytes(
755      reinterpret_cast<const char*>(webkit_der), sizeof(webkit_der));
756  ssl.SetNextProto(kProtoSPDY2);
757  socket_factory_.AddSSLSocketDataProvider(&ssl);
758
759  CreatePool(true /* tcp pool */, false, false);
760  scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT,
761                                                    true);
762
763  scoped_ptr<ClientSocketHandle> handle(new ClientSocketHandle());
764  TestCompletionCallback callback;
765  int rv = handle->Init(
766      "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
767  EXPECT_EQ(ERR_IO_PENDING, rv);
768  EXPECT_FALSE(handle->is_initialized());
769  EXPECT_FALSE(handle->socket());
770
771  EXPECT_EQ(OK, callback.WaitForResult());
772  EXPECT_TRUE(handle->is_initialized());
773  EXPECT_TRUE(handle->socket());
774
775  SSLClientSocket* ssl_socket = static_cast<SSLClientSocket*>(handle->socket());
776  EXPECT_TRUE(ssl_socket->WasNpnNegotiated());
777  std::string proto;
778  std::string server_protos;
779  ssl_socket->GetNextProto(&proto, &server_protos);
780  EXPECT_EQ(SSLClientSocket::NextProtoFromString(proto),
781            kProtoSPDY2);
782
783  // TODO(rtenneti): MockClientSocket::GetPeerAddress returns 0 as the port
784  // number. Fix it to return port 80 and then use GetPeerAddress to AddAlias.
785  SpdySessionPoolPeer pool_peer(session_->spdy_session_pool());
786  pool_peer.AddAlias(test_hosts[0].addresses.front(), test_hosts[0].key);
787
788  scoped_refptr<SpdySession> spdy_session;
789  rv = session_->spdy_session_pool()->GetSpdySessionFromSocket(
790    test_hosts[0].key, handle.release(), BoundNetLog(), 0,
791      &spdy_session, true);
792  EXPECT_EQ(0, rv);
793
794  EXPECT_TRUE(session_->spdy_session_pool()->HasSession(test_hosts[0].key));
795  EXPECT_FALSE(session_->spdy_session_pool()->HasSession(test_hosts[1].key));
796  EXPECT_TRUE(session_->spdy_session_pool()->HasSession(test_hosts[2].key));
797
798  session_->spdy_session_pool()->CloseAllSessions();
799}
800
801void SSLClientSocketPoolTest::TestIPPoolingDisabled(
802    SSLSocketDataProvider* ssl) {
803  const int kTestPort = 80;
804  struct TestHosts {
805    std::string name;
806    std::string iplist;
807    SpdySessionKey key;
808    AddressList addresses;
809  } test_hosts[] = {
810    { "www.webkit.org",    "192.0.2.33,192.168.0.1,192.168.0.5" },
811    { "js.webkit.com",     "192.168.0.4,192.168.0.1,192.0.2.33" },
812  };
813
814  TestCompletionCallback callback;
815  int rv;
816  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_hosts); i++) {
817    host_resolver_.rules()->AddIPLiteralRule(
818        test_hosts[i].name, test_hosts[i].iplist, std::string());
819
820    // This test requires that the HostResolver cache be populated.  Normal
821    // code would have done this already, but we do it manually.
822    HostResolver::RequestInfo info(HostPortPair(test_hosts[i].name, kTestPort));
823    rv = host_resolver_.Resolve(info, &test_hosts[i].addresses,
824                                callback.callback(), NULL, BoundNetLog());
825    EXPECT_EQ(OK, callback.GetResult(rv));
826
827    // Setup a SpdySessionKey
828    test_hosts[i].key = SpdySessionKey(
829        HostPortPair(test_hosts[i].name, kTestPort), ProxyServer::Direct(),
830        kPrivacyModeDisabled);
831  }
832
833  MockRead reads[] = {
834      MockRead(ASYNC, ERR_IO_PENDING),
835  };
836  StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
837  socket_factory_.AddSocketDataProvider(&data);
838  socket_factory_.AddSSLSocketDataProvider(ssl);
839
840  CreatePool(true /* tcp pool */, false, false);
841  scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT,
842                                                    true);
843
844  scoped_ptr<ClientSocketHandle> handle(new ClientSocketHandle());
845  rv = handle->Init(
846      "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog());
847  EXPECT_EQ(ERR_IO_PENDING, rv);
848  EXPECT_FALSE(handle->is_initialized());
849  EXPECT_FALSE(handle->socket());
850
851  EXPECT_EQ(OK, callback.WaitForResult());
852  EXPECT_TRUE(handle->is_initialized());
853  EXPECT_TRUE(handle->socket());
854
855  SSLClientSocket* ssl_socket = static_cast<SSLClientSocket*>(handle->socket());
856  EXPECT_TRUE(ssl_socket->WasNpnNegotiated());
857  std::string proto;
858  std::string server_protos;
859  ssl_socket->GetNextProto(&proto, &server_protos);
860  EXPECT_EQ(SSLClientSocket::NextProtoFromString(proto),
861            kProtoSPDY2);
862
863  // TODO(rtenneti): MockClientSocket::GetPeerAddress returns 0 as the port
864  // number. Fix it to return port 80 and then use GetPeerAddress to AddAlias.
865  SpdySessionPoolPeer pool_peer(session_->spdy_session_pool());
866  pool_peer.AddAlias(test_hosts[0].addresses.front(), test_hosts[0].key);
867
868  scoped_refptr<SpdySession> spdy_session;
869  rv = session_->spdy_session_pool()->GetSpdySessionFromSocket(
870    test_hosts[0].key, handle.release(), BoundNetLog(), 0,
871      &spdy_session, true);
872  EXPECT_EQ(0, rv);
873
874  EXPECT_TRUE(session_->spdy_session_pool()->HasSession(test_hosts[0].key));
875  EXPECT_FALSE(session_->spdy_session_pool()->HasSession(test_hosts[1].key));
876
877  session_->spdy_session_pool()->CloseAllSessions();
878}
879
880// Verifies that an SSL connection with client authentication disables SPDY IP
881// pooling.
882TEST_F(SSLClientSocketPoolTest, IPPoolingClientCert) {
883  SSLSocketDataProvider ssl(ASYNC, OK);
884  ssl.cert = X509Certificate::CreateFromBytes(
885      reinterpret_cast<const char*>(webkit_der), sizeof(webkit_der));
886  ssl.client_cert_sent = true;
887  ssl.SetNextProto(kProtoSPDY2);
888  TestIPPoolingDisabled(&ssl);
889}
890
891// Verifies that an SSL connection with channel ID disables SPDY IP pooling.
892TEST_F(SSLClientSocketPoolTest, IPPoolingChannelID) {
893  SSLSocketDataProvider ssl(ASYNC, OK);
894  ssl.channel_id_sent = true;
895  ssl.SetNextProto(kProtoSPDY2);
896  TestIPPoolingDisabled(&ssl);
897}
898
899// It would be nice to also test the timeouts in SSLClientSocketPool.
900
901}  // namespace
902
903}  // namespace net
904