blob: 084904748d0785a8225666943c78c6749fe81f53 [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]7deea3d2011-01-09 06:03:4161 return net::LogContainsEndEvent(log, i, net::NetLog::TYPE_SSL_CONNECT) ||
62 net::LogContainsEvent(log, i, net::NetLog::TYPE_SOCKET_BYTES_SENT,
[email protected]7f2fff12010-10-09 18:42:1163 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]091fd3b72011-03-14 03:23:52194TEST_F(SSLClientSocketTest, ConnectClientAuthCertRequested) {
[email protected]347599952010-10-28 11:57:36195 net::TestServer::HTTPSOptions https_options;
196 https_options.request_client_certificate = true;
197 net::TestServer test_server(https_options, FilePath());
[email protected]95409e12010-08-17 20:07:11198 ASSERT_TRUE(test_server.Start());
[email protected]8df162a2010-08-07 01:10:02199
200 net::AddressList addr;
[email protected]95409e12010-08-17 20:07:11201 ASSERT_TRUE(test_server.GetAddressList(&addr));
202
[email protected]8df162a2010-08-07 01:10:02203 TestCompletionCallback callback;
[email protected]8df162a2010-08-07 01:10:02204 net::CapturingNetLog log(net::CapturingNetLog::kUnbounded);
[email protected]0a0b7682010-08-25 17:08:07205 net::ClientSocket* transport = new net::TCPClientSocket(
206 addr, &log, net::NetLog::Source());
[email protected]95409e12010-08-17 20:07:11207 int rv = transport->Connect(&callback);
[email protected]8df162a2010-08-07 01:10:02208 if (rv == net::ERR_IO_PENDING)
209 rv = callback.WaitForResult();
210 EXPECT_EQ(net::OK, rv);
211
212 scoped_ptr<net::SSLClientSocket> sock(
[email protected]822581d2010-12-16 17:27:15213 CreateSSLClientSocket(transport, test_server.host_port_pair(),
214 kDefaultSSLConfig));
[email protected]8df162a2010-08-07 01:10:02215
216 EXPECT_FALSE(sock->IsConnected());
217
218 rv = sock->Connect(&callback);
[email protected]b2fcd0e2010-12-01 15:19:40219
220 net::CapturingNetLog::EntryList entries;
221 log.GetEntries(&entries);
[email protected]8df162a2010-08-07 01:10:02222 EXPECT_TRUE(net::LogContainsBeginEvent(
[email protected]b2fcd0e2010-12-01 15:19:40223 entries, 5, net::NetLog::TYPE_SSL_CONNECT));
[email protected]6526380c2010-11-10 04:40:33224 if (rv == net::ERR_IO_PENDING)
[email protected]8df162a2010-08-07 01:10:02225 rv = callback.WaitForResult();
[email protected]8df162a2010-08-07 01:10:02226
[email protected]b2fcd0e2010-12-01 15:19:40227 log.GetEntries(&entries);
[email protected]091fd3b72011-03-14 03:23:52228 // Because we prematurely kill the handshake at CertificateRequest,
229 // the server may still send data (notably the ServerHelloDone)
230 // after the error is returned. As a result, the SSL_CONNECT may not
231 // be the last entry. See http://crbug.com/54445. We use
232 // ExpectLogContainsSomewhere instead of
233 // LogContainsSSLConnectEndEvent to avoid assuming, e.g., only one
234 // extra read instead of two. This occurs before the handshake ends,
235 // so the corking logic of LogContainsSSLConnectEndEvent isn't
236 // necessary.
237 //
238 // TODO(davidben): When SSL_RestartHandshakeAfterCertReq in NSS is
239 // fixed and we can respond to the first CertificateRequest
240 // without closing the socket, add a unit test for sending the
241 // certificate. This test may still be useful as we'll want to close
242 // the socket on a timeout if the user takes a long time to pick a
243 // cert. Related bug: https://bugzilla.mozilla.org/show_bug.cgi?id=542832
244 net::ExpectLogContainsSomewhere(
245 entries, 0, net::NetLog::TYPE_SSL_CONNECT, net::NetLog::PHASE_END);
[email protected]6526380c2010-11-10 04:40:33246 EXPECT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
247 EXPECT_FALSE(sock->IsConnected());
[email protected]8df162a2010-08-07 01:10:02248}
249
[email protected]65a3b912010-08-21 05:46:58250// Connect to a server requesting optional client authentication. Send it a
251// null certificate. It should allow the connection.
252//
253// TODO(davidben): Also test providing an actual certificate.
254TEST_F(SSLClientSocketTest, ConnectClientAuthSendNullCert) {
[email protected]347599952010-10-28 11:57:36255 net::TestServer::HTTPSOptions https_options;
256 https_options.request_client_certificate = true;
257 net::TestServer test_server(https_options, FilePath());
[email protected]65a3b912010-08-21 05:46:58258 ASSERT_TRUE(test_server.Start());
259
260 net::AddressList addr;
261 ASSERT_TRUE(test_server.GetAddressList(&addr));
262
263 TestCompletionCallback callback;
264 net::CapturingNetLog log(net::CapturingNetLog::kUnbounded);
[email protected]0a0b7682010-08-25 17:08:07265 net::ClientSocket* transport = new net::TCPClientSocket(
266 addr, &log, net::NetLog::Source());
[email protected]65a3b912010-08-21 05:46:58267 int rv = transport->Connect(&callback);
268 if (rv == net::ERR_IO_PENDING)
269 rv = callback.WaitForResult();
270 EXPECT_EQ(net::OK, rv);
271
272 net::SSLConfig ssl_config = kDefaultSSLConfig;
273 ssl_config.send_client_cert = true;
274 ssl_config.client_cert = NULL;
275
276 scoped_ptr<net::SSLClientSocket> sock(
[email protected]822581d2010-12-16 17:27:15277 CreateSSLClientSocket(transport, test_server.host_port_pair(),
278 ssl_config));
[email protected]65a3b912010-08-21 05:46:58279
280 EXPECT_FALSE(sock->IsConnected());
281
282 // Our test server accepts certificate-less connections.
283 // TODO(davidben): Add a test which requires them and verify the error.
284 rv = sock->Connect(&callback);
[email protected]b2fcd0e2010-12-01 15:19:40285
286 net::CapturingNetLog::EntryList entries;
287 log.GetEntries(&entries);
[email protected]65a3b912010-08-21 05:46:58288 EXPECT_TRUE(net::LogContainsBeginEvent(
[email protected]b2fcd0e2010-12-01 15:19:40289 entries, 5, net::NetLog::TYPE_SSL_CONNECT));
[email protected]6526380c2010-11-10 04:40:33290 if (rv == net::ERR_IO_PENDING)
[email protected]65a3b912010-08-21 05:46:58291 rv = callback.WaitForResult();
[email protected]65a3b912010-08-21 05:46:58292
[email protected]6526380c2010-11-10 04:40:33293 EXPECT_EQ(net::OK, rv);
[email protected]65a3b912010-08-21 05:46:58294 EXPECT_TRUE(sock->IsConnected());
[email protected]b2fcd0e2010-12-01 15:19:40295 log.GetEntries(&entries);
296 EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1));
[email protected]65a3b912010-08-21 05:46:58297
298 sock->Disconnect();
299 EXPECT_FALSE(sock->IsConnected());
300}
301
[email protected]b2197852009-02-19 23:27:33302// TODO(wtc): Add unit tests for IsConnectedAndIdle:
303// - Server closes an SSL connection (with a close_notify alert message).
304// - Server closes the underlying TCP connection directly.
305// - Server sends data unexpectedly.
306
[email protected]e3eb8f82010-09-21 15:25:15307TEST_F(SSLClientSocketTest, Read) {
[email protected]95409e12010-08-17 20:07:11308 net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath());
309 ASSERT_TRUE(test_server.Start());
[email protected]73e0bba2009-02-19 22:57:09310
311 net::AddressList addr;
[email protected]95409e12010-08-17 20:07:11312 ASSERT_TRUE(test_server.GetAddressList(&addr));
313
[email protected]73e0bba2009-02-19 22:57:09314 TestCompletionCallback callback;
[email protected]0a0b7682010-08-25 17:08:07315 net::ClientSocket* transport = new net::TCPClientSocket(
316 addr, NULL, net::NetLog::Source());
[email protected]95409e12010-08-17 20:07:11317 int rv = transport->Connect(&callback);
[email protected]bacff652009-03-31 17:50:33318 if (rv == net::ERR_IO_PENDING)
319 rv = callback.WaitForResult();
320 EXPECT_EQ(net::OK, rv);
321
[email protected]aaead502008-10-15 00:20:11322 scoped_ptr<net::SSLClientSocket> sock(
[email protected]822581d2010-12-16 17:27:15323 CreateSSLClientSocket(transport, test_server.host_port_pair(),
324 kDefaultSSLConfig));
initial.commit586acc5fe2008-07-26 22:42:52325
[email protected]a2006ece2010-04-23 16:44:02326 rv = sock->Connect(&callback);
[email protected]6526380c2010-11-10 04:40:33327 if (rv == net::ERR_IO_PENDING)
[email protected]7b822b2b2008-08-05 00:15:45328 rv = callback.WaitForResult();
[email protected]6526380c2010-11-10 04:40:33329 EXPECT_EQ(net::OK, rv);
[email protected]b43c97c2008-10-22 19:50:58330 EXPECT_TRUE(sock->IsConnected());
initial.commit586acc5fe2008-07-26 22:42:52331
[email protected]e3eb8f82010-09-21 15:25:15332 const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
[email protected]ad8e04a2010-11-01 04:16:27333 scoped_refptr<net::IOBuffer> request_buffer(
334 new net::IOBuffer(arraysize(request_text) - 1));
[email protected]e3eb8f82010-09-21 15:25:15335 memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1);
[email protected]ffeb0882009-04-30 21:51:25336
[email protected]e3eb8f82010-09-21 15:25:15337 rv = sock->Write(request_buffer, arraysize(request_text) - 1, &callback);
initial.commit586acc5fe2008-07-26 22:42:52338 EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING);
339
[email protected]914286d62009-12-10 23:06:44340 if (rv == net::ERR_IO_PENDING)
initial.commit586acc5fe2008-07-26 22:42:52341 rv = callback.WaitForResult();
[email protected]e3eb8f82010-09-21 15:25:15342 EXPECT_EQ(static_cast<int>(arraysize(request_text) - 1), rv);
initial.commit586acc5fe2008-07-26 22:42:52343
[email protected]ad8e04a2010-11-01 04:16:27344 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(4096));
initial.commit586acc5fe2008-07-26 22:42:52345 for (;;) {
[email protected]ffeb0882009-04-30 21:51:25346 rv = sock->Read(buf, 4096, &callback);
initial.commit586acc5fe2008-07-26 22:42:52347 EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING);
348
349 if (rv == net::ERR_IO_PENDING)
350 rv = callback.WaitForResult();
351
[email protected]7b822b2b2008-08-05 00:15:45352 EXPECT_GE(rv, 0);
353 if (rv <= 0)
initial.commit586acc5fe2008-07-26 22:42:52354 break;
355 }
356}
357
[email protected]914286d62009-12-10 23:06:44358// Test the full duplex mode, with Read and Write pending at the same time.
359// This test also serves as a regression test for http://crbug.com/29815.
360TEST_F(SSLClientSocketTest, Read_FullDuplex) {
[email protected]95409e12010-08-17 20:07:11361 net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath());
362 ASSERT_TRUE(test_server.Start());
[email protected]914286d62009-12-10 23:06:44363
364 net::AddressList addr;
[email protected]95409e12010-08-17 20:07:11365 ASSERT_TRUE(test_server.GetAddressList(&addr));
366
[email protected]914286d62009-12-10 23:06:44367 TestCompletionCallback callback; // Used for everything except Write.
368 TestCompletionCallback callback2; // Used for Write only.
369
[email protected]0a0b7682010-08-25 17:08:07370 net::ClientSocket* transport = new net::TCPClientSocket(
371 addr, NULL, net::NetLog::Source());
[email protected]95409e12010-08-17 20:07:11372 int rv = transport->Connect(&callback);
[email protected]914286d62009-12-10 23:06:44373 if (rv == net::ERR_IO_PENDING)
374 rv = callback.WaitForResult();
375 EXPECT_EQ(net::OK, rv);
376
377 scoped_ptr<net::SSLClientSocket> sock(
[email protected]73c45322010-10-01 23:57:54378 socket_factory_->CreateSSLClientSocket(
[email protected]822581d2010-12-16 17:27:15379 transport, test_server.host_port_pair(), kDefaultSSLConfig,
380 NULL, cert_verifier_.get()));
[email protected]914286d62009-12-10 23:06:44381
[email protected]a2006ece2010-04-23 16:44:02382 rv = sock->Connect(&callback);
[email protected]6526380c2010-11-10 04:40:33383 if (rv == net::ERR_IO_PENDING)
[email protected]914286d62009-12-10 23:06:44384 rv = callback.WaitForResult();
[email protected]6526380c2010-11-10 04:40:33385 EXPECT_EQ(net::OK, rv);
[email protected]914286d62009-12-10 23:06:44386 EXPECT_TRUE(sock->IsConnected());
387
388 // Issue a "hanging" Read first.
[email protected]ad8e04a2010-11-01 04:16:27389 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(4096));
[email protected]914286d62009-12-10 23:06:44390 rv = sock->Read(buf, 4096, &callback);
391 // We haven't written the request, so there should be no response yet.
392 ASSERT_EQ(net::ERR_IO_PENDING, rv);
393
394 // Write the request.
395 // The request is padded with a User-Agent header to a size that causes the
396 // memio circular buffer (4k bytes) in SSLClientSocketNSS to wrap around.
397 // This tests the fix for http://crbug.com/29815.
398 std::string request_text = "GET / HTTP/1.1\r\nUser-Agent: long browser name ";
399 for (int i = 0; i < 3800; ++i)
400 request_text.push_back('*');
401 request_text.append("\r\n\r\n");
[email protected]ad8e04a2010-11-01 04:16:27402 scoped_refptr<net::IOBuffer> request_buffer(
403 new net::StringIOBuffer(request_text));
[email protected]914286d62009-12-10 23:06:44404
405 rv = sock->Write(request_buffer, request_text.size(), &callback2);
406 EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING);
407
408 if (rv == net::ERR_IO_PENDING)
409 rv = callback2.WaitForResult();
410 EXPECT_EQ(static_cast<int>(request_text.size()), rv);
411
412 // Now get the Read result.
413 rv = callback.WaitForResult();
414 EXPECT_GT(rv, 0);
415}
416
[email protected]010e27e2009-08-27 17:49:41417TEST_F(SSLClientSocketTest, Read_SmallChunks) {
[email protected]95409e12010-08-17 20:07:11418 net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath());
419 ASSERT_TRUE(test_server.Start());
[email protected]73e0bba2009-02-19 22:57:09420
initial.commit586acc5fe2008-07-26 22:42:52421 net::AddressList addr;
[email protected]95409e12010-08-17 20:07:11422 ASSERT_TRUE(test_server.GetAddressList(&addr));
423
initial.commit586acc5fe2008-07-26 22:42:52424 TestCompletionCallback callback;
[email protected]0a0b7682010-08-25 17:08:07425 net::ClientSocket* transport = new net::TCPClientSocket(
426 addr, NULL, net::NetLog::Source());
[email protected]95409e12010-08-17 20:07:11427 int rv = transport->Connect(&callback);
[email protected]bacff652009-03-31 17:50:33428 if (rv == net::ERR_IO_PENDING)
429 rv = callback.WaitForResult();
430 EXPECT_EQ(net::OK, rv);
431
[email protected]aaead502008-10-15 00:20:11432 scoped_ptr<net::SSLClientSocket> sock(
[email protected]822581d2010-12-16 17:27:15433 CreateSSLClientSocket(transport, test_server.host_port_pair(),
434 kDefaultSSLConfig));
initial.commit586acc5fe2008-07-26 22:42:52435
[email protected]a2006ece2010-04-23 16:44:02436 rv = sock->Connect(&callback);
[email protected]6526380c2010-11-10 04:40:33437 if (rv == net::ERR_IO_PENDING)
[email protected]7b822b2b2008-08-05 00:15:45438 rv = callback.WaitForResult();
[email protected]6526380c2010-11-10 04:40:33439 EXPECT_EQ(net::OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52440
441 const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
[email protected]ad8e04a2010-11-01 04:16:27442 scoped_refptr<net::IOBuffer> request_buffer(
443 new net::IOBuffer(arraysize(request_text) - 1));
[email protected]ffeb0882009-04-30 21:51:25444 memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1);
445
446 rv = sock->Write(request_buffer, arraysize(request_text) - 1, &callback);
initial.commit586acc5fe2008-07-26 22:42:52447 EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING);
448
[email protected]914286d62009-12-10 23:06:44449 if (rv == net::ERR_IO_PENDING)
initial.commit586acc5fe2008-07-26 22:42:52450 rv = callback.WaitForResult();
[email protected]914286d62009-12-10 23:06:44451 EXPECT_EQ(static_cast<int>(arraysize(request_text) - 1), rv);
initial.commit586acc5fe2008-07-26 22:42:52452
[email protected]ad8e04a2010-11-01 04:16:27453 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(1));
initial.commit586acc5fe2008-07-26 22:42:52454 for (;;) {
[email protected]ffeb0882009-04-30 21:51:25455 rv = sock->Read(buf, 1, &callback);
initial.commit586acc5fe2008-07-26 22:42:52456 EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING);
457
458 if (rv == net::ERR_IO_PENDING)
459 rv = callback.WaitForResult();
460
[email protected]7b822b2b2008-08-05 00:15:45461 EXPECT_GE(rv, 0);
462 if (rv <= 0)
initial.commit586acc5fe2008-07-26 22:42:52463 break;
464 }
465}
466
[email protected]010e27e2009-08-27 17:49:41467TEST_F(SSLClientSocketTest, Read_Interrupted) {
[email protected]95409e12010-08-17 20:07:11468 net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath());
469 ASSERT_TRUE(test_server.Start());
[email protected]73e0bba2009-02-19 22:57:09470
initial.commit586acc5fe2008-07-26 22:42:52471 net::AddressList addr;
[email protected]95409e12010-08-17 20:07:11472 ASSERT_TRUE(test_server.GetAddressList(&addr));
473
initial.commit586acc5fe2008-07-26 22:42:52474 TestCompletionCallback callback;
[email protected]0a0b7682010-08-25 17:08:07475 net::ClientSocket* transport = new net::TCPClientSocket(
476 addr, NULL, net::NetLog::Source());
[email protected]95409e12010-08-17 20:07:11477 int rv = transport->Connect(&callback);
[email protected]bacff652009-03-31 17:50:33478 if (rv == net::ERR_IO_PENDING)
479 rv = callback.WaitForResult();
480 EXPECT_EQ(net::OK, rv);
481
[email protected]aaead502008-10-15 00:20:11482 scoped_ptr<net::SSLClientSocket> sock(
[email protected]822581d2010-12-16 17:27:15483 CreateSSLClientSocket(transport, test_server.host_port_pair(),
484 kDefaultSSLConfig));
initial.commit586acc5fe2008-07-26 22:42:52485
[email protected]a2006ece2010-04-23 16:44:02486 rv = sock->Connect(&callback);
[email protected]6526380c2010-11-10 04:40:33487 if (rv == net::ERR_IO_PENDING)
[email protected]7b822b2b2008-08-05 00:15:45488 rv = callback.WaitForResult();
[email protected]6526380c2010-11-10 04:40:33489 EXPECT_EQ(net::OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52490
491 const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
[email protected]ad8e04a2010-11-01 04:16:27492 scoped_refptr<net::IOBuffer> request_buffer(
493 new net::IOBuffer(arraysize(request_text) - 1));
[email protected]ffeb0882009-04-30 21:51:25494 memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1);
495
496 rv = sock->Write(request_buffer, arraysize(request_text) - 1, &callback);
initial.commit586acc5fe2008-07-26 22:42:52497 EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING);
498
[email protected]914286d62009-12-10 23:06:44499 if (rv == net::ERR_IO_PENDING)
initial.commit586acc5fe2008-07-26 22:42:52500 rv = callback.WaitForResult();
[email protected]914286d62009-12-10 23:06:44501 EXPECT_EQ(static_cast<int>(arraysize(request_text) - 1), rv);
initial.commit586acc5fe2008-07-26 22:42:52502
503 // Do a partial read and then exit. This test should not crash!
[email protected]ad8e04a2010-11-01 04:16:27504 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(512));
[email protected]ffeb0882009-04-30 21:51:25505 rv = sock->Read(buf, 512, &callback);
[email protected]914286d62009-12-10 23:06:44506 EXPECT_TRUE(rv > 0 || rv == net::ERR_IO_PENDING);
initial.commit586acc5fe2008-07-26 22:42:52507
508 if (rv == net::ERR_IO_PENDING)
509 rv = callback.WaitForResult();
510
[email protected]914286d62009-12-10 23:06:44511 EXPECT_GT(rv, 0);
initial.commit586acc5fe2008-07-26 22:42:52512}
[email protected]39afe642010-04-29 14:55:18513
[email protected]39afe642010-04-29 14:55:18514// Regression test for http://crbug.com/42538
515TEST_F(SSLClientSocketTest, PrematureApplicationData) {
[email protected]95409e12010-08-17 20:07:11516 net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath());
517 ASSERT_TRUE(test_server.Start());
518
[email protected]39afe642010-04-29 14:55:18519 net::AddressList addr;
520 TestCompletionCallback callback;
521
522 static const unsigned char application_data[] = {
523 0x17, 0x03, 0x01, 0x00, 0x4a, 0x02, 0x00, 0x00, 0x46, 0x03, 0x01, 0x4b,
524 0xc2, 0xf8, 0xb2, 0xc1, 0x56, 0x42, 0xb9, 0x57, 0x7f, 0xde, 0x87, 0x46,
525 0xf7, 0xa3, 0x52, 0x42, 0x21, 0xf0, 0x13, 0x1c, 0x9c, 0x83, 0x88, 0xd6,
526 0x93, 0x0c, 0xf6, 0x36, 0x30, 0x05, 0x7e, 0x20, 0xb5, 0xb5, 0x73, 0x36,
527 0x53, 0x83, 0x0a, 0xfc, 0x17, 0x63, 0xbf, 0xa0, 0xe4, 0x42, 0x90, 0x0d,
528 0x2f, 0x18, 0x6d, 0x20, 0xd8, 0x36, 0x3f, 0xfc, 0xe6, 0x01, 0xfa, 0x0f,
529 0xa5, 0x75, 0x7f, 0x09, 0x00, 0x04, 0x00, 0x16, 0x03, 0x01, 0x11, 0x57,
530 0x0b, 0x00, 0x11, 0x53, 0x00, 0x11, 0x50, 0x00, 0x06, 0x22, 0x30, 0x82,
531 0x06, 0x1e, 0x30, 0x82, 0x05, 0x06, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
532 0x0a
533 };
534
535 // All reads and writes complete synchronously (async=false).
536 net::MockRead data_reads[] = {
537 net::MockRead(false, reinterpret_cast<const char*>(application_data),
538 arraysize(application_data)),
539 net::MockRead(false, net::OK),
540 };
541
542 net::StaticSocketDataProvider data(data_reads, arraysize(data_reads),
543 NULL, 0);
544
545 net::ClientSocket* transport =
546 new net::MockTCPClientSocket(addr, NULL, &data);
547 int rv = transport->Connect(&callback);
548 if (rv == net::ERR_IO_PENDING)
549 rv = callback.WaitForResult();
550 EXPECT_EQ(net::OK, rv);
551
552 scoped_ptr<net::SSLClientSocket> sock(
[email protected]822581d2010-12-16 17:27:15553 CreateSSLClientSocket(transport, test_server.host_port_pair(),
554 kDefaultSSLConfig));
[email protected]39afe642010-04-29 14:55:18555
556 rv = sock->Connect(&callback);
557 EXPECT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
558}
[email protected]47f7d742010-11-11 04:12:53559
[email protected]109805a2010-12-07 18:17:06560// TODO(rsleevi): Not implemented for Schannel. As Schannel is only used when
[email protected]47f7d742010-11-11 04:12:53561// performing client authentication, it will not be tested here.
[email protected]7deea3d2011-01-09 06:03:41562TEST_F(SSLClientSocketTest, CipherSuiteDisables) {
[email protected]47f7d742010-11-11 04:12:53563 // Rather than exhaustively disabling every RC4 ciphersuite defined at
564 // http://www.iana.org/assignments/tls-parameters/tls-parameters.xml,
565 // only disabling those cipher suites that the test server actually
566 // implements.
567 const uint16 kCiphersToDisable[] = {
568 0x0005, // TLS_RSA_WITH_RC4_128_SHA
569 };
570
571 net::TestServer::HTTPSOptions https_options;
572 // Enable only RC4 on the test server.
573 https_options.bulk_ciphers =
574 net::TestServer::HTTPSOptions::BULK_CIPHER_RC4;
575 net::TestServer test_server(https_options, FilePath());
576 ASSERT_TRUE(test_server.Start());
577
578 net::AddressList addr;
579 ASSERT_TRUE(test_server.GetAddressList(&addr));
580
581 TestCompletionCallback callback;
582 net::CapturingNetLog log(net::CapturingNetLog::kUnbounded);
583 net::ClientSocket* transport = new net::TCPClientSocket(
584 addr, &log, net::NetLog::Source());
585 int rv = transport->Connect(&callback);
586 if (rv == net::ERR_IO_PENDING)
587 rv = callback.WaitForResult();
588 EXPECT_EQ(net::OK, rv);
589
590 net::SSLConfig ssl_config;
591 for (size_t i = 0; i < arraysize(kCiphersToDisable); ++i)
592 ssl_config.disabled_cipher_suites.push_back(kCiphersToDisable[i]);
593
594 scoped_ptr<net::SSLClientSocket> sock(
[email protected]822581d2010-12-16 17:27:15595 CreateSSLClientSocket(transport, test_server.host_port_pair(),
596 ssl_config));
[email protected]47f7d742010-11-11 04:12:53597
598 EXPECT_FALSE(sock->IsConnected());
599
600 rv = sock->Connect(&callback);
[email protected]b2fcd0e2010-12-01 15:19:40601 net::CapturingNetLog::EntryList entries;
602 log.GetEntries(&entries);
[email protected]47f7d742010-11-11 04:12:53603 EXPECT_TRUE(net::LogContainsBeginEvent(
[email protected]b2fcd0e2010-12-01 15:19:40604 entries, 5, net::NetLog::TYPE_SSL_CONNECT));
[email protected]47f7d742010-11-11 04:12:53605
606 // NSS has special handling that maps a handshake_failure alert received
607 // immediately after a client_hello to be a mismatched cipher suite error,
608 // leading to ERR_SSL_VERSION_OR_CIPHER_MISMATCH. When using OpenSSL or
609 // Secure Transport (OS X), the handshake_failure is bubbled up without any
610 // interpretation, leading to ERR_SSL_PROTOCOL_ERROR. Either way, a failure
611 // indicates that no cipher suite was negotiated with the test server.
612 if (rv == net::ERR_IO_PENDING)
613 rv = callback.WaitForResult();
614 EXPECT_TRUE(rv == net::ERR_SSL_VERSION_OR_CIPHER_MISMATCH ||
615 rv == net::ERR_SSL_PROTOCOL_ERROR);
616 // The exact ordering differs between SSLClientSocketNSS (which issues an
617 // extra read) and SSLClientSocketMac (which does not). Just make sure the
618 // error appears somewhere in the log.
[email protected]b2fcd0e2010-12-01 15:19:40619 log.GetEntries(&entries);
620 net::ExpectLogContainsSomewhere(entries, 0,
[email protected]47f7d742010-11-11 04:12:53621 net::NetLog::TYPE_SSL_HANDSHAKE_ERROR,
622 net::NetLog::PHASE_NONE);
623
624 // We cannot test sock->IsConnected(), as the NSS implementation disconnects
625 // the socket when it encounters an error, whereas other implementations
626 // leave it connected.
[email protected]7deea3d2011-01-09 06:03:41627 // Because this an error that the test server is mutually aware of, as opposed
628 // to being an error such as a certificate name mismatch, which is
629 // client-only, the exact index of the SSL connect end depends on how
630 // quickly the test server closes the underlying socket. If the test server
631 // closes before the IO message loop pumps messages, there may be a 0-byte
632 // Read event in the NetLog due to TCPClientSocket picking up the EOF. As a
633 // result, the SSL connect end event will be the second-to-last entry,
634 // rather than the last entry.
635 EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1) ||
636 LogContainsSSLConnectEndEvent(entries, -2));
[email protected]47f7d742010-11-11 04:12:53637}