• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2006-2008 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_client_socket.h"
6 
7 #include "net/base/address_list.h"
8 #include "net/base/host_resolver.h"
9 #include "net/base/io_buffer.h"
10 #include "net/base/load_log.h"
11 #include "net/base/load_log_unittest.h"
12 #include "net/base/net_errors.h"
13 #include "net/base/ssl_config_service.h"
14 #include "net/base/test_completion_callback.h"
15 #include "net/socket/client_socket_factory.h"
16 #include "net/socket/ssl_test_util.h"
17 #include "net/socket/tcp_client_socket.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "testing/platform_test.h"
20 
21 //-----------------------------------------------------------------------------
22 
23 const net::SSLConfig kDefaultSSLConfig;
24 
25 class SSLClientSocketTest : public PlatformTest {
26  public:
SSLClientSocketTest()27   SSLClientSocketTest()
28     : resolver_(net::CreateSystemHostResolver(NULL)),
29         socket_factory_(net::ClientSocketFactory::GetDefaultFactory()) {
30   }
31 
StartOKServer()32   void StartOKServer() {
33     bool success = server_.Start(net::TestServerLauncher::ProtoHTTP,
34         server_.kHostName, server_.kOKHTTPSPort,
35         FilePath(), server_.GetOKCertPath(), std::wstring());
36     ASSERT_TRUE(success);
37   }
38 
StartMismatchedServer()39   void StartMismatchedServer() {
40     bool success = server_.Start(net::TestServerLauncher::ProtoHTTP,
41         server_.kMismatchedHostName, server_.kOKHTTPSPort,
42         FilePath(), server_.GetOKCertPath(), std::wstring());
43     ASSERT_TRUE(success);
44   }
45 
StartExpiredServer()46   void StartExpiredServer() {
47     bool success = server_.Start(net::TestServerLauncher::ProtoHTTP,
48         server_.kHostName, server_.kBadHTTPSPort,
49         FilePath(), server_.GetExpiredCertPath(), std::wstring());
50     ASSERT_TRUE(success);
51   }
52 
53  protected:
54   scoped_refptr<net::HostResolver> resolver_;
55   net::ClientSocketFactory* socket_factory_;
56   net::TestServerLauncher server_;
57 };
58 
59 //-----------------------------------------------------------------------------
60 
TEST_F(SSLClientSocketTest,Connect)61 TEST_F(SSLClientSocketTest, Connect) {
62   StartOKServer();
63 
64   net::AddressList addr;
65   TestCompletionCallback callback;
66 
67   net::HostResolver::RequestInfo info(server_.kHostName, server_.kOKHTTPSPort);
68   int rv = resolver_->Resolve(info, &addr, NULL, NULL, NULL);
69   EXPECT_EQ(net::OK, rv);
70 
71   net::ClientSocket *transport = new net::TCPClientSocket(addr);
72   rv = transport->Connect(&callback, NULL);
73   if (rv == net::ERR_IO_PENDING)
74     rv = callback.WaitForResult();
75   EXPECT_EQ(net::OK, rv);
76 
77   scoped_ptr<net::SSLClientSocket> sock(
78       socket_factory_->CreateSSLClientSocket(transport,
79           server_.kHostName, kDefaultSSLConfig));
80 
81   EXPECT_FALSE(sock->IsConnected());
82 
83   scoped_refptr<net::LoadLog> log(new net::LoadLog(net::LoadLog::kUnbounded));
84   rv = sock->Connect(&callback, log);
85   EXPECT_TRUE(net::LogContainsBeginEvent(
86       *log, 0, net::LoadLog::TYPE_SSL_CONNECT));
87   if (rv != net::OK) {
88     ASSERT_EQ(net::ERR_IO_PENDING, rv);
89     EXPECT_FALSE(sock->IsConnected());
90     EXPECT_FALSE(net::LogContainsEndEvent(
91         *log, -1, net::LoadLog::TYPE_SSL_CONNECT));
92 
93     rv = callback.WaitForResult();
94     EXPECT_EQ(net::OK, rv);
95   }
96 
97   EXPECT_TRUE(sock->IsConnected());
98   EXPECT_TRUE(net::LogContainsEndEvent(
99       *log, -1, net::LoadLog::TYPE_SSL_CONNECT));
100 
101   sock->Disconnect();
102   EXPECT_FALSE(sock->IsConnected());
103 }
104 
TEST_F(SSLClientSocketTest,ConnectExpired)105 TEST_F(SSLClientSocketTest, ConnectExpired) {
106   StartExpiredServer();
107 
108   net::AddressList addr;
109   TestCompletionCallback callback;
110 
111   net::HostResolver::RequestInfo info(server_.kHostName, server_.kBadHTTPSPort);
112   int rv = resolver_->Resolve(info, &addr, NULL, NULL, NULL);
113   EXPECT_EQ(net::OK, rv);
114 
115   net::ClientSocket *transport = new net::TCPClientSocket(addr);
116   rv = transport->Connect(&callback, NULL);
117   if (rv == net::ERR_IO_PENDING)
118     rv = callback.WaitForResult();
119   EXPECT_EQ(net::OK, rv);
120 
121   scoped_ptr<net::SSLClientSocket> sock(
122       socket_factory_->CreateSSLClientSocket(transport,
123           server_.kHostName, kDefaultSSLConfig));
124 
125   EXPECT_FALSE(sock->IsConnected());
126 
127   scoped_refptr<net::LoadLog> log(new net::LoadLog(net::LoadLog::kUnbounded));
128   rv = sock->Connect(&callback, log);
129   EXPECT_TRUE(net::LogContainsBeginEvent(
130       *log, 0, net::LoadLog::TYPE_SSL_CONNECT));
131   if (rv != net::OK) {
132     ASSERT_EQ(net::ERR_IO_PENDING, rv);
133     EXPECT_FALSE(sock->IsConnected());
134     EXPECT_FALSE(net::LogContainsEndEvent(
135         *log, -1, net::LoadLog::TYPE_SSL_CONNECT));
136 
137     rv = callback.WaitForResult();
138     EXPECT_EQ(net::ERR_CERT_DATE_INVALID, rv);
139   }
140 
141   // We cannot test sock->IsConnected(), as the NSS implementation disconnects
142   // the socket when it encounters an error, whereas other implementations
143   // leave it connected.
144 
145   EXPECT_TRUE(net::LogContainsEndEvent(
146       *log, -1, net::LoadLog::TYPE_SSL_CONNECT));
147 }
148 
TEST_F(SSLClientSocketTest,ConnectMismatched)149 TEST_F(SSLClientSocketTest, ConnectMismatched) {
150   StartMismatchedServer();
151 
152   net::AddressList addr;
153   TestCompletionCallback callback;
154 
155   net::HostResolver::RequestInfo info(server_.kMismatchedHostName,
156                                       server_.kOKHTTPSPort);
157   int rv = resolver_->Resolve(info, &addr, NULL, NULL, NULL);
158   EXPECT_EQ(net::OK, rv);
159 
160   net::ClientSocket *transport = new net::TCPClientSocket(addr);
161   rv = transport->Connect(&callback, NULL);
162   if (rv == net::ERR_IO_PENDING)
163     rv = callback.WaitForResult();
164   EXPECT_EQ(net::OK, rv);
165 
166   scoped_ptr<net::SSLClientSocket> sock(
167       socket_factory_->CreateSSLClientSocket(transport,
168           server_.kMismatchedHostName, kDefaultSSLConfig));
169 
170   EXPECT_FALSE(sock->IsConnected());
171 
172   scoped_refptr<net::LoadLog> log(new net::LoadLog(net::LoadLog::kUnbounded));
173   rv = sock->Connect(&callback, log);
174   EXPECT_TRUE(net::LogContainsBeginEvent(
175       *log, 0, net::LoadLog::TYPE_SSL_CONNECT));
176   if (rv != net::ERR_CERT_COMMON_NAME_INVALID) {
177     ASSERT_EQ(net::ERR_IO_PENDING, rv);
178     EXPECT_FALSE(sock->IsConnected());
179     EXPECT_FALSE(net::LogContainsEndEvent(
180         *log, -1, net::LoadLog::TYPE_SSL_CONNECT));
181 
182     rv = callback.WaitForResult();
183     EXPECT_EQ(net::ERR_CERT_COMMON_NAME_INVALID, rv);
184   }
185 
186   // We cannot test sock->IsConnected(), as the NSS implementation disconnects
187   // the socket when it encounters an error, whereas other implementations
188   // leave it connected.
189 
190   EXPECT_TRUE(net::LogContainsEndEvent(
191       *log, -1, net::LoadLog::TYPE_SSL_CONNECT));
192 }
193 
194 // TODO(wtc): Add unit tests for IsConnectedAndIdle:
195 //   - Server closes an SSL connection (with a close_notify alert message).
196 //   - Server closes the underlying TCP connection directly.
197 //   - Server sends data unexpectedly.
198 
TEST_F(SSLClientSocketTest,Read)199 TEST_F(SSLClientSocketTest, Read) {
200   StartOKServer();
201 
202   net::AddressList addr;
203   TestCompletionCallback callback;
204 
205   net::HostResolver::RequestInfo info(server_.kHostName, server_.kOKHTTPSPort);
206   int rv = resolver_->Resolve(info, &addr, &callback, NULL, NULL);
207   EXPECT_EQ(net::ERR_IO_PENDING, rv);
208 
209   rv = callback.WaitForResult();
210   EXPECT_EQ(net::OK, rv);
211 
212   net::ClientSocket *transport = new net::TCPClientSocket(addr);
213   rv = transport->Connect(&callback, NULL);
214   if (rv == net::ERR_IO_PENDING)
215     rv = callback.WaitForResult();
216   EXPECT_EQ(net::OK, rv);
217 
218   scoped_ptr<net::SSLClientSocket> sock(
219       socket_factory_->CreateSSLClientSocket(transport,
220                                              server_.kHostName,
221                                              kDefaultSSLConfig));
222 
223   rv = sock->Connect(&callback, NULL);
224   if (rv != net::OK) {
225     ASSERT_EQ(net::ERR_IO_PENDING, rv);
226 
227     rv = callback.WaitForResult();
228     EXPECT_EQ(net::OK, rv);
229   }
230   EXPECT_TRUE(sock->IsConnected());
231 
232   const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
233   scoped_refptr<net::IOBuffer> request_buffer =
234       new net::IOBuffer(arraysize(request_text) - 1);
235   memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1);
236 
237   rv = sock->Write(request_buffer, arraysize(request_text) - 1, &callback);
238   EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING);
239 
240   if (rv == net::ERR_IO_PENDING)
241     rv = callback.WaitForResult();
242   EXPECT_EQ(static_cast<int>(arraysize(request_text) - 1), rv);
243 
244   scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(4096);
245   for (;;) {
246     rv = sock->Read(buf, 4096, &callback);
247     EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING);
248 
249     if (rv == net::ERR_IO_PENDING)
250       rv = callback.WaitForResult();
251 
252     EXPECT_GE(rv, 0);
253     if (rv <= 0)
254       break;
255   }
256 }
257 
258 // Test the full duplex mode, with Read and Write pending at the same time.
259 // This test also serves as a regression test for http://crbug.com/29815.
TEST_F(SSLClientSocketTest,Read_FullDuplex)260 TEST_F(SSLClientSocketTest, Read_FullDuplex) {
261   StartOKServer();
262 
263   net::AddressList addr;
264   TestCompletionCallback callback;  // Used for everything except Write.
265   TestCompletionCallback callback2;  // Used for Write only.
266 
267   net::HostResolver::RequestInfo info(server_.kHostName, server_.kOKHTTPSPort);
268   int rv = resolver_->Resolve(info, &addr, &callback, NULL, NULL);
269   EXPECT_EQ(net::ERR_IO_PENDING, rv);
270 
271   rv = callback.WaitForResult();
272   EXPECT_EQ(net::OK, rv);
273 
274   net::ClientSocket *transport = new net::TCPClientSocket(addr);
275   rv = transport->Connect(&callback, NULL);
276   if (rv == net::ERR_IO_PENDING)
277     rv = callback.WaitForResult();
278   EXPECT_EQ(net::OK, rv);
279 
280   scoped_ptr<net::SSLClientSocket> sock(
281       socket_factory_->CreateSSLClientSocket(transport,
282                                              server_.kHostName,
283                                              kDefaultSSLConfig));
284 
285   rv = sock->Connect(&callback, NULL);
286   if (rv != net::OK) {
287     ASSERT_EQ(net::ERR_IO_PENDING, rv);
288 
289     rv = callback.WaitForResult();
290     EXPECT_EQ(net::OK, rv);
291   }
292   EXPECT_TRUE(sock->IsConnected());
293 
294   // Issue a "hanging" Read first.
295   scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(4096);
296   rv = sock->Read(buf, 4096, &callback);
297   // We haven't written the request, so there should be no response yet.
298   ASSERT_EQ(net::ERR_IO_PENDING, rv);
299 
300   // Write the request.
301   // The request is padded with a User-Agent header to a size that causes the
302   // memio circular buffer (4k bytes) in SSLClientSocketNSS to wrap around.
303   // This tests the fix for http://crbug.com/29815.
304   std::string request_text = "GET / HTTP/1.1\r\nUser-Agent: long browser name ";
305   for (int i = 0; i < 3800; ++i)
306     request_text.push_back('*');
307   request_text.append("\r\n\r\n");
308   scoped_refptr<net::IOBuffer> request_buffer =
309       new net::StringIOBuffer(request_text);
310 
311   rv = sock->Write(request_buffer, request_text.size(), &callback2);
312   EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING);
313 
314   if (rv == net::ERR_IO_PENDING)
315     rv = callback2.WaitForResult();
316   EXPECT_EQ(static_cast<int>(request_text.size()), rv);
317 
318   // Now get the Read result.
319   rv = callback.WaitForResult();
320   EXPECT_GT(rv, 0);
321 }
322 
TEST_F(SSLClientSocketTest,Read_SmallChunks)323 TEST_F(SSLClientSocketTest, Read_SmallChunks) {
324   StartOKServer();
325 
326   net::AddressList addr;
327   TestCompletionCallback callback;
328 
329   net::HostResolver::RequestInfo info(server_.kHostName, server_.kOKHTTPSPort);
330   int rv = resolver_->Resolve(info, &addr, NULL, NULL, NULL);
331   EXPECT_EQ(net::OK, rv);
332 
333   net::ClientSocket *transport = new net::TCPClientSocket(addr);
334   rv = transport->Connect(&callback, NULL);
335   if (rv == net::ERR_IO_PENDING)
336     rv = callback.WaitForResult();
337   EXPECT_EQ(net::OK, rv);
338 
339   scoped_ptr<net::SSLClientSocket> sock(
340       socket_factory_->CreateSSLClientSocket(transport,
341           server_.kHostName, kDefaultSSLConfig));
342 
343   rv = sock->Connect(&callback, NULL);
344   if (rv != net::OK) {
345     ASSERT_EQ(net::ERR_IO_PENDING, rv);
346 
347     rv = callback.WaitForResult();
348     EXPECT_EQ(net::OK, rv);
349   }
350 
351   const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
352   scoped_refptr<net::IOBuffer> request_buffer =
353       new net::IOBuffer(arraysize(request_text) - 1);
354   memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1);
355 
356   rv = sock->Write(request_buffer, arraysize(request_text) - 1, &callback);
357   EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING);
358 
359   if (rv == net::ERR_IO_PENDING)
360     rv = callback.WaitForResult();
361   EXPECT_EQ(static_cast<int>(arraysize(request_text) - 1), rv);
362 
363   scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(1);
364   for (;;) {
365     rv = sock->Read(buf, 1, &callback);
366     EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING);
367 
368     if (rv == net::ERR_IO_PENDING)
369       rv = callback.WaitForResult();
370 
371     EXPECT_GE(rv, 0);
372     if (rv <= 0)
373       break;
374   }
375 }
376 
TEST_F(SSLClientSocketTest,Read_Interrupted)377 TEST_F(SSLClientSocketTest, Read_Interrupted) {
378   StartOKServer();
379 
380   net::AddressList addr;
381   TestCompletionCallback callback;
382 
383   net::HostResolver::RequestInfo info(server_.kHostName, server_.kOKHTTPSPort);
384   int rv = resolver_->Resolve(info, &addr, NULL, NULL, NULL);
385   EXPECT_EQ(net::OK, rv);
386 
387   net::ClientSocket *transport = new net::TCPClientSocket(addr);
388   rv = transport->Connect(&callback, NULL);
389   if (rv == net::ERR_IO_PENDING)
390     rv = callback.WaitForResult();
391   EXPECT_EQ(net::OK, rv);
392 
393   scoped_ptr<net::SSLClientSocket> sock(
394       socket_factory_->CreateSSLClientSocket(transport,
395           server_.kHostName, kDefaultSSLConfig));
396 
397   rv = sock->Connect(&callback, NULL);
398   if (rv != net::OK) {
399     ASSERT_EQ(net::ERR_IO_PENDING, rv);
400 
401     rv = callback.WaitForResult();
402     EXPECT_EQ(net::OK, rv);
403   }
404 
405   const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
406   scoped_refptr<net::IOBuffer> request_buffer =
407       new net::IOBuffer(arraysize(request_text) - 1);
408   memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1);
409 
410   rv = sock->Write(request_buffer, arraysize(request_text) - 1, &callback);
411   EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING);
412 
413   if (rv == net::ERR_IO_PENDING)
414     rv = callback.WaitForResult();
415   EXPECT_EQ(static_cast<int>(arraysize(request_text) - 1), rv);
416 
417   // Do a partial read and then exit.  This test should not crash!
418   scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(512);
419   rv = sock->Read(buf, 512, &callback);
420   EXPECT_TRUE(rv > 0 || rv == net::ERR_IO_PENDING);
421 
422   if (rv == net::ERR_IO_PENDING)
423     rv = callback.WaitForResult();
424 
425   EXPECT_GT(rv, 0);
426 }
427