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/cert_verifier.h" 9 #include "net/base/host_resolver.h" 10 #include "net/base/io_buffer.h" 11 #include "net/base/net_log.h" 12 #include "net/base/net_log_unittest.h" 13 #include "net/base/net_errors.h" 14 #include "net/base/ssl_config_service.h" 15 #include "net/base/test_completion_callback.h" 16 #include "net/socket/client_socket_factory.h" 17 #include "net/socket/socket_test_util.h" 18 #include "net/socket/tcp_client_socket.h" 19 #include "net/test/test_server.h" 20 #include "testing/gtest/include/gtest/gtest.h" 21 #include "testing/platform_test.h" 22 23 //----------------------------------------------------------------------------- 24 25 const net::SSLConfig kDefaultSSLConfig; 26 27 class SSLClientSocketTest : public PlatformTest { 28 public: 29 SSLClientSocketTest() 30 : socket_factory_(net::ClientSocketFactory::GetDefaultFactory()), 31 cert_verifier_(new net::CertVerifier) { 32 } 33 34 protected: 35 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 46 net::ClientSocketFactory* socket_factory_; 47 scoped_ptr<net::CertVerifier> cert_verifier_; 48 }; 49 50 //----------------------------------------------------------------------------- 51 52 // 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. 59 static bool LogContainsSSLConnectEndEvent( 60 const net::CapturingNetLog::EntryList& log, int i) { 61 return net::LogContainsEndEvent(log, i, net::NetLog::TYPE_SSL_CONNECT) || 62 net::LogContainsEvent(log, i, net::NetLog::TYPE_SOCKET_BYTES_SENT, 63 net::NetLog::PHASE_NONE); 64 }; 65 66 TEST_F(SSLClientSocketTest, Connect) { 67 net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath()); 68 ASSERT_TRUE(test_server.Start()); 69 70 net::AddressList addr; 71 ASSERT_TRUE(test_server.GetAddressList(&addr)); 72 73 TestCompletionCallback callback; 74 net::CapturingNetLog log(net::CapturingNetLog::kUnbounded); 75 net::ClientSocket* transport = new net::TCPClientSocket( 76 addr, &log, net::NetLog::Source()); 77 int rv = transport->Connect(&callback); 78 if (rv == net::ERR_IO_PENDING) 79 rv = callback.WaitForResult(); 80 EXPECT_EQ(net::OK, rv); 81 82 scoped_ptr<net::SSLClientSocket> sock( 83 socket_factory_->CreateSSLClientSocket( 84 transport, test_server.host_port_pair(), kDefaultSSLConfig, 85 NULL, cert_verifier_.get())); 86 87 EXPECT_FALSE(sock->IsConnected()); 88 89 rv = sock->Connect(&callback); 90 91 net::CapturingNetLog::EntryList entries; 92 log.GetEntries(&entries); 93 EXPECT_TRUE(net::LogContainsBeginEvent( 94 entries, 5, net::NetLog::TYPE_SSL_CONNECT)); 95 if (rv == net::ERR_IO_PENDING) 96 rv = callback.WaitForResult(); 97 EXPECT_EQ(net::OK, rv); 98 EXPECT_TRUE(sock->IsConnected()); 99 log.GetEntries(&entries); 100 EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1)); 101 102 sock->Disconnect(); 103 EXPECT_FALSE(sock->IsConnected()); 104 } 105 106 TEST_F(SSLClientSocketTest, ConnectExpired) { 107 net::TestServer::HTTPSOptions https_options( 108 net::TestServer::HTTPSOptions::CERT_EXPIRED); 109 net::TestServer test_server(https_options, FilePath()); 110 ASSERT_TRUE(test_server.Start()); 111 112 net::AddressList addr; 113 ASSERT_TRUE(test_server.GetAddressList(&addr)); 114 115 TestCompletionCallback callback; 116 net::CapturingNetLog log(net::CapturingNetLog::kUnbounded); 117 net::ClientSocket* transport = new net::TCPClientSocket( 118 addr, &log, net::NetLog::Source()); 119 int rv = transport->Connect(&callback); 120 if (rv == net::ERR_IO_PENDING) 121 rv = callback.WaitForResult(); 122 EXPECT_EQ(net::OK, rv); 123 124 scoped_ptr<net::SSLClientSocket> sock( 125 CreateSSLClientSocket(transport, test_server.host_port_pair(), 126 kDefaultSSLConfig)); 127 128 EXPECT_FALSE(sock->IsConnected()); 129 130 rv = sock->Connect(&callback); 131 132 net::CapturingNetLog::EntryList entries; 133 log.GetEntries(&entries); 134 EXPECT_TRUE(net::LogContainsBeginEvent( 135 entries, 5, net::NetLog::TYPE_SSL_CONNECT)); 136 if (rv == net::ERR_IO_PENDING) 137 rv = callback.WaitForResult(); 138 139 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. 145 log.GetEntries(&entries); 146 EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1)); 147 } 148 149 TEST_F(SSLClientSocketTest, ConnectMismatched) { 150 net::TestServer::HTTPSOptions https_options( 151 net::TestServer::HTTPSOptions::CERT_MISMATCHED_NAME); 152 net::TestServer test_server(https_options, FilePath()); 153 ASSERT_TRUE(test_server.Start()); 154 155 net::AddressList addr; 156 ASSERT_TRUE(test_server.GetAddressList(&addr)); 157 158 TestCompletionCallback callback; 159 net::CapturingNetLog log(net::CapturingNetLog::kUnbounded); 160 net::ClientSocket* transport = new net::TCPClientSocket( 161 addr, &log, net::NetLog::Source()); 162 int rv = transport->Connect(&callback); 163 if (rv == net::ERR_IO_PENDING) 164 rv = callback.WaitForResult(); 165 EXPECT_EQ(net::OK, rv); 166 167 scoped_ptr<net::SSLClientSocket> sock( 168 CreateSSLClientSocket(transport, test_server.host_port_pair(), 169 kDefaultSSLConfig)); 170 171 EXPECT_FALSE(sock->IsConnected()); 172 173 rv = sock->Connect(&callback); 174 175 net::CapturingNetLog::EntryList entries; 176 log.GetEntries(&entries); 177 EXPECT_TRUE(net::LogContainsBeginEvent( 178 entries, 5, net::NetLog::TYPE_SSL_CONNECT)); 179 if (rv == net::ERR_IO_PENDING) 180 rv = callback.WaitForResult(); 181 182 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. 188 log.GetEntries(&entries); 189 EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1)); 190 } 191 192 // Attempt to connect to a page which requests a client certificate. It should 193 // return an error code on connect. 194 TEST_F(SSLClientSocketTest, ConnectClientAuthCertRequested) { 195 net::TestServer::HTTPSOptions https_options; 196 https_options.request_client_certificate = true; 197 net::TestServer test_server(https_options, FilePath()); 198 ASSERT_TRUE(test_server.Start()); 199 200 net::AddressList addr; 201 ASSERT_TRUE(test_server.GetAddressList(&addr)); 202 203 TestCompletionCallback callback; 204 net::CapturingNetLog log(net::CapturingNetLog::kUnbounded); 205 net::ClientSocket* transport = new net::TCPClientSocket( 206 addr, &log, net::NetLog::Source()); 207 int rv = transport->Connect(&callback); 208 if (rv == net::ERR_IO_PENDING) 209 rv = callback.WaitForResult(); 210 EXPECT_EQ(net::OK, rv); 211 212 scoped_ptr<net::SSLClientSocket> sock( 213 CreateSSLClientSocket(transport, test_server.host_port_pair(), 214 kDefaultSSLConfig)); 215 216 EXPECT_FALSE(sock->IsConnected()); 217 218 rv = sock->Connect(&callback); 219 220 net::CapturingNetLog::EntryList entries; 221 log.GetEntries(&entries); 222 EXPECT_TRUE(net::LogContainsBeginEvent( 223 entries, 5, net::NetLog::TYPE_SSL_CONNECT)); 224 if (rv == net::ERR_IO_PENDING) 225 rv = callback.WaitForResult(); 226 227 log.GetEntries(&entries); 228 // 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); 246 EXPECT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv); 247 EXPECT_FALSE(sock->IsConnected()); 248 } 249 250 // 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. 254 TEST_F(SSLClientSocketTest, ConnectClientAuthSendNullCert) { 255 net::TestServer::HTTPSOptions https_options; 256 https_options.request_client_certificate = true; 257 net::TestServer test_server(https_options, 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::CapturingNetLog log(net::CapturingNetLog::kUnbounded); 265 net::ClientSocket* transport = new net::TCPClientSocket( 266 addr, &log, net::NetLog::Source()); 267 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( 277 CreateSSLClientSocket(transport, test_server.host_port_pair(), 278 ssl_config)); 279 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); 285 286 net::CapturingNetLog::EntryList entries; 287 log.GetEntries(&entries); 288 EXPECT_TRUE(net::LogContainsBeginEvent( 289 entries, 5, net::NetLog::TYPE_SSL_CONNECT)); 290 if (rv == net::ERR_IO_PENDING) 291 rv = callback.WaitForResult(); 292 293 EXPECT_EQ(net::OK, rv); 294 EXPECT_TRUE(sock->IsConnected()); 295 log.GetEntries(&entries); 296 EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1)); 297 298 sock->Disconnect(); 299 EXPECT_FALSE(sock->IsConnected()); 300 } 301 302 // 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 307 TEST_F(SSLClientSocketTest, Read) { 308 net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath()); 309 ASSERT_TRUE(test_server.Start()); 310 311 net::AddressList addr; 312 ASSERT_TRUE(test_server.GetAddressList(&addr)); 313 314 TestCompletionCallback callback; 315 net::ClientSocket* transport = new net::TCPClientSocket( 316 addr, NULL, net::NetLog::Source()); 317 int rv = transport->Connect(&callback); 318 if (rv == net::ERR_IO_PENDING) 319 rv = callback.WaitForResult(); 320 EXPECT_EQ(net::OK, rv); 321 322 scoped_ptr<net::SSLClientSocket> sock( 323 CreateSSLClientSocket(transport, test_server.host_port_pair(), 324 kDefaultSSLConfig)); 325 326 rv = sock->Connect(&callback); 327 if (rv == net::ERR_IO_PENDING) 328 rv = callback.WaitForResult(); 329 EXPECT_EQ(net::OK, rv); 330 EXPECT_TRUE(sock->IsConnected()); 331 332 const char request_text[] = "GET / HTTP/1.0\r\n\r\n"; 333 scoped_refptr<net::IOBuffer> request_buffer( 334 new net::IOBuffer(arraysize(request_text) - 1)); 335 memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1); 336 337 rv = sock->Write(request_buffer, arraysize(request_text) - 1, &callback); 338 EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING); 339 340 if (rv == net::ERR_IO_PENDING) 341 rv = callback.WaitForResult(); 342 EXPECT_EQ(static_cast<int>(arraysize(request_text) - 1), rv); 343 344 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(4096)); 345 for (;;) { 346 rv = sock->Read(buf, 4096, &callback); 347 EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING); 348 349 if (rv == net::ERR_IO_PENDING) 350 rv = callback.WaitForResult(); 351 352 EXPECT_GE(rv, 0); 353 if (rv <= 0) 354 break; 355 } 356 } 357 358 // 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. 360 TEST_F(SSLClientSocketTest, Read_FullDuplex) { 361 net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath()); 362 ASSERT_TRUE(test_server.Start()); 363 364 net::AddressList addr; 365 ASSERT_TRUE(test_server.GetAddressList(&addr)); 366 367 TestCompletionCallback callback; // Used for everything except Write. 368 TestCompletionCallback callback2; // Used for Write only. 369 370 net::ClientSocket* transport = new net::TCPClientSocket( 371 addr, NULL, net::NetLog::Source()); 372 int rv = transport->Connect(&callback); 373 if (rv == net::ERR_IO_PENDING) 374 rv = callback.WaitForResult(); 375 EXPECT_EQ(net::OK, rv); 376 377 scoped_ptr<net::SSLClientSocket> sock( 378 socket_factory_->CreateSSLClientSocket( 379 transport, test_server.host_port_pair(), kDefaultSSLConfig, 380 NULL, cert_verifier_.get())); 381 382 rv = sock->Connect(&callback); 383 if (rv == net::ERR_IO_PENDING) 384 rv = callback.WaitForResult(); 385 EXPECT_EQ(net::OK, rv); 386 EXPECT_TRUE(sock->IsConnected()); 387 388 // Issue a "hanging" Read first. 389 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(4096)); 390 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"); 402 scoped_refptr<net::IOBuffer> request_buffer( 403 new net::StringIOBuffer(request_text)); 404 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 417 TEST_F(SSLClientSocketTest, Read_SmallChunks) { 418 net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath()); 419 ASSERT_TRUE(test_server.Start()); 420 421 net::AddressList addr; 422 ASSERT_TRUE(test_server.GetAddressList(&addr)); 423 424 TestCompletionCallback callback; 425 net::ClientSocket* transport = new net::TCPClientSocket( 426 addr, NULL, net::NetLog::Source()); 427 int rv = transport->Connect(&callback); 428 if (rv == net::ERR_IO_PENDING) 429 rv = callback.WaitForResult(); 430 EXPECT_EQ(net::OK, rv); 431 432 scoped_ptr<net::SSLClientSocket> sock( 433 CreateSSLClientSocket(transport, test_server.host_port_pair(), 434 kDefaultSSLConfig)); 435 436 rv = sock->Connect(&callback); 437 if (rv == net::ERR_IO_PENDING) 438 rv = callback.WaitForResult(); 439 EXPECT_EQ(net::OK, rv); 440 441 const char request_text[] = "GET / HTTP/1.0\r\n\r\n"; 442 scoped_refptr<net::IOBuffer> request_buffer( 443 new net::IOBuffer(arraysize(request_text) - 1)); 444 memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1); 445 446 rv = sock->Write(request_buffer, arraysize(request_text) - 1, &callback); 447 EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING); 448 449 if (rv == net::ERR_IO_PENDING) 450 rv = callback.WaitForResult(); 451 EXPECT_EQ(static_cast<int>(arraysize(request_text) - 1), rv); 452 453 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(1)); 454 for (;;) { 455 rv = sock->Read(buf, 1, &callback); 456 EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING); 457 458 if (rv == net::ERR_IO_PENDING) 459 rv = callback.WaitForResult(); 460 461 EXPECT_GE(rv, 0); 462 if (rv <= 0) 463 break; 464 } 465 } 466 467 TEST_F(SSLClientSocketTest, Read_Interrupted) { 468 net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath()); 469 ASSERT_TRUE(test_server.Start()); 470 471 net::AddressList addr; 472 ASSERT_TRUE(test_server.GetAddressList(&addr)); 473 474 TestCompletionCallback callback; 475 net::ClientSocket* transport = new net::TCPClientSocket( 476 addr, NULL, net::NetLog::Source()); 477 int rv = transport->Connect(&callback); 478 if (rv == net::ERR_IO_PENDING) 479 rv = callback.WaitForResult(); 480 EXPECT_EQ(net::OK, rv); 481 482 scoped_ptr<net::SSLClientSocket> sock( 483 CreateSSLClientSocket(transport, test_server.host_port_pair(), 484 kDefaultSSLConfig)); 485 486 rv = sock->Connect(&callback); 487 if (rv == net::ERR_IO_PENDING) 488 rv = callback.WaitForResult(); 489 EXPECT_EQ(net::OK, rv); 490 491 const char request_text[] = "GET / HTTP/1.0\r\n\r\n"; 492 scoped_refptr<net::IOBuffer> request_buffer( 493 new net::IOBuffer(arraysize(request_text) - 1)); 494 memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1); 495 496 rv = sock->Write(request_buffer, arraysize(request_text) - 1, &callback); 497 EXPECT_TRUE(rv >= 0 || rv == net::ERR_IO_PENDING); 498 499 if (rv == net::ERR_IO_PENDING) 500 rv = callback.WaitForResult(); 501 EXPECT_EQ(static_cast<int>(arraysize(request_text) - 1), rv); 502 503 // Do a partial read and then exit. This test should not crash! 504 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(512)); 505 rv = sock->Read(buf, 512, &callback); 506 EXPECT_TRUE(rv > 0 || rv == net::ERR_IO_PENDING); 507 508 if (rv == net::ERR_IO_PENDING) 509 rv = callback.WaitForResult(); 510 511 EXPECT_GT(rv, 0); 512 } 513 514 // Regression test for http://crbug.com/42538 515 TEST_F(SSLClientSocketTest, PrematureApplicationData) { 516 net::TestServer test_server(net::TestServer::TYPE_HTTPS, FilePath()); 517 ASSERT_TRUE(test_server.Start()); 518 519 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( 553 CreateSSLClientSocket(transport, test_server.host_port_pair(), 554 kDefaultSSLConfig)); 555 556 rv = sock->Connect(&callback); 557 EXPECT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv); 558 } 559 560 // TODO(rsleevi): Not implemented for Schannel. As Schannel is only used when 561 // performing client authentication, it will not be tested here. 562 TEST_F(SSLClientSocketTest, CipherSuiteDisables) { 563 // 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( 595 CreateSSLClientSocket(transport, test_server.host_port_pair(), 596 ssl_config)); 597 598 EXPECT_FALSE(sock->IsConnected()); 599 600 rv = sock->Connect(&callback); 601 net::CapturingNetLog::EntryList entries; 602 log.GetEntries(&entries); 603 EXPECT_TRUE(net::LogContainsBeginEvent( 604 entries, 5, net::NetLog::TYPE_SSL_CONNECT)); 605 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. 619 log.GetEntries(&entries); 620 net::ExpectLogContainsSomewhere(entries, 0, 621 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. 627 // 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)); 637 } 638