ssl_client_socket_unittest.cc revision 4a5e2dc747d50c653511c68ccb2cfbfb740bd5a7
1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/socket/ssl_client_socket.h"
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/address_list.h"
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/host_resolver.h"
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/io_buffer.h"
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_log.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_log_unittest.h"
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/net_errors.h"
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/ssl_config_service.h"
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/test_completion_callback.h"
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/socket/client_socket_factory.h"
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/socket/socket_test_util.h"
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/socket/tcp_client_socket.h"
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/test/test_server.h"
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "testing/gtest/include/gtest/gtest.h"
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "testing/platform_test.h"
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//-----------------------------------------------------------------------------
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst net::SSLConfig kDefaultSSLConfig;
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass SSLClientSocketTest : public PlatformTest {
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SSLClientSocketTest()
29731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      : socket_factory_(net::ClientSocketFactory::GetDefaultFactory()) {
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott protected:
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  net::ClientSocketFactory* socket_factory_;
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//-----------------------------------------------------------------------------
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
38731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// LogContainsSSLConnectEndEvent returns true if the given index in the given
39731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// log is an SSL connect end event. The NSS sockets will cork in an attempt to
40731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// merge the first application data record with the Finished message when false
41731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// starting. However, in order to avoid the server timing out the handshake,
42731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// they'll give up waiting for application data and send the Finished after a
43731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// timeout. This means that an SSL connect end event may appear as a socket
44731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// write.
45731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickstatic bool LogContainsSSLConnectEndEvent(
46731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const net::CapturingNetLog::EntryList& log, int i) {
47731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return  net::LogContainsEndEvent(log, -1, net::NetLog::TYPE_SSL_CONNECT) ||
48731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          net::LogContainsEvent(log, -1, net::NetLog::TYPE_SOCKET_BYTES_SENT,
49731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                net::NetLog::PHASE_NONE);
50731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick};
51731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(SSLClientSocketTest, Connect) {
533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath());
543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(test_server.Start());
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  net::AddressList addr;
573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(test_server.GetAddressList(&addr));
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback;
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  net::CapturingNetLog log(net::CapturingNetLog::kUnbounded);
613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  net::ClientSocket* transport = new net::TCPClientSocket(
623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      addr, &log, net::NetLog::Source());
633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = transport->Connect(&callback);
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (rv == net::ERR_IO_PENDING)
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    rv = callback.WaitForResult();
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(net::OK, rv);
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_ptr<net::SSLClientSocket> sock(
694a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      socket_factory_->CreateSSLClientSocket(
704a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch          transport, test_server.host_port_pair(), kDefaultSSLConfig, NULL));
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_FALSE(sock->IsConnected());
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rv = sock->Connect(&callback);
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(net::LogContainsBeginEvent(
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      log.entries(), 5, net::NetLog::TYPE_SSL_CONNECT));
774a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (rv == net::ERR_IO_PENDING)
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    rv = callback.WaitForResult();
794a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ(net::OK, rv);
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(sock->IsConnected());
81731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  EXPECT_TRUE(LogContainsSSLConnectEndEvent(log.entries(), -1));
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  sock->Disconnect();
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_FALSE(sock->IsConnected());
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(SSLClientSocketTest, ConnectExpired) {
88513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  net::TestServer::HTTPSOptions https_options(
89513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      net::TestServer::HTTPSOptions::CERT_EXPIRED);
90513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  net::TestServer test_server(https_options, FilePath());
913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(test_server.Start());
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  net::AddressList addr;
943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(test_server.GetAddressList(&addr));
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback;
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  net::CapturingNetLog log(net::CapturingNetLog::kUnbounded);
983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  net::ClientSocket* transport = new net::TCPClientSocket(
993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      addr, &log, net::NetLog::Source());
1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = transport->Connect(&callback);
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (rv == net::ERR_IO_PENDING)
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    rv = callback.WaitForResult();
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(net::OK, rv);
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_ptr<net::SSLClientSocket> sock(
1064a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      socket_factory_->CreateSSLClientSocket(
1074a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch          transport, test_server.host_port_pair(), kDefaultSSLConfig, NULL));
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_FALSE(sock->IsConnected());
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rv = sock->Connect(&callback);
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(net::LogContainsBeginEvent(
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      log.entries(), 5, net::NetLog::TYPE_SSL_CONNECT));
1144a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (rv == net::ERR_IO_PENDING)
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    rv = callback.WaitForResult();
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1174a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ(net::ERR_CERT_DATE_INVALID, rv);
1184a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1194a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // Rather than testing whether or not the underlying socket is connected,
1204a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // test that the handshake has finished. This is because it may be
1214a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // desirable to disconnect the socket before showing a user prompt, since
1224a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // the user may take indefinitely long to respond.
123731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  EXPECT_TRUE(LogContainsSSLConnectEndEvent(log.entries(), -1));
124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(SSLClientSocketTest, ConnectMismatched) {
127513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  net::TestServer::HTTPSOptions https_options(
128513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      net::TestServer::HTTPSOptions::CERT_MISMATCHED_NAME);
129513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  net::TestServer test_server(https_options, FilePath());
1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(test_server.Start());
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  net::AddressList addr;
1333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(test_server.GetAddressList(&addr));
134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback;
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  net::CapturingNetLog log(net::CapturingNetLog::kUnbounded);
1373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  net::ClientSocket* transport = new net::TCPClientSocket(
1383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      addr, &log, net::NetLog::Source());
1393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = transport->Connect(&callback);
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (rv == net::ERR_IO_PENDING)
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    rv = callback.WaitForResult();
142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(net::OK, rv);
143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_ptr<net::SSLClientSocket> sock(
1454a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      socket_factory_->CreateSSLClientSocket(
1464a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch          transport, test_server.host_port_pair(), kDefaultSSLConfig, NULL));
147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_FALSE(sock->IsConnected());
149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rv = sock->Connect(&callback);
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(net::LogContainsBeginEvent(
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      log.entries(), 5, net::NetLog::TYPE_SSL_CONNECT));
1544a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (rv == net::ERR_IO_PENDING)
155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    rv = callback.WaitForResult();
156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1574a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ(net::ERR_CERT_COMMON_NAME_INVALID, rv);
1584a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1594a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // Rather than testing whether or not the underlying socket is connected,
1604a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // test that the handshake has finished. This is because it may be
1614a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // desirable to disconnect the socket before showing a user prompt, since
1624a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // the user may take indefinitely long to respond.
163731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  EXPECT_TRUE(LogContainsSSLConnectEndEvent(log.entries(), -1));
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Attempt to connect to a page which requests a client certificate. It should
1673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// return an error code on connect.
168513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Flaky: http://crbug.com/54445
1693345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_F(SSLClientSocketTest, FLAKY_ConnectClientAuthCertRequested) {
170513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  net::TestServer::HTTPSOptions https_options;
171513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  https_options.request_client_certificate = true;
172513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  net::TestServer test_server(https_options, FilePath());
1733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(test_server.Start());
1743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  net::AddressList addr;
1763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(test_server.GetAddressList(&addr));
1773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback;
1793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  net::CapturingNetLog log(net::CapturingNetLog::kUnbounded);
1803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  net::ClientSocket* transport = new net::TCPClientSocket(
1813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      addr, &log, net::NetLog::Source());
1823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = transport->Connect(&callback);
1833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (rv == net::ERR_IO_PENDING)
1843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    rv = callback.WaitForResult();
1853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(net::OK, rv);
1863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<net::SSLClientSocket> sock(
1884a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      socket_factory_->CreateSSLClientSocket(
1894a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch          transport, test_server.host_port_pair(), kDefaultSSLConfig, NULL));
1903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_FALSE(sock->IsConnected());
1923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  rv = sock->Connect(&callback);
1943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(net::LogContainsBeginEvent(
1953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      log.entries(), 5, net::NetLog::TYPE_SSL_CONNECT));
1964a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (rv == net::ERR_IO_PENDING)
1973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    rv = callback.WaitForResult();
1983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1994a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
2004a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_FALSE(sock->IsConnected());
2013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
2023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Connect to a server requesting optional client authentication. Send it a
2043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// null certificate. It should allow the connection.
2053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick//
2063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// TODO(davidben): Also test providing an actual certificate.
2073345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST_F(SSLClientSocketTest, ConnectClientAuthSendNullCert) {
208513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  net::TestServer::HTTPSOptions https_options;
209513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  https_options.request_client_certificate = true;
210513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  net::TestServer test_server(https_options, FilePath());
2113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(test_server.Start());
2123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  net::AddressList addr;
2143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(test_server.GetAddressList(&addr));
2153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback;
2173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  net::CapturingNetLog log(net::CapturingNetLog::kUnbounded);
2183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  net::ClientSocket* transport = new net::TCPClientSocket(
2193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      addr, &log, net::NetLog::Source());
2203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = transport->Connect(&callback);
2213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (rv == net::ERR_IO_PENDING)
2223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    rv = callback.WaitForResult();
2233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(net::OK, rv);
2243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  net::SSLConfig ssl_config = kDefaultSSLConfig;
2263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ssl_config.send_client_cert = true;
2273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ssl_config.client_cert = NULL;
2283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<net::SSLClientSocket> sock(
2304a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      socket_factory_->CreateSSLClientSocket(
2314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch          transport, test_server.host_port_pair(), ssl_config, NULL));
2323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_FALSE(sock->IsConnected());
2343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Our test server accepts certificate-less connections.
2363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // TODO(davidben): Add a test which requires them and verify the error.
2373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  rv = sock->Connect(&callback);
2383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(net::LogContainsBeginEvent(
2393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      log.entries(), 5, net::NetLog::TYPE_SSL_CONNECT));
2404a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (rv == net::ERR_IO_PENDING)
2413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    rv = callback.WaitForResult();
2423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2434a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ(net::OK, rv);
2443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_TRUE(sock->IsConnected());
245731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  EXPECT_TRUE(LogContainsSSLConnectEndEvent(log.entries(), -1));
2463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  sock->Disconnect();
2483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_FALSE(sock->IsConnected());
2493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
2503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// TODO(wtc): Add unit tests for IsConnectedAndIdle:
252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   - Server closes an SSL connection (with a close_notify alert message).
253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   - Server closes the underlying TCP connection directly.
254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   - Server sends data unexpectedly.
255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(SSLClientSocketTest, Read) {
2573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath());
2583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(test_server.Start());
259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  net::AddressList addr;
2613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(test_server.GetAddressList(&addr));
262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback;
2643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  net::ClientSocket* transport = new net::TCPClientSocket(
2653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      addr, NULL, net::NetLog::Source());
2663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = transport->Connect(&callback);
267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (rv == net::ERR_IO_PENDING)
268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    rv = callback.WaitForResult();
269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(net::OK, rv);
270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_ptr<net::SSLClientSocket> sock(
272731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      socket_factory_->CreateSSLClientSocket(
2734a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch          transport, test_server.host_port_pair(), kDefaultSSLConfig, NULL));
274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rv = sock->Connect(&callback);
2764a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (rv == net::ERR_IO_PENDING)
277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    rv = callback.WaitForResult();
2784a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ(net::OK, rv);
279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(sock->IsConnected());
280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
282513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_refptr<net::IOBuffer> request_buffer(
283513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      new net::IOBuffer(arraysize(request_text) - 1));
284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1);
285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  rv = sock->Write(request_buffer, arraysize(request_text) - 1, &callback);
287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING);
288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (rv == net::ERR_IO_PENDING)
290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    rv = callback.WaitForResult();
291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(static_cast<int>(arraysize(request_text) - 1), rv);
292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
293513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(4096));
294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (;;) {
295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    rv = sock->Read(buf, 4096, &callback);
296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING);
297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (rv == net::ERR_IO_PENDING)
299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      rv = callback.WaitForResult();
300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_GE(rv, 0);
302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (rv <= 0)
303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Test the full duplex mode, with Read and Write pending at the same time.
308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This test also serves as a regression test for http://crbug.com/29815.
309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(SSLClientSocketTest, Read_FullDuplex) {
3103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath());
3113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(test_server.Start());
312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  net::AddressList addr;
3143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(test_server.GetAddressList(&addr));
3153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TestCompletionCallback callback;  // Used for everything except Write.
317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TestCompletionCallback callback2;  // Used for Write only.
318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
3193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  net::ClientSocket* transport = new net::TCPClientSocket(
3203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      addr, NULL, net::NetLog::Source());
3213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = transport->Connect(&callback);
322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (rv == net::ERR_IO_PENDING)
323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    rv = callback.WaitForResult();
324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(net::OK, rv);
325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_ptr<net::SSLClientSocket> sock(
327731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      socket_factory_->CreateSSLClientSocket(
3284a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch          transport, test_server.host_port_pair(), kDefaultSSLConfig, NULL));
329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rv = sock->Connect(&callback);
3314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (rv == net::ERR_IO_PENDING)
332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    rv = callback.WaitForResult();
3334a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ(net::OK, rv);
334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(sock->IsConnected());
335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Issue a "hanging" Read first.
337513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(4096));
338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  rv = sock->Read(buf, 4096, &callback);
339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We haven't written the request, so there should be no response yet.
340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ASSERT_EQ(net::ERR_IO_PENDING, rv);
341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Write the request.
343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The request is padded with a User-Agent header to a size that causes the
344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // memio circular buffer (4k bytes) in SSLClientSocketNSS to wrap around.
345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // This tests the fix for http://crbug.com/29815.
346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::string request_text = "GET / HTTP/1.1\r\nUser-Agent: long browser name ";
347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 0; i < 3800; ++i)
348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    request_text.push_back('*');
349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  request_text.append("\r\n\r\n");
350513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_refptr<net::IOBuffer> request_buffer(
351513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      new net::StringIOBuffer(request_text));
352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  rv = sock->Write(request_buffer, request_text.size(), &callback2);
354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING);
355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (rv == net::ERR_IO_PENDING)
357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    rv = callback2.WaitForResult();
358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(static_cast<int>(request_text.size()), rv);
359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Now get the Read result.
361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  rv = callback.WaitForResult();
362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_GT(rv, 0);
363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(SSLClientSocketTest, Read_SmallChunks) {
3663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath());
3673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(test_server.Start());
368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  net::AddressList addr;
3703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(test_server.GetAddressList(&addr));
371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
3723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback;
3733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  net::ClientSocket* transport = new net::TCPClientSocket(
3743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      addr, NULL, net::NetLog::Source());
3753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = transport->Connect(&callback);
376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (rv == net::ERR_IO_PENDING)
377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    rv = callback.WaitForResult();
378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(net::OK, rv);
379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_ptr<net::SSLClientSocket> sock(
3814a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      socket_factory_->CreateSSLClientSocket(
3824a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch          transport, test_server.host_port_pair(), kDefaultSSLConfig, NULL));
383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rv = sock->Connect(&callback);
3854a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (rv == net::ERR_IO_PENDING)
386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    rv = callback.WaitForResult();
3874a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ(net::OK, rv);
388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
390513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_refptr<net::IOBuffer> request_buffer(
391513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      new net::IOBuffer(arraysize(request_text) - 1));
392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1);
393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  rv = sock->Write(request_buffer, arraysize(request_text) - 1, &callback);
395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING);
396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (rv == net::ERR_IO_PENDING)
398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    rv = callback.WaitForResult();
399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(static_cast<int>(arraysize(request_text) - 1), rv);
400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
401513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(1));
402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (;;) {
403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    rv = sock->Read(buf, 1, &callback);
404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING);
405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (rv == net::ERR_IO_PENDING)
407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      rv = callback.WaitForResult();
408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_GE(rv, 0);
410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (rv <= 0)
411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST_F(SSLClientSocketTest, Read_Interrupted) {
4163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath());
4173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(test_server.Start());
418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  net::AddressList addr;
4203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(test_server.GetAddressList(&addr));
421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
4223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TestCompletionCallback callback;
4233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  net::ClientSocket* transport = new net::TCPClientSocket(
4243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      addr, NULL, net::NetLog::Source());
4253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = transport->Connect(&callback);
426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (rv == net::ERR_IO_PENDING)
427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    rv = callback.WaitForResult();
428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(net::OK, rv);
429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_ptr<net::SSLClientSocket> sock(
4314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      socket_factory_->CreateSSLClientSocket(
4324a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch          transport, test_server.host_port_pair(), kDefaultSSLConfig, NULL));
433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rv = sock->Connect(&callback);
4354a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (rv == net::ERR_IO_PENDING)
436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    rv = callback.WaitForResult();
4374a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ(net::OK, rv);
438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
440513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_refptr<net::IOBuffer> request_buffer(
441513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      new net::IOBuffer(arraysize(request_text) - 1));
442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1);
443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  rv = sock->Write(request_buffer, arraysize(request_text) - 1, &callback);
445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING);
446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (rv == net::ERR_IO_PENDING)
448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    rv = callback.WaitForResult();
449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(static_cast<int>(arraysize(request_text) - 1), rv);
450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Do a partial read and then exit.  This test should not crash!
452513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(512));
453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  rv = sock->Read(buf, 512, &callback);
454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(rv > 0 || rv == net::ERR_IO_PENDING);
455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (rv == net::ERR_IO_PENDING)
457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    rv = callback.WaitForResult();
458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_GT(rv, 0);
460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Regression test for http://crbug.com/42538
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(SSLClientSocketTest, PrematureApplicationData) {
4643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath());
4653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT_TRUE(test_server.Start());
4663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  net::AddressList addr;
468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback callback;
469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const unsigned char application_data[] = {
471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0x17, 0x03, 0x01, 0x00, 0x4a, 0x02, 0x00, 0x00, 0x46, 0x03, 0x01, 0x4b,
472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0xc2, 0xf8, 0xb2, 0xc1, 0x56, 0x42, 0xb9, 0x57, 0x7f, 0xde, 0x87, 0x46,
473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0xf7, 0xa3, 0x52, 0x42, 0x21, 0xf0, 0x13, 0x1c, 0x9c, 0x83, 0x88, 0xd6,
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0x93, 0x0c, 0xf6, 0x36, 0x30, 0x05, 0x7e, 0x20, 0xb5, 0xb5, 0x73, 0x36,
475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0x53, 0x83, 0x0a, 0xfc, 0x17, 0x63, 0xbf, 0xa0, 0xe4, 0x42, 0x90, 0x0d,
476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0x2f, 0x18, 0x6d, 0x20, 0xd8, 0x36, 0x3f, 0xfc, 0xe6, 0x01, 0xfa, 0x0f,
477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0xa5, 0x75, 0x7f, 0x09, 0x00, 0x04, 0x00, 0x16, 0x03, 0x01, 0x11, 0x57,
478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0x0b, 0x00, 0x11, 0x53, 0x00, 0x11, 0x50, 0x00, 0x06, 0x22, 0x30, 0x82,
479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0x06, 0x1e, 0x30, 0x82, 0x05, 0x06, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0x0a
481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // All reads and writes complete synchronously (async=false).
484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  net::MockRead data_reads[] = {
485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    net::MockRead(false, reinterpret_cast<const char*>(application_data),
486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                  arraysize(application_data)),
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    net::MockRead(false, net::OK),
488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  net::StaticSocketDataProvider data(data_reads, arraysize(data_reads),
491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     NULL, 0);
492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  net::ClientSocket* transport =
494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new net::MockTCPClientSocket(addr, NULL, &data);
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = transport->Connect(&callback);
496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (rv == net::ERR_IO_PENDING)
497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    rv = callback.WaitForResult();
498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(net::OK, rv);
499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<net::SSLClientSocket> sock(
501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      socket_factory_->CreateSSLClientSocket(
5024a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch          transport, test_server.host_port_pair(), kDefaultSSLConfig, NULL));
503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rv = sock->Connect(&callback);
505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
5074a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
5084a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#if defined(USE_OPENSSL)
5094a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// TODO(rsleevi): Not implemented for Schannel or OpenSSL. Schannel is
5104a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// controlled by the SSL client socket factory, rather than a define, so it
5114a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// cannot be conditionally disabled here. As Schannel is only used when
5124a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// performing client authentication, it will not be tested here.
5134a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#define MAYBE_CipherSuiteDisables DISABLED_CipherSuiteDisables
5144a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#else
5154a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#define MAYBE_CipherSuiteDisables CipherSuiteDisables
5164a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#endif
5174a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben MurdochTEST_F(SSLClientSocketTest, MAYBE_CipherSuiteDisables) {
5184a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // Rather than exhaustively disabling every RC4 ciphersuite defined at
5194a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // http://www.iana.org/assignments/tls-parameters/tls-parameters.xml,
5204a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // only disabling those cipher suites that the test server actually
5214a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // implements.
5224a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  const uint16 kCiphersToDisable[] = {
5234a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    0x0005,  // TLS_RSA_WITH_RC4_128_SHA
5244a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  };
5254a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
5264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  net::TestServer::HTTPSOptions https_options;
5274a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // Enable only RC4 on the test server.
5284a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  https_options.bulk_ciphers =
5294a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      net::TestServer::HTTPSOptions::BULK_CIPHER_RC4;
5304a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  net::TestServer test_server(https_options, FilePath());
5314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  ASSERT_TRUE(test_server.Start());
5324a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
5334a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  net::AddressList addr;
5344a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  ASSERT_TRUE(test_server.GetAddressList(&addr));
5354a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
5364a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  TestCompletionCallback callback;
5374a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  net::CapturingNetLog log(net::CapturingNetLog::kUnbounded);
5384a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  net::ClientSocket* transport = new net::TCPClientSocket(
5394a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      addr, &log, net::NetLog::Source());
5404a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  int rv = transport->Connect(&callback);
5414a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (rv == net::ERR_IO_PENDING)
5424a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    rv = callback.WaitForResult();
5434a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ(net::OK, rv);
5444a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
5454a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  net::SSLConfig ssl_config;
5464a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  for (size_t i = 0; i < arraysize(kCiphersToDisable); ++i)
5474a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    ssl_config.disabled_cipher_suites.push_back(kCiphersToDisable[i]);
5484a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
5494a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  scoped_ptr<net::SSLClientSocket> sock(
5504a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      socket_factory_->CreateSSLClientSocket(
5514a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch          transport, test_server.host_port_pair(), ssl_config, NULL));
5524a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
5534a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_FALSE(sock->IsConnected());
5544a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
5554a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  rv = sock->Connect(&callback);
5564a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_TRUE(net::LogContainsBeginEvent(
5574a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      log.entries(), 5, net::NetLog::TYPE_SSL_CONNECT));
5584a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
5594a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // NSS has special handling that maps a handshake_failure alert received
5604a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // immediately after a client_hello to be a mismatched cipher suite error,
5614a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // leading to ERR_SSL_VERSION_OR_CIPHER_MISMATCH. When using OpenSSL or
5624a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // Secure Transport (OS X), the handshake_failure is bubbled up without any
5634a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // interpretation, leading to ERR_SSL_PROTOCOL_ERROR. Either way, a failure
5644a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // indicates that no cipher suite was negotiated with the test server.
5654a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (rv == net::ERR_IO_PENDING)
5664a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    rv = callback.WaitForResult();
5674a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_TRUE(rv == net::ERR_SSL_VERSION_OR_CIPHER_MISMATCH ||
5684a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch              rv == net::ERR_SSL_PROTOCOL_ERROR);
5694a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // The exact ordering differs between SSLClientSocketNSS (which issues an
5704a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // extra read) and SSLClientSocketMac (which does not). Just make sure the
5714a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // error appears somewhere in the log.
5724a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  net::ExpectLogContainsSomewhere(log.entries(), 0,
5734a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                                  net::NetLog::TYPE_SSL_HANDSHAKE_ERROR,
5744a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                                  net::NetLog::PHASE_NONE);
5754a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
5764a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // We cannot test sock->IsConnected(), as the NSS implementation disconnects
5774a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // the socket when it encounters an error, whereas other implementations
5784a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // leave it connected.
5794a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_TRUE(LogContainsSSLConnectEndEvent(log.entries(), -1));
5804a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
581