blob: 9ba5cbfca24ba20999d65874faadc82e565df6aa [file] [log] [blame]
[email protected]a2006ece2010-04-23 16:44:021// Copyright (c) 2010 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit586acc5fe2008-07-26 22:42:524
[email protected]f7984fc62009-06-22 23:26:445#include "net/socket/ssl_client_socket.h"
6
initial.commit586acc5fe2008-07-26 22:42:527#include "net/base/address_list.h"
[email protected]822581d2010-12-16 17:27:158#include "net/base/cert_verifier.h"
initial.commit586acc5fe2008-07-26 22:42:529#include "net/base/host_resolver.h"
[email protected]597cf6e2009-05-29 09:43:2610#include "net/base/io_buffer.h"
[email protected]9e743cd2010-03-16 07:03:5311#include "net/base/net_log.h"
12#include "net/base/net_log_unittest.h"
[email protected]7b822b2b2008-08-05 00:15:4513#include "net/base/net_errors.h"
[email protected]aaead502008-10-15 00:20:1114#include "net/base/ssl_config_service.h"
initial.commit586acc5fe2008-07-26 22:42:5215#include "net/base/test_completion_callback.h"
[email protected]f7984fc62009-06-22 23:26:4416#include "net/socket/client_socket_factory.h"
[email protected]39afe642010-04-29 14:55:1817#include "net/socket/socket_test_util.h"
[email protected]f7984fc62009-06-22 23:26:4418#include "net/socket/tcp_client_socket.h"
[email protected]1b9565c2010-07-21 01:19:3119#include "net/test/test_server.h"
initial.commit586acc5fe2008-07-26 22:42:5220#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1521#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5222
23//-----------------------------------------------------------------------------
24
[email protected]aaead502008-10-15 00:20:1125const net::SSLConfig kDefaultSSLConfig;
[email protected]c5949a32008-10-08 17:28:2326
[email protected]b75523f2008-10-17 14:49:0727class SSLClientSocketTest : public PlatformTest {
[email protected]aaead502008-10-15 00:20:1128 public:
29 SSLClientSocketTest()
[email protected]822581d2010-12-16 17:27:1530 : socket_factory_(net::ClientSocketFactory::GetDefaultFactory()),
31 cert_verifier_(new net::CertVerifier) {
[email protected]73e0bba2009-02-19 22:57:0932 }
33
[email protected]aaead502008-10-15 00:20:1134 protected:
[email protected]822581d2010-12-16 17:27:1535 net::SSLClientSocket* CreateSSLClientSocket(
36 net::ClientSocket* transport_socket,
37 const net::HostPortPair& host_and_port,
38 const net::SSLConfig& ssl_config) {
39 return socket_factory_->CreateSSLClientSocket(transport_socket,
40 host_and_port,
41 ssl_config,
42 NULL,
43 cert_verifier_.get());
44 }
45
[email protected]aaead502008-10-15 00:20:1146 net::ClientSocketFactory* socket_factory_;
[email protected]822581d2010-12-16 17:27:1547 scoped_ptr<net::CertVerifier> cert_verifier_;
initial.commit586acc5fe2008-07-26 22:42:5248};
49
initial.commit586acc5fe2008-07-26 22:42:5250//-----------------------------------------------------------------------------
51
[email protected]6a47ac82010-10-08 14:39:3052// LogContainsSSLConnectEndEvent returns true if the given index in the given
53// log is an SSL connect end event. The NSS sockets will cork in an attempt to
54// merge the first application data record with the Finished message when false
55// starting. However, in order to avoid the server timing out the handshake,
56// they'll give up waiting for application data and send the Finished after a
57// timeout. This means that an SSL connect end event may appear as a socket
58// write.
59static bool LogContainsSSLConnectEndEvent(
60 const net::CapturingNetLog::EntryList& log, int i) {
[email protected]7f2fff12010-10-09 18:42:1161 return net::LogContainsEndEvent(log, -1, net::NetLog::TYPE_SSL_CONNECT) ||
62 net::LogContainsEvent(log, -1, net::NetLog::TYPE_SOCKET_BYTES_SENT,
63 net::NetLog::PHASE_NONE);
[email protected]6a47ac82010-10-08 14:39:3064};
65
[email protected]010e27e2009-08-27 17:49:4166TEST_F(SSLClientSocketTest, Connect) {
[email protected]95409e12010-08-17 20:07:1167 net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath());
68 ASSERT_TRUE(test_server.Start());
[email protected]73e0bba2009-02-19 22:57:0969
initial.commit586acc5fe2008-07-26 22:42:5270 net::AddressList addr;
[email protected]95409e12010-08-17 20:07:1171 ASSERT_TRUE(test_server.GetAddressList(&addr));
72
initial.commit586acc5fe2008-07-26 22:42:5273 TestCompletionCallback callback;
[email protected]a2006ece2010-04-23 16:44:0274 net::CapturingNetLog log(net::CapturingNetLog::kUnbounded);
[email protected]0a0b7682010-08-25 17:08:0775 net::ClientSocket* transport = new net::TCPClientSocket(
76 addr, &log, net::NetLog::Source());
[email protected]95409e12010-08-17 20:07:1177 int rv = transport->Connect(&callback);
[email protected]bacff652009-03-31 17:50:3378 if (rv == net::ERR_IO_PENDING)
79 rv = callback.WaitForResult();
80 EXPECT_EQ(net::OK, rv);
81
[email protected]aaead502008-10-15 00:20:1182 scoped_ptr<net::SSLClientSocket> sock(
[email protected]6526380c2010-11-10 04:40:3383 socket_factory_->CreateSSLClientSocket(
[email protected]822581d2010-12-16 17:27:1584 transport, test_server.host_port_pair(), kDefaultSSLConfig,
85 NULL, cert_verifier_.get()));
initial.commit586acc5fe2008-07-26 22:42:5286
[email protected]aaead502008-10-15 00:20:1187 EXPECT_FALSE(sock->IsConnected());
initial.commit586acc5fe2008-07-26 22:42:5288
[email protected]a2006ece2010-04-23 16:44:0289 rv = sock->Connect(&callback);
[email protected]b2fcd0e2010-12-01 15:19:4090
91 net::CapturingNetLog::EntryList entries;
92 log.GetEntries(&entries);
[email protected]eb8605c2010-05-21 22:17:4793 EXPECT_TRUE(net::LogContainsBeginEvent(
[email protected]b2fcd0e2010-12-01 15:19:4094 entries, 5, net::NetLog::TYPE_SSL_CONNECT));
[email protected]6526380c2010-11-10 04:40:3395 if (rv == net::ERR_IO_PENDING)
[email protected]7b822b2b2008-08-05 00:15:4596 rv = callback.WaitForResult();
[email protected]6526380c2010-11-10 04:40:3397 EXPECT_EQ(net::OK, rv);
[email protected]aaead502008-10-15 00:20:1198 EXPECT_TRUE(sock->IsConnected());
[email protected]b2fcd0e2010-12-01 15:19:4099 log.GetEntries(&entries);
100 EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1));
initial.commit586acc5fe2008-07-26 22:42:52101
[email protected]aaead502008-10-15 00:20:11102 sock->Disconnect();
103 EXPECT_FALSE(sock->IsConnected());
initial.commit586acc5fe2008-07-26 22:42:52104}
105
[email protected]7f2fff12010-10-09 18:42:11106TEST_F(SSLClientSocketTest, ConnectExpired) {
[email protected]347599952010-10-28 11:57:36107 net::TestServer::HTTPSOptions https_options(
108 net::TestServer::HTTPSOptions::CERT_EXPIRED);
109 net::TestServer test_server(https_options, FilePath());
[email protected]95409e12010-08-17 20:07:11110 ASSERT_TRUE(test_server.Start());
[email protected]73e0bba2009-02-19 22:57:09111
initial.commit586acc5fe2008-07-26 22:42:52112 net::AddressList addr;
[email protected]95409e12010-08-17 20:07:11113 ASSERT_TRUE(test_server.GetAddressList(&addr));
114
initial.commit586acc5fe2008-07-26 22:42:52115 TestCompletionCallback callback;
[email protected]a2006ece2010-04-23 16:44:02116 net::CapturingNetLog log(net::CapturingNetLog::kUnbounded);
[email protected]0a0b7682010-08-25 17:08:07117 net::ClientSocket* transport = new net::TCPClientSocket(
118 addr, &log, net::NetLog::Source());
[email protected]95409e12010-08-17 20:07:11119 int rv = transport->Connect(&callback);
[email protected]bacff652009-03-31 17:50:33120 if (rv == net::ERR_IO_PENDING)
121 rv = callback.WaitForResult();
122 EXPECT_EQ(net::OK, rv);
123
[email protected]73e0bba2009-02-19 22:57:09124 scoped_ptr<net::SSLClientSocket> sock(
[email protected]822581d2010-12-16 17:27:15125 CreateSSLClientSocket(transport, test_server.host_port_pair(),
126 kDefaultSSLConfig));
[email protected]73e0bba2009-02-19 22:57:09127
128 EXPECT_FALSE(sock->IsConnected());
129
[email protected]a2006ece2010-04-23 16:44:02130 rv = sock->Connect(&callback);
[email protected]b2fcd0e2010-12-01 15:19:40131
132 net::CapturingNetLog::EntryList entries;
133 log.GetEntries(&entries);
[email protected]eb8605c2010-05-21 22:17:47134 EXPECT_TRUE(net::LogContainsBeginEvent(
[email protected]b2fcd0e2010-12-01 15:19:40135 entries, 5, net::NetLog::TYPE_SSL_CONNECT));
[email protected]6526380c2010-11-10 04:40:33136 if (rv == net::ERR_IO_PENDING)
[email protected]73e0bba2009-02-19 22:57:09137 rv = callback.WaitForResult();
[email protected]73e0bba2009-02-19 22:57:09138
[email protected]6526380c2010-11-10 04:40:33139 EXPECT_EQ(net::ERR_CERT_DATE_INVALID, rv);
140
141 // Rather than testing whether or not the underlying socket is connected,
142 // test that the handshake has finished. This is because it may be
143 // desirable to disconnect the socket before showing a user prompt, since
144 // the user may take indefinitely long to respond.
[email protected]b2fcd0e2010-12-01 15:19:40145 log.GetEntries(&entries);
146 EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1));
[email protected]73e0bba2009-02-19 22:57:09147}
148
[email protected]7f2fff12010-10-09 18:42:11149TEST_F(SSLClientSocketTest, ConnectMismatched) {
[email protected]347599952010-10-28 11:57:36150 net::TestServer::HTTPSOptions https_options(
151 net::TestServer::HTTPSOptions::CERT_MISMATCHED_NAME);
152 net::TestServer test_server(https_options, FilePath());
[email protected]95409e12010-08-17 20:07:11153 ASSERT_TRUE(test_server.Start());
[email protected]73e0bba2009-02-19 22:57:09154
155 net::AddressList addr;
[email protected]95409e12010-08-17 20:07:11156 ASSERT_TRUE(test_server.GetAddressList(&addr));
157
[email protected]73e0bba2009-02-19 22:57:09158 TestCompletionCallback callback;
[email protected]a2006ece2010-04-23 16:44:02159 net::CapturingNetLog log(net::CapturingNetLog::kUnbounded);
[email protected]0a0b7682010-08-25 17:08:07160 net::ClientSocket* transport = new net::TCPClientSocket(
161 addr, &log, net::NetLog::Source());
[email protected]95409e12010-08-17 20:07:11162 int rv = transport->Connect(&callback);
[email protected]bacff652009-03-31 17:50:33163 if (rv == net::ERR_IO_PENDING)
164 rv = callback.WaitForResult();
165 EXPECT_EQ(net::OK, rv);
166
[email protected]73e0bba2009-02-19 22:57:09167 scoped_ptr<net::SSLClientSocket> sock(
[email protected]822581d2010-12-16 17:27:15168 CreateSSLClientSocket(transport, test_server.host_port_pair(),
169 kDefaultSSLConfig));
[email protected]73e0bba2009-02-19 22:57:09170
171 EXPECT_FALSE(sock->IsConnected());
172
[email protected]a2006ece2010-04-23 16:44:02173 rv = sock->Connect(&callback);
[email protected]4b32be92010-05-20 03:21:42174
[email protected]b2fcd0e2010-12-01 15:19:40175 net::CapturingNetLog::EntryList entries;
176 log.GetEntries(&entries);
[email protected]eb8605c2010-05-21 22:17:47177 EXPECT_TRUE(net::LogContainsBeginEvent(
[email protected]b2fcd0e2010-12-01 15:19:40178 entries, 5, net::NetLog::TYPE_SSL_CONNECT));
[email protected]6526380c2010-11-10 04:40:33179 if (rv == net::ERR_IO_PENDING)
[email protected]73e0bba2009-02-19 22:57:09180 rv = callback.WaitForResult();
[email protected]73e0bba2009-02-19 22:57:09181
[email protected]6526380c2010-11-10 04:40:33182 EXPECT_EQ(net::ERR_CERT_COMMON_NAME_INVALID, rv);
183
184 // Rather than testing whether or not the underlying socket is connected,
185 // test that the handshake has finished. This is because it may be
186 // desirable to disconnect the socket before showing a user prompt, since
187 // the user may take indefinitely long to respond.
[email protected]b2fcd0e2010-12-01 15:19:40188 log.GetEntries(&entries);
189 EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1));
[email protected]73e0bba2009-02-19 22:57:09190}
191
[email protected]65a3b912010-08-21 05:46:58192// Attempt to connect to a page which requests a client certificate. It should
193// return an error code on connect.
[email protected]2fbd3a72010-10-27 21:20:18194// Flaky: http://crbug.com/54445
[email protected]308a7302010-09-03 21:33:58195TEST_F(SSLClientSocketTest, FLAKY_ConnectClientAuthCertRequested) {
[email protected]347599952010-10-28 11:57:36196 net::TestServer::HTTPSOptions https_options;
197 https_options.request_client_certificate = true;
198 net::TestServer test_server(https_options, FilePath());
[email protected]95409e12010-08-17 20:07:11199 ASSERT_TRUE(test_server.Start());
[email protected]8df162a2010-08-07 01:10:02200
201 net::AddressList addr;
[email protected]95409e12010-08-17 20:07:11202 ASSERT_TRUE(test_server.GetAddressList(&addr));
203
[email protected]8df162a2010-08-07 01:10:02204 TestCompletionCallback callback;
[email protected]8df162a2010-08-07 01:10:02205 net::CapturingNetLog log(net::CapturingNetLog::kUnbounded);
[email protected]0a0b7682010-08-25 17:08:07206 net::ClientSocket* transport = new net::TCPClientSocket(
207 addr, &log, net::NetLog::Source());
[email protected]95409e12010-08-17 20:07:11208 int rv = transport->Connect(&callback);
[email protected]8df162a2010-08-07 01:10:02209 if (rv == net::ERR_IO_PENDING)
210 rv = callback.WaitForResult();
211 EXPECT_EQ(net::OK, rv);
212
213 scoped_ptr<net::SSLClientSocket> sock(
[email protected]822581d2010-12-16 17:27:15214 CreateSSLClientSocket(transport, test_server.host_port_pair(),
215 kDefaultSSLConfig));
[email protected]8df162a2010-08-07 01:10:02216
217 EXPECT_FALSE(sock->IsConnected());
218
219 rv = sock->Connect(&callback);
[email protected]b2fcd0e2010-12-01 15:19:40220
221 net::CapturingNetLog::EntryList entries;
222 log.GetEntries(&entries);
[email protected]8df162a2010-08-07 01:10:02223 EXPECT_TRUE(net::LogContainsBeginEvent(
[email protected]b2fcd0e2010-12-01 15:19:40224 entries, 5, net::NetLog::TYPE_SSL_CONNECT));
[email protected]6526380c2010-11-10 04:40:33225 if (rv == net::ERR_IO_PENDING)
[email protected]8df162a2010-08-07 01:10:02226 rv = callback.WaitForResult();
[email protected]8df162a2010-08-07 01:10:02227
[email protected]b2fcd0e2010-12-01 15:19:40228 log.GetEntries(&entries);
229 EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1));
[email protected]6526380c2010-11-10 04:40:33230 EXPECT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
231 EXPECT_FALSE(sock->IsConnected());
[email protected]8df162a2010-08-07 01:10:02232}
233
[email protected]65a3b912010-08-21 05:46:58234// Connect to a server requesting optional client authentication. Send it a
235// null certificate. It should allow the connection.
236//
237// TODO(davidben): Also test providing an actual certificate.
238TEST_F(SSLClientSocketTest, ConnectClientAuthSendNullCert) {
[email protected]347599952010-10-28 11:57:36239 net::TestServer::HTTPSOptions https_options;
240 https_options.request_client_certificate = true;
241 net::TestServer test_server(https_options, FilePath());
[email protected]65a3b912010-08-21 05:46:58242 ASSERT_TRUE(test_server.Start());
243
244 net::AddressList addr;
245 ASSERT_TRUE(test_server.GetAddressList(&addr));
246
247 TestCompletionCallback callback;
248 net::CapturingNetLog log(net::CapturingNetLog::kUnbounded);
[email protected]0a0b7682010-08-25 17:08:07249 net::ClientSocket* transport = new net::TCPClientSocket(
250 addr, &log, net::NetLog::Source());
[email protected]65a3b912010-08-21 05:46:58251 int rv = transport->Connect(&callback);
252 if (rv == net::ERR_IO_PENDING)
253 rv = callback.WaitForResult();
254 EXPECT_EQ(net::OK, rv);
255
256 net::SSLConfig ssl_config = kDefaultSSLConfig;
257 ssl_config.send_client_cert = true;
258 ssl_config.client_cert = NULL;
259
260 scoped_ptr<net::SSLClientSocket> sock(
[email protected]822581d2010-12-16 17:27:15261 CreateSSLClientSocket(transport, test_server.host_port_pair(),
262 ssl_config));
[email protected]65a3b912010-08-21 05:46:58263
264 EXPECT_FALSE(sock->IsConnected());
265
266 // Our test server accepts certificate-less connections.
267 // TODO(davidben): Add a test which requires them and verify the error.
268 rv = sock->Connect(&callback);
[email protected]b2fcd0e2010-12-01 15:19:40269
270 net::CapturingNetLog::EntryList entries;
271 log.GetEntries(&entries);
[email protected]65a3b912010-08-21 05:46:58272 EXPECT_TRUE(net::LogContainsBeginEvent(
[email protected]b2fcd0e2010-12-01 15:19:40273 entries, 5, net::NetLog::TYPE_SSL_CONNECT));
[email protected]6526380c2010-11-10 04:40:33274 if (rv == net::ERR_IO_PENDING)
[email protected]65a3b912010-08-21 05:46:58275 rv = callback.WaitForResult();
[email protected]65a3b912010-08-21 05:46:58276
[email protected]6526380c2010-11-10 04:40:33277 EXPECT_EQ(net::OK, rv);
[email protected]65a3b912010-08-21 05:46:58278 EXPECT_TRUE(sock->IsConnected());
[email protected]b2fcd0e2010-12-01 15:19:40279 log.GetEntries(&entries);
280 EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1));
[email protected]65a3b912010-08-21 05:46:58281
282 sock->Disconnect();
283 EXPECT_FALSE(sock->IsConnected());
284}
285
[email protected]b2197852009-02-19 23:27:33286// TODO(wtc): Add unit tests for IsConnectedAndIdle:
287// - Server closes an SSL connection (with a close_notify alert message).
288// - Server closes the underlying TCP connection directly.
289// - Server sends data unexpectedly.
290
[email protected]e3eb8f82010-09-21 15:25:15291TEST_F(SSLClientSocketTest, Read) {
[email protected]95409e12010-08-17 20:07:11292 net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath());
293 ASSERT_TRUE(test_server.Start());
[email protected]73e0bba2009-02-19 22:57:09294
295 net::AddressList addr;
[email protected]95409e12010-08-17 20:07:11296 ASSERT_TRUE(test_server.GetAddressList(&addr));
297
[email protected]73e0bba2009-02-19 22:57:09298 TestCompletionCallback callback;
[email protected]0a0b7682010-08-25 17:08:07299 net::ClientSocket* transport = new net::TCPClientSocket(
300 addr, NULL, net::NetLog::Source());
[email protected]95409e12010-08-17 20:07:11301 int rv = transport->Connect(&callback);
[email protected]bacff652009-03-31 17:50:33302 if (rv == net::ERR_IO_PENDING)
303 rv = callback.WaitForResult();
304 EXPECT_EQ(net::OK, rv);
305
[email protected]aaead502008-10-15 00:20:11306 scoped_ptr<net::SSLClientSocket> sock(
[email protected]822581d2010-12-16 17:27:15307 CreateSSLClientSocket(transport, test_server.host_port_pair(),
308 kDefaultSSLConfig));
initial.commit586acc5fe2008-07-26 22:42:52309
[email protected]a2006ece2010-04-23 16:44:02310 rv = sock->Connect(&callback);
[email protected]6526380c2010-11-10 04:40:33311 if (rv == net::ERR_IO_PENDING)
[email protected]7b822b2b2008-08-05 00:15:45312 rv = callback.WaitForResult();
[email protected]6526380c2010-11-10 04:40:33313 EXPECT_EQ(net::OK, rv);
[email protected]b43c97c2008-10-22 19:50:58314 EXPECT_TRUE(sock->IsConnected());
initial.commit586acc5fe2008-07-26 22:42:52315
[email protected]e3eb8f82010-09-21 15:25:15316 const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
[email protected]ad8e04a2010-11-01 04:16:27317 scoped_refptr<net::IOBuffer> request_buffer(
318 new net::IOBuffer(arraysize(request_text) - 1));
[email protected]e3eb8f82010-09-21 15:25:15319 memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1);
[email protected]ffeb0882009-04-30 21:51:25320
[email protected]e3eb8f82010-09-21 15:25:15321 rv = sock->Write(request_buffer, arraysize(request_text) - 1, &callback);
initial.commit586acc5fe2008-07-26 22:42:52322 EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING);
323
[email protected]914286d62009-12-10 23:06:44324 if (rv == net::ERR_IO_PENDING)
initial.commit586acc5fe2008-07-26 22:42:52325 rv = callback.WaitForResult();
[email protected]e3eb8f82010-09-21 15:25:15326 EXPECT_EQ(static_cast<int>(arraysize(request_text) - 1), rv);
initial.commit586acc5fe2008-07-26 22:42:52327
[email protected]ad8e04a2010-11-01 04:16:27328 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(4096));
initial.commit586acc5fe2008-07-26 22:42:52329 for (;;) {
[email protected]ffeb0882009-04-30 21:51:25330 rv = sock->Read(buf, 4096, &callback);
initial.commit586acc5fe2008-07-26 22:42:52331 EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING);
332
333 if (rv == net::ERR_IO_PENDING)
334 rv = callback.WaitForResult();
335
[email protected]7b822b2b2008-08-05 00:15:45336 EXPECT_GE(rv, 0);
337 if (rv <= 0)
initial.commit586acc5fe2008-07-26 22:42:52338 break;
339 }
340}
341
[email protected]914286d62009-12-10 23:06:44342// Test the full duplex mode, with Read and Write pending at the same time.
343// This test also serves as a regression test for http://crbug.com/29815.
344TEST_F(SSLClientSocketTest, Read_FullDuplex) {
[email protected]95409e12010-08-17 20:07:11345 net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath());
346 ASSERT_TRUE(test_server.Start());
[email protected]914286d62009-12-10 23:06:44347
348 net::AddressList addr;
[email protected]95409e12010-08-17 20:07:11349 ASSERT_TRUE(test_server.GetAddressList(&addr));
350
[email protected]914286d62009-12-10 23:06:44351 TestCompletionCallback callback; // Used for everything except Write.
352 TestCompletionCallback callback2; // Used for Write only.
353
[email protected]0a0b7682010-08-25 17:08:07354 net::ClientSocket* transport = new net::TCPClientSocket(
355 addr, NULL, net::NetLog::Source());
[email protected]95409e12010-08-17 20:07:11356 int rv = transport->Connect(&callback);
[email protected]914286d62009-12-10 23:06:44357 if (rv == net::ERR_IO_PENDING)
358 rv = callback.WaitForResult();
359 EXPECT_EQ(net::OK, rv);
360
361 scoped_ptr<net::SSLClientSocket> sock(
[email protected]73c45322010-10-01 23:57:54362 socket_factory_->CreateSSLClientSocket(
[email protected]822581d2010-12-16 17:27:15363 transport, test_server.host_port_pair(), kDefaultSSLConfig,
364 NULL, cert_verifier_.get()));
[email protected]914286d62009-12-10 23:06:44365
[email protected]a2006ece2010-04-23 16:44:02366 rv = sock->Connect(&callback);
[email protected]6526380c2010-11-10 04:40:33367 if (rv == net::ERR_IO_PENDING)
[email protected]914286d62009-12-10 23:06:44368 rv = callback.WaitForResult();
[email protected]6526380c2010-11-10 04:40:33369 EXPECT_EQ(net::OK, rv);
[email protected]914286d62009-12-10 23:06:44370 EXPECT_TRUE(sock->IsConnected());
371
372 // Issue a "hanging" Read first.
[email protected]ad8e04a2010-11-01 04:16:27373 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(4096));
[email protected]914286d62009-12-10 23:06:44374 rv = sock->Read(buf, 4096, &callback);
375 // We haven't written the request, so there should be no response yet.
376 ASSERT_EQ(net::ERR_IO_PENDING, rv);
377
378 // Write the request.
379 // The request is padded with a User-Agent header to a size that causes the
380 // memio circular buffer (4k bytes) in SSLClientSocketNSS to wrap around.
381 // This tests the fix for http://crbug.com/29815.
382 std::string request_text = "GET / HTTP/1.1\r\nUser-Agent: long browser name ";
383 for (int i = 0; i < 3800; ++i)
384 request_text.push_back('*');
385 request_text.append("\r\n\r\n");
[email protected]ad8e04a2010-11-01 04:16:27386 scoped_refptr<net::IOBuffer> request_buffer(
387 new net::StringIOBuffer(request_text));
[email protected]914286d62009-12-10 23:06:44388
389 rv = sock->Write(request_buffer, request_text.size(), &callback2);
390 EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING);
391
392 if (rv == net::ERR_IO_PENDING)
393 rv = callback2.WaitForResult();
394 EXPECT_EQ(static_cast<int>(request_text.size()), rv);
395
396 // Now get the Read result.
397 rv = callback.WaitForResult();
398 EXPECT_GT(rv, 0);
399}
400
[email protected]010e27e2009-08-27 17:49:41401TEST_F(SSLClientSocketTest, Read_SmallChunks) {
[email protected]95409e12010-08-17 20:07:11402 net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath());
403 ASSERT_TRUE(test_server.Start());
[email protected]73e0bba2009-02-19 22:57:09404
initial.commit586acc5fe2008-07-26 22:42:52405 net::AddressList addr;
[email protected]95409e12010-08-17 20:07:11406 ASSERT_TRUE(test_server.GetAddressList(&addr));
407
initial.commit586acc5fe2008-07-26 22:42:52408 TestCompletionCallback callback;
[email protected]0a0b7682010-08-25 17:08:07409 net::ClientSocket* transport = new net::TCPClientSocket(
410 addr, NULL, net::NetLog::Source());
[email protected]95409e12010-08-17 20:07:11411 int rv = transport->Connect(&callback);
[email protected]bacff652009-03-31 17:50:33412 if (rv == net::ERR_IO_PENDING)
413 rv = callback.WaitForResult();
414 EXPECT_EQ(net::OK, rv);
415
[email protected]aaead502008-10-15 00:20:11416 scoped_ptr<net::SSLClientSocket> sock(
[email protected]822581d2010-12-16 17:27:15417 CreateSSLClientSocket(transport, test_server.host_port_pair(),
418 kDefaultSSLConfig));
initial.commit586acc5fe2008-07-26 22:42:52419
[email protected]a2006ece2010-04-23 16:44:02420 rv = sock->Connect(&callback);
[email protected]6526380c2010-11-10 04:40:33421 if (rv == net::ERR_IO_PENDING)
[email protected]7b822b2b2008-08-05 00:15:45422 rv = callback.WaitForResult();
[email protected]6526380c2010-11-10 04:40:33423 EXPECT_EQ(net::OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52424
425 const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
[email protected]ad8e04a2010-11-01 04:16:27426 scoped_refptr<net::IOBuffer> request_buffer(
427 new net::IOBuffer(arraysize(request_text) - 1));
[email protected]ffeb0882009-04-30 21:51:25428 memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1);
429
430 rv = sock->Write(request_buffer, arraysize(request_text) - 1, &callback);
initial.commit586acc5fe2008-07-26 22:42:52431 EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING);
432
[email protected]914286d62009-12-10 23:06:44433 if (rv == net::ERR_IO_PENDING)
initial.commit586acc5fe2008-07-26 22:42:52434 rv = callback.WaitForResult();
[email protected]914286d62009-12-10 23:06:44435 EXPECT_EQ(static_cast<int>(arraysize(request_text) - 1), rv);
initial.commit586acc5fe2008-07-26 22:42:52436
[email protected]ad8e04a2010-11-01 04:16:27437 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(1));
initial.commit586acc5fe2008-07-26 22:42:52438 for (;;) {
[email protected]ffeb0882009-04-30 21:51:25439 rv = sock->Read(buf, 1, &callback);
initial.commit586acc5fe2008-07-26 22:42:52440 EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING);
441
442 if (rv == net::ERR_IO_PENDING)
443 rv = callback.WaitForResult();
444
[email protected]7b822b2b2008-08-05 00:15:45445 EXPECT_GE(rv, 0);
446 if (rv <= 0)
initial.commit586acc5fe2008-07-26 22:42:52447 break;
448 }
449}
450
[email protected]010e27e2009-08-27 17:49:41451TEST_F(SSLClientSocketTest, Read_Interrupted) {
[email protected]95409e12010-08-17 20:07:11452 net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath());
453 ASSERT_TRUE(test_server.Start());
[email protected]73e0bba2009-02-19 22:57:09454
initial.commit586acc5fe2008-07-26 22:42:52455 net::AddressList addr;
[email protected]95409e12010-08-17 20:07:11456 ASSERT_TRUE(test_server.GetAddressList(&addr));
457
initial.commit586acc5fe2008-07-26 22:42:52458 TestCompletionCallback callback;
[email protected]0a0b7682010-08-25 17:08:07459 net::ClientSocket* transport = new net::TCPClientSocket(
460 addr, NULL, net::NetLog::Source());
[email protected]95409e12010-08-17 20:07:11461 int rv = transport->Connect(&callback);
[email protected]bacff652009-03-31 17:50:33462 if (rv == net::ERR_IO_PENDING)
463 rv = callback.WaitForResult();
464 EXPECT_EQ(net::OK, rv);
465
[email protected]aaead502008-10-15 00:20:11466 scoped_ptr<net::SSLClientSocket> sock(
[email protected]822581d2010-12-16 17:27:15467 CreateSSLClientSocket(transport, test_server.host_port_pair(),
468 kDefaultSSLConfig));
initial.commit586acc5fe2008-07-26 22:42:52469
[email protected]a2006ece2010-04-23 16:44:02470 rv = sock->Connect(&callback);
[email protected]6526380c2010-11-10 04:40:33471 if (rv == net::ERR_IO_PENDING)
[email protected]7b822b2b2008-08-05 00:15:45472 rv = callback.WaitForResult();
[email protected]6526380c2010-11-10 04:40:33473 EXPECT_EQ(net::OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52474
475 const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
[email protected]ad8e04a2010-11-01 04:16:27476 scoped_refptr<net::IOBuffer> request_buffer(
477 new net::IOBuffer(arraysize(request_text) - 1));
[email protected]ffeb0882009-04-30 21:51:25478 memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1);
479
480 rv = sock->Write(request_buffer, arraysize(request_text) - 1, &callback);
initial.commit586acc5fe2008-07-26 22:42:52481 EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING);
482
[email protected]914286d62009-12-10 23:06:44483 if (rv == net::ERR_IO_PENDING)
initial.commit586acc5fe2008-07-26 22:42:52484 rv = callback.WaitForResult();
[email protected]914286d62009-12-10 23:06:44485 EXPECT_EQ(static_cast<int>(arraysize(request_text) - 1), rv);
initial.commit586acc5fe2008-07-26 22:42:52486
487 // Do a partial read and then exit. This test should not crash!
[email protected]ad8e04a2010-11-01 04:16:27488 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(512));
[email protected]ffeb0882009-04-30 21:51:25489 rv = sock->Read(buf, 512, &callback);
[email protected]914286d62009-12-10 23:06:44490 EXPECT_TRUE(rv > 0 || rv == net::ERR_IO_PENDING);
initial.commit586acc5fe2008-07-26 22:42:52491
492 if (rv == net::ERR_IO_PENDING)
493 rv = callback.WaitForResult();
494
[email protected]914286d62009-12-10 23:06:44495 EXPECT_GT(rv, 0);
initial.commit586acc5fe2008-07-26 22:42:52496}
[email protected]39afe642010-04-29 14:55:18497
[email protected]39afe642010-04-29 14:55:18498// Regression test for http://crbug.com/42538
499TEST_F(SSLClientSocketTest, PrematureApplicationData) {
[email protected]95409e12010-08-17 20:07:11500 net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath());
501 ASSERT_TRUE(test_server.Start());
502
[email protected]39afe642010-04-29 14:55:18503 net::AddressList addr;
504 TestCompletionCallback callback;
505
506 static const unsigned char application_data[] = {
507 0x17, 0x03, 0x01, 0x00, 0x4a, 0x02, 0x00, 0x00, 0x46, 0x03, 0x01, 0x4b,
508 0xc2, 0xf8, 0xb2, 0xc1, 0x56, 0x42, 0xb9, 0x57, 0x7f, 0xde, 0x87, 0x46,
509 0xf7, 0xa3, 0x52, 0x42, 0x21, 0xf0, 0x13, 0x1c, 0x9c, 0x83, 0x88, 0xd6,
510 0x93, 0x0c, 0xf6, 0x36, 0x30, 0x05, 0x7e, 0x20, 0xb5, 0xb5, 0x73, 0x36,
511 0x53, 0x83, 0x0a, 0xfc, 0x17, 0x63, 0xbf, 0xa0, 0xe4, 0x42, 0x90, 0x0d,
512 0x2f, 0x18, 0x6d, 0x20, 0xd8, 0x36, 0x3f, 0xfc, 0xe6, 0x01, 0xfa, 0x0f,
513 0xa5, 0x75, 0x7f, 0x09, 0x00, 0x04, 0x00, 0x16, 0x03, 0x01, 0x11, 0x57,
514 0x0b, 0x00, 0x11, 0x53, 0x00, 0x11, 0x50, 0x00, 0x06, 0x22, 0x30, 0x82,
515 0x06, 0x1e, 0x30, 0x82, 0x05, 0x06, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
516 0x0a
517 };
518
519 // All reads and writes complete synchronously (async=false).
520 net::MockRead data_reads[] = {
521 net::MockRead(false, reinterpret_cast<const char*>(application_data),
522 arraysize(application_data)),
523 net::MockRead(false, net::OK),
524 };
525
526 net::StaticSocketDataProvider data(data_reads, arraysize(data_reads),
527 NULL, 0);
528
529 net::ClientSocket* transport =
530 new net::MockTCPClientSocket(addr, NULL, &data);
531 int rv = transport->Connect(&callback);
532 if (rv == net::ERR_IO_PENDING)
533 rv = callback.WaitForResult();
534 EXPECT_EQ(net::OK, rv);
535
536 scoped_ptr<net::SSLClientSocket> sock(
[email protected]822581d2010-12-16 17:27:15537 CreateSSLClientSocket(transport, test_server.host_port_pair(),
538 kDefaultSSLConfig));
[email protected]39afe642010-04-29 14:55:18539
540 rv = sock->Connect(&callback);
541 EXPECT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
542}
[email protected]47f7d742010-11-11 04:12:53543
[email protected]109805a2010-12-07 18:17:06544// TODO(rsleevi): Not implemented for Schannel. As Schannel is only used when
[email protected]47f7d742010-11-11 04:12:53545// performing client authentication, it will not be tested here.
[email protected]109805a2010-12-07 18:17:06546TEST_F(SSLClientSocketTest, CipherSuiteDisables) {
[email protected]47f7d742010-11-11 04:12:53547 // Rather than exhaustively disabling every RC4 ciphersuite defined at
548 // http://www.iana.org/assignments/tls-parameters/tls-parameters.xml,
549 // only disabling those cipher suites that the test server actually
550 // implements.
551 const uint16 kCiphersToDisable[] = {
552 0x0005, // TLS_RSA_WITH_RC4_128_SHA
553 };
554
555 net::TestServer::HTTPSOptions https_options;
556 // Enable only RC4 on the test server.
557 https_options.bulk_ciphers =
558 net::TestServer::HTTPSOptions::BULK_CIPHER_RC4;
559 net::TestServer test_server(https_options, FilePath());
560 ASSERT_TRUE(test_server.Start());
561
562 net::AddressList addr;
563 ASSERT_TRUE(test_server.GetAddressList(&addr));
564
565 TestCompletionCallback callback;
566 net::CapturingNetLog log(net::CapturingNetLog::kUnbounded);
567 net::ClientSocket* transport = new net::TCPClientSocket(
568 addr, &log, net::NetLog::Source());
569 int rv = transport->Connect(&callback);
570 if (rv == net::ERR_IO_PENDING)
571 rv = callback.WaitForResult();
572 EXPECT_EQ(net::OK, rv);
573
574 net::SSLConfig ssl_config;
575 for (size_t i = 0; i < arraysize(kCiphersToDisable); ++i)
576 ssl_config.disabled_cipher_suites.push_back(kCiphersToDisable[i]);
577
578 scoped_ptr<net::SSLClientSocket> sock(
[email protected]822581d2010-12-16 17:27:15579 CreateSSLClientSocket(transport, test_server.host_port_pair(),
580 ssl_config));
[email protected]47f7d742010-11-11 04:12:53581
582 EXPECT_FALSE(sock->IsConnected());
583
584 rv = sock->Connect(&callback);
[email protected]b2fcd0e2010-12-01 15:19:40585 net::CapturingNetLog::EntryList entries;
586 log.GetEntries(&entries);
[email protected]47f7d742010-11-11 04:12:53587 EXPECT_TRUE(net::LogContainsBeginEvent(
[email protected]b2fcd0e2010-12-01 15:19:40588 entries, 5, net::NetLog::TYPE_SSL_CONNECT));
[email protected]47f7d742010-11-11 04:12:53589
590 // NSS has special handling that maps a handshake_failure alert received
591 // immediately after a client_hello to be a mismatched cipher suite error,
592 // leading to ERR_SSL_VERSION_OR_CIPHER_MISMATCH. When using OpenSSL or
593 // Secure Transport (OS X), the handshake_failure is bubbled up without any
594 // interpretation, leading to ERR_SSL_PROTOCOL_ERROR. Either way, a failure
595 // indicates that no cipher suite was negotiated with the test server.
596 if (rv == net::ERR_IO_PENDING)
597 rv = callback.WaitForResult();
598 EXPECT_TRUE(rv == net::ERR_SSL_VERSION_OR_CIPHER_MISMATCH ||
599 rv == net::ERR_SSL_PROTOCOL_ERROR);
600 // The exact ordering differs between SSLClientSocketNSS (which issues an
601 // extra read) and SSLClientSocketMac (which does not). Just make sure the
602 // error appears somewhere in the log.
[email protected]b2fcd0e2010-12-01 15:19:40603 log.GetEntries(&entries);
604 net::ExpectLogContainsSomewhere(entries, 0,
[email protected]47f7d742010-11-11 04:12:53605 net::NetLog::TYPE_SSL_HANDSHAKE_ERROR,
606 net::NetLog::PHASE_NONE);
607
608 // We cannot test sock->IsConnected(), as the NSS implementation disconnects
609 // the socket when it encounters an error, whereas other implementations
610 // leave it connected.
[email protected]b2fcd0e2010-12-01 15:19:40611 EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1));
[email protected]47f7d742010-11-11 04:12:53612}