Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/socket/ssl_client_socket.h" | 5 #include "net/socket/ssl_client_socket.h" |
| 6 | 6 |
| 7 #include "base/callback_helpers.h" | 7 #include "base/callback_helpers.h" |
| 8 #include "base/memory/ref_counted.h" | 8 #include "base/memory/ref_counted.h" |
| 9 #include "base/run_loop.h" | 9 #include "base/run_loop.h" |
| 10 #include "net/base/address_list.h" | 10 #include "net/base/address_list.h" |
| (...skipping 581 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 592 SSLClientSocketTest() | 592 SSLClientSocketTest() |
| 593 : socket_factory_(ClientSocketFactory::GetDefaultFactory()), | 593 : socket_factory_(ClientSocketFactory::GetDefaultFactory()), |
| 594 cert_verifier_(new MockCertVerifier), | 594 cert_verifier_(new MockCertVerifier), |
| 595 transport_security_state_(new TransportSecurityState) { | 595 transport_security_state_(new TransportSecurityState) { |
| 596 cert_verifier_->set_default_result(OK); | 596 cert_verifier_->set_default_result(OK); |
| 597 context_.cert_verifier = cert_verifier_.get(); | 597 context_.cert_verifier = cert_verifier_.get(); |
| 598 context_.transport_security_state = transport_security_state_.get(); | 598 context_.transport_security_state = transport_security_state_.get(); |
| 599 } | 599 } |
| 600 | 600 |
| 601 protected: | 601 protected: |
| 602 // Sets up a TCP connection to a HTTPS server. To actually do the SSL | 602 bool StartTestServer(const SpawnedTestServer::SSLOptions& ssl_options) { |
| 603 // handshake, follow up with call to CreateAndConnectSSLClientSocket() below. | |
| 604 bool ConnectToTestServer(SpawnedTestServer::SSLOptions& ssl_options) { | |
| 605 test_server_.reset(new SpawnedTestServer( | 603 test_server_.reset(new SpawnedTestServer( |
| 606 SpawnedTestServer::TYPE_HTTPS, ssl_options, base::FilePath())); | 604 SpawnedTestServer::TYPE_HTTPS, ssl_options, base::FilePath())); |
| 607 if (!test_server_->Start()) { | 605 if (!test_server_->Start()) { |
| 608 LOG(ERROR) << "Could not start SpawnedTestServer"; | 606 LOG(ERROR) << "Could not start SpawnedTestServer"; |
| 609 return false; | 607 return false; |
| 610 } | 608 } |
| 611 | 609 |
| 612 if (!test_server_->GetAddressList(&addr_)) { | 610 if (!test_server_->GetAddressList(&addr_)) { |
| 613 LOG(ERROR) << "Could not get SpawnedTestServer address list"; | 611 LOG(ERROR) << "Could not get SpawnedTestServer address list"; |
| 614 return false; | 612 return false; |
| 615 } | 613 } |
| 614 return true; | |
| 615 } | |
| 616 | |
| 617 // Sets up a TCP connection to a HTTPS server. To actually do the SSL | |
| 618 // handshake, follow up with call to CreateAndConnectSSLClientSocket() below. | |
| 619 bool ConnectToTestServer(const SpawnedTestServer::SSLOptions& ssl_options) { | |
| 620 if (!StartTestServer(ssl_options)) | |
| 621 return false; | |
| 616 | 622 |
| 617 transport_.reset(new TCPClientSocket(addr_, &log_, NetLog::Source())); | 623 transport_.reset(new TCPClientSocket(addr_, &log_, NetLog::Source())); |
| 618 int rv = callback_.GetResult(transport_->Connect(callback_.callback())); | 624 int rv = callback_.GetResult(transport_->Connect(callback_.callback())); |
| 619 if (rv != OK) { | 625 if (rv != OK) { |
| 620 LOG(ERROR) << "Could not connect to SpawnedTestServer"; | 626 LOG(ERROR) << "Could not connect to SpawnedTestServer"; |
| 621 return false; | 627 return false; |
| 622 } | 628 } |
| 623 return true; | 629 return true; |
| 624 } | 630 } |
| 625 | 631 |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 653 *result = callback_.GetResult(sock_->Connect(callback_.callback())); | 659 *result = callback_.GetResult(sock_->Connect(callback_.callback())); |
| 654 return true; | 660 return true; |
| 655 } | 661 } |
| 656 | 662 |
| 657 ClientSocketFactory* socket_factory_; | 663 ClientSocketFactory* socket_factory_; |
| 658 scoped_ptr<MockCertVerifier> cert_verifier_; | 664 scoped_ptr<MockCertVerifier> cert_verifier_; |
| 659 scoped_ptr<TransportSecurityState> transport_security_state_; | 665 scoped_ptr<TransportSecurityState> transport_security_state_; |
| 660 SSLClientSocketContext context_; | 666 SSLClientSocketContext context_; |
| 661 scoped_ptr<SSLClientSocket> sock_; | 667 scoped_ptr<SSLClientSocket> sock_; |
| 662 CapturingNetLog log_; | 668 CapturingNetLog log_; |
| 669 AddressList addr_; | |
| 670 scoped_ptr<SpawnedTestServer> test_server_; | |
| 663 | 671 |
| 664 private: | 672 private: |
| 665 scoped_ptr<StreamSocket> transport_; | 673 scoped_ptr<StreamSocket> transport_; |
| 666 scoped_ptr<SpawnedTestServer> test_server_; | |
| 667 TestCompletionCallback callback_; | 674 TestCompletionCallback callback_; |
| 668 AddressList addr_; | |
| 669 }; | 675 }; |
| 670 | 676 |
| 671 // Verifies the correctness of GetSSLCertRequestInfo. | 677 // Verifies the correctness of GetSSLCertRequestInfo. |
| 672 class SSLClientSocketCertRequestInfoTest : public SSLClientSocketTest { | 678 class SSLClientSocketCertRequestInfoTest : public SSLClientSocketTest { |
| 673 protected: | 679 protected: |
| 674 // Creates a test server with the given SSLOptions, connects to it and returns | 680 // Creates a test server with the given SSLOptions, connects to it and returns |
| 675 // the SSLCertRequestInfo reported by the socket. | 681 // the SSLCertRequestInfo reported by the socket. |
| 676 scoped_refptr<SSLCertRequestInfo> GetCertRequest( | 682 scoped_refptr<SSLCertRequestInfo> GetCertRequest( |
| 677 SpawnedTestServer::SSLOptions ssl_options) { | 683 SpawnedTestServer::SSLOptions ssl_options) { |
| 678 SpawnedTestServer test_server( | 684 SpawnedTestServer test_server( |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 706 EXPECT_FALSE(sock->IsConnected()); | 712 EXPECT_FALSE(sock->IsConnected()); |
| 707 EXPECT_TRUE( | 713 EXPECT_TRUE( |
| 708 test_server.host_port_pair().Equals(request_info->host_and_port)); | 714 test_server.host_port_pair().Equals(request_info->host_and_port)); |
| 709 | 715 |
| 710 return request_info; | 716 return request_info; |
| 711 } | 717 } |
| 712 }; | 718 }; |
| 713 | 719 |
| 714 class SSLClientSocketFalseStartTest : public SSLClientSocketTest { | 720 class SSLClientSocketFalseStartTest : public SSLClientSocketTest { |
| 715 protected: | 721 protected: |
| 716 void TestFalseStart(const SpawnedTestServer::SSLOptions& server_options, | 722 void CreateAndConnectUpToServerFinished( |
|
Ryan Sleevi
2014/05/31 00:46:11
s/UpToServerFinished/UntilServerFinishedReceived?
davidben
2014/06/02 18:45:38
Done.
| |
| 717 const SSLConfig& client_config, | 723 const SSLConfig& client_config, |
| 718 bool expect_false_start) { | 724 TestCompletionCallback* callback, |
| 719 SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS, | 725 FakeBlockingStreamSocket** out_raw_transport, |
|
Ryan Sleevi
2014/05/31 00:46:11
More documentation is needed here. My red alert al
davidben
2014/06/02 18:45:38
Documented. (The FakeBlockingStreamSocket annoying
| |
| 720 server_options, | 726 scoped_ptr<SSLClientSocket>* out_sock) { |
| 721 base::FilePath()); | |
| 722 ASSERT_TRUE(test_server.Start()); | |
| 723 | |
| 724 AddressList addr; | |
| 725 ASSERT_TRUE(test_server.GetAddressList(&addr)); | |
| 726 | |
| 727 TestCompletionCallback callback; | |
| 728 scoped_ptr<StreamSocket> real_transport( | 727 scoped_ptr<StreamSocket> real_transport( |
| 729 new TCPClientSocket(addr, NULL, NetLog::Source())); | 728 new TCPClientSocket(addr_, NULL, NetLog::Source())); |
| 730 scoped_ptr<FakeBlockingStreamSocket> transport( | 729 scoped_ptr<FakeBlockingStreamSocket> transport( |
| 731 new FakeBlockingStreamSocket(real_transport.Pass())); | 730 new FakeBlockingStreamSocket(real_transport.Pass())); |
| 732 int rv = callback.GetResult(transport->Connect(callback.callback())); | 731 int rv = callback->GetResult(transport->Connect(callback->callback())); |
| 733 EXPECT_EQ(OK, rv); | 732 EXPECT_EQ(OK, rv); |
| 734 | 733 |
| 735 FakeBlockingStreamSocket* raw_transport = transport.get(); | 734 FakeBlockingStreamSocket* raw_transport = transport.get(); |
| 736 scoped_ptr<SSLClientSocket> sock( | 735 scoped_ptr<SSLClientSocket> sock = |
| 737 CreateSSLClientSocket(transport.PassAs<StreamSocket>(), | 736 CreateSSLClientSocket(transport.PassAs<StreamSocket>(), |
| 738 test_server.host_port_pair(), | 737 test_server_->host_port_pair(), |
| 739 client_config)); | 738 client_config); |
| 740 | 739 |
| 741 // Connect. Stop before the client processes the first server leg | 740 // Connect. Stop before the client processes the first server leg |
| 742 // (ServerHello, etc.) | 741 // (ServerHello, etc.) |
| 743 raw_transport->BlockReadResult(); | 742 raw_transport->BlockReadResult(); |
| 744 rv = sock->Connect(callback.callback()); | 743 rv = sock->Connect(callback->callback()); |
| 745 EXPECT_EQ(ERR_IO_PENDING, rv); | 744 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 746 raw_transport->WaitForReadResult(); | 745 raw_transport->WaitForReadResult(); |
| 747 | 746 |
| 748 // Release the ServerHello and wait for the client to write | 747 // Release the ServerHello and wait for the client to write |
| 749 // ClientKeyExchange, etc. (A proxy for waiting for the entirety of the | 748 // ClientKeyExchange, etc. (A proxy for waiting for the entirety of the |
| 750 // server's leg to complete, since it may span multiple reads.) | 749 // server's leg to complete, since it may span multiple reads.) |
| 751 EXPECT_FALSE(callback.have_result()); | 750 EXPECT_FALSE(callback->have_result()); |
| 752 raw_transport->BlockWrite(); | 751 raw_transport->BlockWrite(); |
| 753 raw_transport->UnblockReadResult(); | 752 raw_transport->UnblockReadResult(); |
| 754 raw_transport->WaitForWrite(); | 753 raw_transport->WaitForWrite(); |
| 755 | 754 |
| 756 // And, finally, release that and block the next server leg | 755 // And, finally, release that and block the next server leg |
| 757 // (ChangeCipherSpec, Finished). Note: callback.have_result() may or may not | 756 // (ChangeCipherSpec, Finished). Note: callback->have_result() may or may |
| 758 // be true at this point depending on whether the SSL implementation waits | 757 // not be true at this point depending on whether the SSL implementation |
| 759 // for the client second leg to clear the internal write buffer and hit the | 758 // waits for the client second leg to clear the internal write buffer and |
| 760 // network. | 759 // hit the network. |
| 761 raw_transport->BlockReadResult(); | 760 raw_transport->BlockReadResult(); |
| 762 raw_transport->UnblockWrite(); | 761 raw_transport->UnblockWrite(); |
| 763 | 762 |
| 763 *out_raw_transport = raw_transport; | |
| 764 *out_sock = sock.Pass(); | |
| 765 } | |
| 766 | |
| 767 void TestFalseStart(const SpawnedTestServer::SSLOptions& server_options, | |
| 768 const SSLConfig& client_config, | |
| 769 bool expect_false_start) { | |
| 770 ASSERT_TRUE(StartTestServer(server_options)); | |
| 771 | |
| 772 TestCompletionCallback callback; | |
| 773 FakeBlockingStreamSocket* raw_transport; | |
| 774 scoped_ptr<SSLClientSocket> sock; | |
| 775 CreateAndConnectUpToServerFinished( | |
| 776 client_config, &callback, &raw_transport, &sock); | |
|
Ryan Sleevi
2014/05/31 00:46:11
DANGER: If you ever added an ASSERT_() to CreateAn
davidben
2014/06/02 18:45:38
Oh, so that's how you do it... done.
| |
| 777 | |
| 764 if (expect_false_start) { | 778 if (expect_false_start) { |
| 765 // When False Starting, the handshake should complete before receiving the | 779 // When False Starting, the handshake should complete before receiving the |
| 766 // Change Cipher Spec and Finished messages. | 780 // Change Cipher Spec and Finished messages. |
| 767 rv = callback.GetResult(rv); | 781 int rv = callback.GetResult(ERR_IO_PENDING); |
|
Ryan Sleevi
2014/05/31 00:46:11
Just use
int rv = callback.WaitForResult();
no n
davidben
2014/06/02 18:45:38
Done.
| |
| 768 EXPECT_EQ(OK, rv); | 782 EXPECT_EQ(OK, rv); |
| 769 EXPECT_TRUE(sock->IsConnected()); | 783 EXPECT_TRUE(sock->IsConnected()); |
| 770 | 784 |
| 771 const char request_text[] = "GET / HTTP/1.0\r\n\r\n"; | 785 const char request_text[] = "GET / HTTP/1.0\r\n\r\n"; |
| 772 static const int kRequestTextSize = | 786 static const int kRequestTextSize = |
| 773 static_cast<int>(arraysize(request_text) - 1); | 787 static_cast<int>(arraysize(request_text) - 1); |
| 774 scoped_refptr<IOBuffer> request_buffer(new IOBuffer(kRequestTextSize)); | 788 scoped_refptr<IOBuffer> request_buffer(new IOBuffer(kRequestTextSize)); |
| 775 memcpy(request_buffer->data(), request_text, kRequestTextSize); | 789 memcpy(request_buffer->data(), request_text, kRequestTextSize); |
| 776 | 790 |
| 777 // Write the request. | 791 // Write the request. |
| (...skipping 1697 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2475 TEST_F(SSLClientSocketFalseStartTest, NoForwardSecrecy) { | 2489 TEST_F(SSLClientSocketFalseStartTest, NoForwardSecrecy) { |
| 2476 SpawnedTestServer::SSLOptions server_options; | 2490 SpawnedTestServer::SSLOptions server_options; |
| 2477 server_options.key_exchanges = | 2491 server_options.key_exchanges = |
| 2478 SpawnedTestServer::SSLOptions::KEY_EXCHANGE_RSA; | 2492 SpawnedTestServer::SSLOptions::KEY_EXCHANGE_RSA; |
| 2479 server_options.enable_npn = true; | 2493 server_options.enable_npn = true; |
| 2480 SSLConfig client_config; | 2494 SSLConfig client_config; |
| 2481 client_config.next_protos.push_back("http/1.1"); | 2495 client_config.next_protos.push_back("http/1.1"); |
| 2482 TestFalseStart(server_options, client_config, false); | 2496 TestFalseStart(server_options, client_config, false); |
| 2483 } | 2497 } |
| 2484 | 2498 |
| 2499 // Test that sessions are resumable after receiving the server Finished message. | |
| 2500 TEST_F(SSLClientSocketFalseStartTest, SessionResumption) { | |
| 2501 // Start a server. | |
| 2502 SpawnedTestServer::SSLOptions server_options; | |
| 2503 server_options.key_exchanges = | |
| 2504 SpawnedTestServer::SSLOptions::KEY_EXCHANGE_DHE_RSA; | |
| 2505 server_options.enable_npn = true; | |
| 2506 SSLConfig client_config; | |
| 2507 client_config.next_protos.push_back("http/1.1"); | |
| 2508 | |
| 2509 // Let a full handshake complete with False Start. | |
| 2510 TestFalseStart(server_options, client_config, true); | |
| 2511 | |
| 2512 // Make a second connection. | |
| 2513 TestCompletionCallback callback; | |
| 2514 scoped_ptr<StreamSocket> transport2( | |
| 2515 new TCPClientSocket(addr_, &log_, NetLog::Source())); | |
| 2516 EXPECT_EQ(OK, callback.GetResult(transport2->Connect(callback.callback()))); | |
| 2517 scoped_ptr<SSLClientSocket> sock2 = CreateSSLClientSocket( | |
| 2518 transport2.Pass(), test_server_->host_port_pair(), client_config); | |
| 2519 EXPECT_EQ(OK, callback.GetResult(sock2->Connect(callback.callback()))); | |
| 2520 | |
| 2521 // It should resume the session. | |
| 2522 SSLInfo ssl_info; | |
| 2523 EXPECT_TRUE(sock2->GetSSLInfo(&ssl_info)); | |
| 2524 EXPECT_EQ(SSLInfo::HANDSHAKE_RESUME, ssl_info.handshake_type); | |
| 2525 } | |
| 2526 | |
| 2527 // Test that sessions are not resumable before receiving the server Finished | |
| 2528 // message. | |
| 2529 TEST_F(SSLClientSocketFalseStartTest, NoSessionResumptionBeforeFinish) { | |
| 2530 // Start a server. | |
| 2531 SpawnedTestServer::SSLOptions server_options; | |
| 2532 server_options.key_exchanges = | |
| 2533 SpawnedTestServer::SSLOptions::KEY_EXCHANGE_DHE_RSA; | |
| 2534 server_options.enable_npn = true; | |
| 2535 ASSERT_TRUE(StartTestServer(server_options)); | |
| 2536 | |
| 2537 SSLConfig client_config; | |
| 2538 client_config.next_protos.push_back("http/1.1"); | |
| 2539 | |
| 2540 // Start a handshake up to the server Finished message. | |
| 2541 TestCompletionCallback callback; | |
| 2542 FakeBlockingStreamSocket* raw_transport1; | |
| 2543 scoped_ptr<SSLClientSocket> sock1; | |
| 2544 CreateAndConnectUpToServerFinished( | |
| 2545 client_config, &callback, &raw_transport1, &sock1); | |
| 2546 // The handshake should False Start. | |
| 2547 EXPECT_EQ(OK, callback.GetResult(ERR_IO_PENDING)); | |
|
Ryan Sleevi
2014/05/31 00:46:11
ditto WaitForResult()
However, it's unclear to me
davidben
2014/06/02 18:45:38
Done. Also added a comment.
| |
| 2548 | |
| 2549 // Drop the old socket. This is needed because the Python test server can't | |
| 2550 // service two sockets in parallel. | |
| 2551 sock1.reset(); | |
| 2552 | |
| 2553 // Before the first connection receives ServerFinished, start a second | |
| 2554 // connection. | |
| 2555 scoped_ptr<StreamSocket> transport2( | |
| 2556 new TCPClientSocket(addr_, &log_, NetLog::Source())); | |
| 2557 EXPECT_EQ(OK, callback.GetResult(transport2->Connect(callback.callback()))); | |
| 2558 scoped_ptr<SSLClientSocket> sock2 = CreateSSLClientSocket( | |
| 2559 transport2.Pass(), test_server_->host_port_pair(), client_config); | |
| 2560 EXPECT_EQ(OK, callback.GetResult(sock2->Connect(callback.callback()))); | |
| 2561 | |
| 2562 // No session resumption. | |
| 2563 SSLInfo ssl_info; | |
| 2564 EXPECT_TRUE(sock2->GetSSLInfo(&ssl_info)); | |
| 2565 EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, ssl_info.handshake_type); | |
| 2566 } | |
| 2567 | |
| 2485 // Connect to a server using channel id. It should allow the connection. | 2568 // Connect to a server using channel id. It should allow the connection. |
| 2486 TEST_F(SSLClientSocketChannelIDTest, SendChannelID) { | 2569 TEST_F(SSLClientSocketChannelIDTest, SendChannelID) { |
| 2487 SpawnedTestServer::SSLOptions ssl_options; | 2570 SpawnedTestServer::SSLOptions ssl_options; |
| 2488 | 2571 |
| 2489 ASSERT_TRUE(ConnectToTestServer(ssl_options)); | 2572 ASSERT_TRUE(ConnectToTestServer(ssl_options)); |
| 2490 | 2573 |
| 2491 EnableChannelID(); | 2574 EnableChannelID(); |
| 2492 SSLConfig ssl_config = kDefaultSSLConfig; | 2575 SSLConfig ssl_config = kDefaultSSLConfig; |
| 2493 ssl_config.channel_id_enabled = true; | 2576 ssl_config.channel_id_enabled = true; |
| 2494 | 2577 |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 2519 | 2602 |
| 2520 // TODO(haavardm@opera.com): Due to differences in threading, Linux returns | 2603 // TODO(haavardm@opera.com): Due to differences in threading, Linux returns |
| 2521 // ERR_UNEXPECTED while Mac and Windows return ERR_PROTOCOL_ERROR. Accept all | 2604 // ERR_UNEXPECTED while Mac and Windows return ERR_PROTOCOL_ERROR. Accept all |
| 2522 // error codes for now. | 2605 // error codes for now. |
| 2523 // http://crbug.com/373670 | 2606 // http://crbug.com/373670 |
| 2524 EXPECT_NE(OK, rv); | 2607 EXPECT_NE(OK, rv); |
| 2525 EXPECT_FALSE(sock_->IsConnected()); | 2608 EXPECT_FALSE(sock_->IsConnected()); |
| 2526 } | 2609 } |
| 2527 | 2610 |
| 2528 } // namespace net | 2611 } // namespace net |
| OLD | NEW |