ssl_client_socket_unittest.cc revision 4a5e2dc747d50c653511c68ccb2cfbfb740bd5a7
1// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "net/socket/ssl_client_socket.h" 6 7#include "net/base/address_list.h" 8#include "net/base/host_resolver.h" 9#include "net/base/io_buffer.h" 10#include "net/base/net_log.h" 11#include "net/base/net_log_unittest.h" 12#include "net/base/net_errors.h" 13#include "net/base/ssl_config_service.h" 14#include "net/base/test_completion_callback.h" 15#include "net/socket/client_socket_factory.h" 16#include "net/socket/socket_test_util.h" 17#include "net/socket/tcp_client_socket.h" 18#include "net/test/test_server.h" 19#include "testing/gtest/include/gtest/gtest.h" 20#include "testing/platform_test.h" 21 22//----------------------------------------------------------------------------- 23 24const net::SSLConfig kDefaultSSLConfig; 25 26class SSLClientSocketTest : public PlatformTest { 27 public: 28 SSLClientSocketTest() 29 : socket_factory_(net::ClientSocketFactory::GetDefaultFactory()) { 30 } 31 32 protected: 33 net::ClientSocketFactory* socket_factory_; 34}; 35 36//----------------------------------------------------------------------------- 37 38// LogContainsSSLConnectEndEvent returns true if the given index in the given 39// log is an SSL connect end event. The NSS sockets will cork in an attempt to 40// merge the first application data record with the Finished message when false 41// starting. However, in order to avoid the server timing out the handshake, 42// they'll give up waiting for application data and send the Finished after a 43// timeout. This means that an SSL connect end event may appear as a socket 44// write. 45static bool LogContainsSSLConnectEndEvent( 46 const net::CapturingNetLog::EntryList& log, int i) { 47 return net::LogContainsEndEvent(log, -1, net::NetLog::TYPE_SSL_CONNECT) || 48 net::LogContainsEvent(log, -1, net::NetLog::TYPE_SOCKET_BYTES_SENT, 49 net::NetLog::PHASE_NONE); 50}; 51 52TEST_F(SSLClientSocketTest, Connect) { 53 net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath()); 54 ASSERT_TRUE(test_server.Start()); 55 56 net::AddressList addr; 57 ASSERT_TRUE(test_server.GetAddressList(&addr)); 58 59 TestCompletionCallback callback; 60 net::CapturingNetLog log(net::CapturingNetLog::kUnbounded); 61 net::ClientSocket* transport = new net::TCPClientSocket( 62 addr, &log, net::NetLog::Source()); 63 int rv = transport->Connect(&callback); 64 if (rv == net::ERR_IO_PENDING) 65 rv = callback.WaitForResult(); 66 EXPECT_EQ(net::OK, rv); 67 68 scoped_ptr<net::SSLClientSocket> sock( 69 socket_factory_->CreateSSLClientSocket( 70 transport, test_server.host_port_pair(), kDefaultSSLConfig, NULL)); 71 72 EXPECT_FALSE(sock->IsConnected()); 73 74 rv = sock->Connect(&callback); 75 EXPECT_TRUE(net::LogContainsBeginEvent( 76 log.entries(), 5, net::NetLog::TYPE_SSL_CONNECT)); 77 if (rv == net::ERR_IO_PENDING) 78 rv = callback.WaitForResult(); 79 EXPECT_EQ(net::OK, rv); 80 EXPECT_TRUE(sock->IsConnected()); 81 EXPECT_TRUE(LogContainsSSLConnectEndEvent(log.entries(), -1)); 82 83 sock->Disconnect(); 84 EXPECT_FALSE(sock->IsConnected()); 85} 86 87TEST_F(SSLClientSocketTest, ConnectExpired) { 88 net::TestServer::HTTPSOptions https_options( 89 net::TestServer::HTTPSOptions::CERT_EXPIRED); 90 net::TestServer test_server(https_options, FilePath()); 91 ASSERT_TRUE(test_server.Start()); 92 93 net::AddressList addr; 94 ASSERT_TRUE(test_server.GetAddressList(&addr)); 95 96 TestCompletionCallback callback; 97 net::CapturingNetLog log(net::CapturingNetLog::kUnbounded); 98 net::ClientSocket* transport = new net::TCPClientSocket( 99 addr, &log, net::NetLog::Source()); 100 int rv = transport->Connect(&callback); 101 if (rv == net::ERR_IO_PENDING) 102 rv = callback.WaitForResult(); 103 EXPECT_EQ(net::OK, rv); 104 105 scoped_ptr<net::SSLClientSocket> sock( 106 socket_factory_->CreateSSLClientSocket( 107 transport, test_server.host_port_pair(), kDefaultSSLConfig, NULL)); 108 109 EXPECT_FALSE(sock->IsConnected()); 110 111 rv = sock->Connect(&callback); 112 EXPECT_TRUE(net::LogContainsBeginEvent( 113 log.entries(), 5, net::NetLog::TYPE_SSL_CONNECT)); 114 if (rv == net::ERR_IO_PENDING) 115 rv = callback.WaitForResult(); 116 117 EXPECT_EQ(net::ERR_CERT_DATE_INVALID, rv); 118 119 // Rather than testing whether or not the underlying socket is connected, 120 // test that the handshake has finished. This is because it may be 121 // desirable to disconnect the socket before showing a user prompt, since 122 // the user may take indefinitely long to respond. 123 EXPECT_TRUE(LogContainsSSLConnectEndEvent(log.entries(), -1)); 124} 125 126TEST_F(SSLClientSocketTest, ConnectMismatched) { 127 net::TestServer::HTTPSOptions https_options( 128 net::TestServer::HTTPSOptions::CERT_MISMATCHED_NAME); 129 net::TestServer test_server(https_options, FilePath()); 130 ASSERT_TRUE(test_server.Start()); 131 132 net::AddressList addr; 133 ASSERT_TRUE(test_server.GetAddressList(&addr)); 134 135 TestCompletionCallback callback; 136 net::CapturingNetLog log(net::CapturingNetLog::kUnbounded); 137 net::ClientSocket* transport = new net::TCPClientSocket( 138 addr, &log, net::NetLog::Source()); 139 int rv = transport->Connect(&callback); 140 if (rv == net::ERR_IO_PENDING) 141 rv = callback.WaitForResult(); 142 EXPECT_EQ(net::OK, rv); 143 144 scoped_ptr<net::SSLClientSocket> sock( 145 socket_factory_->CreateSSLClientSocket( 146 transport, test_server.host_port_pair(), kDefaultSSLConfig, NULL)); 147 148 EXPECT_FALSE(sock->IsConnected()); 149 150 rv = sock->Connect(&callback); 151 152 EXPECT_TRUE(net::LogContainsBeginEvent( 153 log.entries(), 5, net::NetLog::TYPE_SSL_CONNECT)); 154 if (rv == net::ERR_IO_PENDING) 155 rv = callback.WaitForResult(); 156 157 EXPECT_EQ(net::ERR_CERT_COMMON_NAME_INVALID, rv); 158 159 // Rather than testing whether or not the underlying socket is connected, 160 // test that the handshake has finished. This is because it may be 161 // desirable to disconnect the socket before showing a user prompt, since 162 // the user may take indefinitely long to respond. 163 EXPECT_TRUE(LogContainsSSLConnectEndEvent(log.entries(), -1)); 164} 165 166// Attempt to connect to a page which requests a client certificate. It should 167// return an error code on connect. 168// Flaky: http://crbug.com/54445 169TEST_F(SSLClientSocketTest, FLAKY_ConnectClientAuthCertRequested) { 170 net::TestServer::HTTPSOptions https_options; 171 https_options.request_client_certificate = true; 172 net::TestServer test_server(https_options, FilePath()); 173 ASSERT_TRUE(test_server.Start()); 174 175 net::AddressList addr; 176 ASSERT_TRUE(test_server.GetAddressList(&addr)); 177 178 TestCompletionCallback callback; 179 net::CapturingNetLog log(net::CapturingNetLog::kUnbounded); 180 net::ClientSocket* transport = new net::TCPClientSocket( 181 addr, &log, net::NetLog::Source()); 182 int rv = transport->Connect(&callback); 183 if (rv == net::ERR_IO_PENDING) 184 rv = callback.WaitForResult(); 185 EXPECT_EQ(net::OK, rv); 186 187 scoped_ptr<net::SSLClientSocket> sock( 188 socket_factory_->CreateSSLClientSocket( 189 transport, test_server.host_port_pair(), kDefaultSSLConfig, NULL)); 190 191 EXPECT_FALSE(sock->IsConnected()); 192 193 rv = sock->Connect(&callback); 194 EXPECT_TRUE(net::LogContainsBeginEvent( 195 log.entries(), 5, net::NetLog::TYPE_SSL_CONNECT)); 196 if (rv == net::ERR_IO_PENDING) 197 rv = callback.WaitForResult(); 198 199 EXPECT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv); 200 EXPECT_FALSE(sock->IsConnected()); 201} 202 203// Connect to a server requesting optional client authentication. Send it a 204// null certificate. It should allow the connection. 205// 206// TODO(davidben): Also test providing an actual certificate. 207TEST_F(SSLClientSocketTest, ConnectClientAuthSendNullCert) { 208 net::TestServer::HTTPSOptions https_options; 209 https_options.request_client_certificate = true; 210 net::TestServer test_server(https_options, FilePath()); 211 ASSERT_TRUE(test_server.Start()); 212 213 net::AddressList addr; 214 ASSERT_TRUE(test_server.GetAddressList(&addr)); 215 216 TestCompletionCallback callback; 217 net::CapturingNetLog log(net::CapturingNetLog::kUnbounded); 218 net::ClientSocket* transport = new net::TCPClientSocket( 219 addr, &log, net::NetLog::Source()); 220 int rv = transport->Connect(&callback); 221 if (rv == net::ERR_IO_PENDING) 222 rv = callback.WaitForResult(); 223 EXPECT_EQ(net::OK, rv); 224 225 net::SSLConfig ssl_config = kDefaultSSLConfig; 226 ssl_config.send_client_cert = true; 227 ssl_config.client_cert = NULL; 228 229 scoped_ptr<net::SSLClientSocket> sock( 230 socket_factory_->CreateSSLClientSocket( 231 transport, test_server.host_port_pair(), ssl_config, NULL)); 232 233 EXPECT_FALSE(sock->IsConnected()); 234 235 // Our test server accepts certificate-less connections. 236 // TODO(davidben): Add a test which requires them and verify the error. 237 rv = sock->Connect(&callback); 238 EXPECT_TRUE(net::LogContainsBeginEvent( 239 log.entries(), 5, net::NetLog::TYPE_SSL_CONNECT)); 240 if (rv == net::ERR_IO_PENDING) 241 rv = callback.WaitForResult(); 242 243 EXPECT_EQ(net::OK, rv); 244 EXPECT_TRUE(sock->IsConnected()); 245 EXPECT_TRUE(LogContainsSSLConnectEndEvent(log.entries(), -1)); 246 247 sock->Disconnect(); 248 EXPECT_FALSE(sock->IsConnected()); 249} 250 251// TODO(wtc): Add unit tests for IsConnectedAndIdle: 252// - Server closes an SSL connection (with a close_notify alert message). 253// - Server closes the underlying TCP connection directly. 254// - Server sends data unexpectedly. 255 256TEST_F(SSLClientSocketTest, Read) { 257 net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath()); 258 ASSERT_TRUE(test_server.Start()); 259 260 net::AddressList addr; 261 ASSERT_TRUE(test_server.GetAddressList(&addr)); 262 263 TestCompletionCallback callback; 264 net::ClientSocket* transport = new net::TCPClientSocket( 265 addr, NULL, net::NetLog::Source()); 266 int rv = transport->Connect(&callback); 267 if (rv == net::ERR_IO_PENDING) 268 rv = callback.WaitForResult(); 269 EXPECT_EQ(net::OK, rv); 270 271 scoped_ptr<net::SSLClientSocket> sock( 272 socket_factory_->CreateSSLClientSocket( 273 transport, test_server.host_port_pair(), kDefaultSSLConfig, NULL)); 274 275 rv = sock->Connect(&callback); 276 if (rv == net::ERR_IO_PENDING) 277 rv = callback.WaitForResult(); 278 EXPECT_EQ(net::OK, rv); 279 EXPECT_TRUE(sock->IsConnected()); 280 281 const char request_text[] = "GET / HTTP/1.0\r\n\r\n"; 282 scoped_refptr<net::IOBuffer> request_buffer( 283 new net::IOBuffer(arraysize(request_text) - 1)); 284 memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1); 285 286 rv = sock->Write(request_buffer, arraysize(request_text) - 1, &callback); 287 EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING); 288 289 if (rv == net::ERR_IO_PENDING) 290 rv = callback.WaitForResult(); 291 EXPECT_EQ(static_cast<int>(arraysize(request_text) - 1), rv); 292 293 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(4096)); 294 for (;;) { 295 rv = sock->Read(buf, 4096, &callback); 296 EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING); 297 298 if (rv == net::ERR_IO_PENDING) 299 rv = callback.WaitForResult(); 300 301 EXPECT_GE(rv, 0); 302 if (rv <= 0) 303 break; 304 } 305} 306 307// Test the full duplex mode, with Read and Write pending at the same time. 308// This test also serves as a regression test for http://crbug.com/29815. 309TEST_F(SSLClientSocketTest, Read_FullDuplex) { 310 net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath()); 311 ASSERT_TRUE(test_server.Start()); 312 313 net::AddressList addr; 314 ASSERT_TRUE(test_server.GetAddressList(&addr)); 315 316 TestCompletionCallback callback; // Used for everything except Write. 317 TestCompletionCallback callback2; // Used for Write only. 318 319 net::ClientSocket* transport = new net::TCPClientSocket( 320 addr, NULL, net::NetLog::Source()); 321 int rv = transport->Connect(&callback); 322 if (rv == net::ERR_IO_PENDING) 323 rv = callback.WaitForResult(); 324 EXPECT_EQ(net::OK, rv); 325 326 scoped_ptr<net::SSLClientSocket> sock( 327 socket_factory_->CreateSSLClientSocket( 328 transport, test_server.host_port_pair(), kDefaultSSLConfig, NULL)); 329 330 rv = sock->Connect(&callback); 331 if (rv == net::ERR_IO_PENDING) 332 rv = callback.WaitForResult(); 333 EXPECT_EQ(net::OK, rv); 334 EXPECT_TRUE(sock->IsConnected()); 335 336 // Issue a "hanging" Read first. 337 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(4096)); 338 rv = sock->Read(buf, 4096, &callback); 339 // We haven't written the request, so there should be no response yet. 340 ASSERT_EQ(net::ERR_IO_PENDING, rv); 341 342 // Write the request. 343 // The request is padded with a User-Agent header to a size that causes the 344 // memio circular buffer (4k bytes) in SSLClientSocketNSS to wrap around. 345 // This tests the fix for http://crbug.com/29815. 346 std::string request_text = "GET / HTTP/1.1\r\nUser-Agent: long browser name "; 347 for (int i = 0; i < 3800; ++i) 348 request_text.push_back('*'); 349 request_text.append("\r\n\r\n"); 350 scoped_refptr<net::IOBuffer> request_buffer( 351 new net::StringIOBuffer(request_text)); 352 353 rv = sock->Write(request_buffer, request_text.size(), &callback2); 354 EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING); 355 356 if (rv == net::ERR_IO_PENDING) 357 rv = callback2.WaitForResult(); 358 EXPECT_EQ(static_cast<int>(request_text.size()), rv); 359 360 // Now get the Read result. 361 rv = callback.WaitForResult(); 362 EXPECT_GT(rv, 0); 363} 364 365TEST_F(SSLClientSocketTest, Read_SmallChunks) { 366 net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath()); 367 ASSERT_TRUE(test_server.Start()); 368 369 net::AddressList addr; 370 ASSERT_TRUE(test_server.GetAddressList(&addr)); 371 372 TestCompletionCallback callback; 373 net::ClientSocket* transport = new net::TCPClientSocket( 374 addr, NULL, net::NetLog::Source()); 375 int rv = transport->Connect(&callback); 376 if (rv == net::ERR_IO_PENDING) 377 rv = callback.WaitForResult(); 378 EXPECT_EQ(net::OK, rv); 379 380 scoped_ptr<net::SSLClientSocket> sock( 381 socket_factory_->CreateSSLClientSocket( 382 transport, test_server.host_port_pair(), kDefaultSSLConfig, NULL)); 383 384 rv = sock->Connect(&callback); 385 if (rv == net::ERR_IO_PENDING) 386 rv = callback.WaitForResult(); 387 EXPECT_EQ(net::OK, rv); 388 389 const char request_text[] = "GET / HTTP/1.0\r\n\r\n"; 390 scoped_refptr<net::IOBuffer> request_buffer( 391 new net::IOBuffer(arraysize(request_text) - 1)); 392 memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1); 393 394 rv = sock->Write(request_buffer, arraysize(request_text) - 1, &callback); 395 EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING); 396 397 if (rv == net::ERR_IO_PENDING) 398 rv = callback.WaitForResult(); 399 EXPECT_EQ(static_cast<int>(arraysize(request_text) - 1), rv); 400 401 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(1)); 402 for (;;) { 403 rv = sock->Read(buf, 1, &callback); 404 EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING); 405 406 if (rv == net::ERR_IO_PENDING) 407 rv = callback.WaitForResult(); 408 409 EXPECT_GE(rv, 0); 410 if (rv <= 0) 411 break; 412 } 413} 414 415TEST_F(SSLClientSocketTest, Read_Interrupted) { 416 net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath()); 417 ASSERT_TRUE(test_server.Start()); 418 419 net::AddressList addr; 420 ASSERT_TRUE(test_server.GetAddressList(&addr)); 421 422 TestCompletionCallback callback; 423 net::ClientSocket* transport = new net::TCPClientSocket( 424 addr, NULL, net::NetLog::Source()); 425 int rv = transport->Connect(&callback); 426 if (rv == net::ERR_IO_PENDING) 427 rv = callback.WaitForResult(); 428 EXPECT_EQ(net::OK, rv); 429 430 scoped_ptr<net::SSLClientSocket> sock( 431 socket_factory_->CreateSSLClientSocket( 432 transport, test_server.host_port_pair(), kDefaultSSLConfig, NULL)); 433 434 rv = sock->Connect(&callback); 435 if (rv == net::ERR_IO_PENDING) 436 rv = callback.WaitForResult(); 437 EXPECT_EQ(net::OK, rv); 438 439 const char request_text[] = "GET / HTTP/1.0\r\n\r\n"; 440 scoped_refptr<net::IOBuffer> request_buffer( 441 new net::IOBuffer(arraysize(request_text) - 1)); 442 memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1); 443 444 rv = sock->Write(request_buffer, arraysize(request_text) - 1, &callback); 445 EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING); 446 447 if (rv == net::ERR_IO_PENDING) 448 rv = callback.WaitForResult(); 449 EXPECT_EQ(static_cast<int>(arraysize(request_text) - 1), rv); 450 451 // Do a partial read and then exit. This test should not crash! 452 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(512)); 453 rv = sock->Read(buf, 512, &callback); 454 EXPECT_TRUE(rv > 0 || rv == net::ERR_IO_PENDING); 455 456 if (rv == net::ERR_IO_PENDING) 457 rv = callback.WaitForResult(); 458 459 EXPECT_GT(rv, 0); 460} 461 462// Regression test for http://crbug.com/42538 463TEST_F(SSLClientSocketTest, PrematureApplicationData) { 464 net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath()); 465 ASSERT_TRUE(test_server.Start()); 466 467 net::AddressList addr; 468 TestCompletionCallback callback; 469 470 static const unsigned char application_data[] = { 471 0x17, 0x03, 0x01, 0x00, 0x4a, 0x02, 0x00, 0x00, 0x46, 0x03, 0x01, 0x4b, 472 0xc2, 0xf8, 0xb2, 0xc1, 0x56, 0x42, 0xb9, 0x57, 0x7f, 0xde, 0x87, 0x46, 473 0xf7, 0xa3, 0x52, 0x42, 0x21, 0xf0, 0x13, 0x1c, 0x9c, 0x83, 0x88, 0xd6, 474 0x93, 0x0c, 0xf6, 0x36, 0x30, 0x05, 0x7e, 0x20, 0xb5, 0xb5, 0x73, 0x36, 475 0x53, 0x83, 0x0a, 0xfc, 0x17, 0x63, 0xbf, 0xa0, 0xe4, 0x42, 0x90, 0x0d, 476 0x2f, 0x18, 0x6d, 0x20, 0xd8, 0x36, 0x3f, 0xfc, 0xe6, 0x01, 0xfa, 0x0f, 477 0xa5, 0x75, 0x7f, 0x09, 0x00, 0x04, 0x00, 0x16, 0x03, 0x01, 0x11, 0x57, 478 0x0b, 0x00, 0x11, 0x53, 0x00, 0x11, 0x50, 0x00, 0x06, 0x22, 0x30, 0x82, 479 0x06, 0x1e, 0x30, 0x82, 0x05, 0x06, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 480 0x0a 481 }; 482 483 // All reads and writes complete synchronously (async=false). 484 net::MockRead data_reads[] = { 485 net::MockRead(false, reinterpret_cast<const char*>(application_data), 486 arraysize(application_data)), 487 net::MockRead(false, net::OK), 488 }; 489 490 net::StaticSocketDataProvider data(data_reads, arraysize(data_reads), 491 NULL, 0); 492 493 net::ClientSocket* transport = 494 new net::MockTCPClientSocket(addr, NULL, &data); 495 int rv = transport->Connect(&callback); 496 if (rv == net::ERR_IO_PENDING) 497 rv = callback.WaitForResult(); 498 EXPECT_EQ(net::OK, rv); 499 500 scoped_ptr<net::SSLClientSocket> sock( 501 socket_factory_->CreateSSLClientSocket( 502 transport, test_server.host_port_pair(), kDefaultSSLConfig, NULL)); 503 504 rv = sock->Connect(&callback); 505 EXPECT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv); 506} 507 508#if defined(USE_OPENSSL) 509// TODO(rsleevi): Not implemented for Schannel or OpenSSL. Schannel is 510// controlled by the SSL client socket factory, rather than a define, so it 511// cannot be conditionally disabled here. As Schannel is only used when 512// performing client authentication, it will not be tested here. 513#define MAYBE_CipherSuiteDisables DISABLED_CipherSuiteDisables 514#else 515#define MAYBE_CipherSuiteDisables CipherSuiteDisables 516#endif 517TEST_F(SSLClientSocketTest, MAYBE_CipherSuiteDisables) { 518 // Rather than exhaustively disabling every RC4 ciphersuite defined at 519 // http://www.iana.org/assignments/tls-parameters/tls-parameters.xml, 520 // only disabling those cipher suites that the test server actually 521 // implements. 522 const uint16 kCiphersToDisable[] = { 523 0x0005, // TLS_RSA_WITH_RC4_128_SHA 524 }; 525 526 net::TestServer::HTTPSOptions https_options; 527 // Enable only RC4 on the test server. 528 https_options.bulk_ciphers = 529 net::TestServer::HTTPSOptions::BULK_CIPHER_RC4; 530 net::TestServer test_server(https_options, FilePath()); 531 ASSERT_TRUE(test_server.Start()); 532 533 net::AddressList addr; 534 ASSERT_TRUE(test_server.GetAddressList(&addr)); 535 536 TestCompletionCallback callback; 537 net::CapturingNetLog log(net::CapturingNetLog::kUnbounded); 538 net::ClientSocket* transport = new net::TCPClientSocket( 539 addr, &log, net::NetLog::Source()); 540 int rv = transport->Connect(&callback); 541 if (rv == net::ERR_IO_PENDING) 542 rv = callback.WaitForResult(); 543 EXPECT_EQ(net::OK, rv); 544 545 net::SSLConfig ssl_config; 546 for (size_t i = 0; i < arraysize(kCiphersToDisable); ++i) 547 ssl_config.disabled_cipher_suites.push_back(kCiphersToDisable[i]); 548 549 scoped_ptr<net::SSLClientSocket> sock( 550 socket_factory_->CreateSSLClientSocket( 551 transport, test_server.host_port_pair(), ssl_config, NULL)); 552 553 EXPECT_FALSE(sock->IsConnected()); 554 555 rv = sock->Connect(&callback); 556 EXPECT_TRUE(net::LogContainsBeginEvent( 557 log.entries(), 5, net::NetLog::TYPE_SSL_CONNECT)); 558 559 // NSS has special handling that maps a handshake_failure alert received 560 // immediately after a client_hello to be a mismatched cipher suite error, 561 // leading to ERR_SSL_VERSION_OR_CIPHER_MISMATCH. When using OpenSSL or 562 // Secure Transport (OS X), the handshake_failure is bubbled up without any 563 // interpretation, leading to ERR_SSL_PROTOCOL_ERROR. Either way, a failure 564 // indicates that no cipher suite was negotiated with the test server. 565 if (rv == net::ERR_IO_PENDING) 566 rv = callback.WaitForResult(); 567 EXPECT_TRUE(rv == net::ERR_SSL_VERSION_OR_CIPHER_MISMATCH || 568 rv == net::ERR_SSL_PROTOCOL_ERROR); 569 // The exact ordering differs between SSLClientSocketNSS (which issues an 570 // extra read) and SSLClientSocketMac (which does not). Just make sure the 571 // error appears somewhere in the log. 572 net::ExpectLogContainsSomewhere(log.entries(), 0, 573 net::NetLog::TYPE_SSL_HANDSHAKE_ERROR, 574 net::NetLog::PHASE_NONE); 575 576 // We cannot test sock->IsConnected(), as the NSS implementation disconnects 577 // the socket when it encounters an error, whereas other implementations 578 // leave it connected. 579 EXPECT_TRUE(LogContainsSSLConnectEndEvent(log.entries(), -1)); 580} 581