Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(31)

Unified Diff: net/socket/ssl_client_socket_unittest.cc

Issue 337773003: Reland r276815: Add tests for session cache and false start behavior. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | third_party/tlslite/README.chromium » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/socket/ssl_client_socket_unittest.cc
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc
index 2639870e81f36f4fefef5ad4626ced9bc629da13..7748f07106b2c73f1eeab10bd6ede8e832b5a5dd 100644
--- a/net/socket/ssl_client_socket_unittest.cc
+++ b/net/socket/ssl_client_socket_unittest.cc
@@ -599,9 +599,15 @@ class SSLClientSocketTest : public PlatformTest {
}
protected:
- // Sets up a TCP connection to a HTTPS server. To actually do the SSL
- // handshake, follow up with call to CreateAndConnectSSLClientSocket() below.
- bool ConnectToTestServer(SpawnedTestServer::SSLOptions& ssl_options) {
+ // The address of the spawned test server, after calling StartTestServer().
+ const AddressList& addr() const { return addr_; }
+
+ // The SpawnedTestServer object, after calling StartTestServer().
+ const SpawnedTestServer* test_server() const { return test_server_.get(); }
+
+ // Starts the test server with SSL configuration |ssl_options|. Returns true
+ // on success.
+ bool StartTestServer(const SpawnedTestServer::SSLOptions& ssl_options) {
test_server_.reset(new SpawnedTestServer(
SpawnedTestServer::TYPE_HTTPS, ssl_options, base::FilePath()));
if (!test_server_->Start()) {
@@ -613,6 +619,14 @@ class SSLClientSocketTest : public PlatformTest {
LOG(ERROR) << "Could not get SpawnedTestServer address list";
return false;
}
+ return true;
+ }
+
+ // Sets up a TCP connection to a HTTPS server. To actually do the SSL
+ // handshake, follow up with call to CreateAndConnectSSLClientSocket() below.
+ bool ConnectToTestServer(const SpawnedTestServer::SSLOptions& ssl_options) {
+ if (!StartTestServer(ssl_options))
+ return false;
transport_.reset(new TCPClientSocket(addr_, &log_, NetLog::Source()));
int rv = callback_.GetResult(transport_->Connect(callback_.callback()));
@@ -713,58 +727,82 @@ class SSLClientSocketCertRequestInfoTest : public SSLClientSocketTest {
class SSLClientSocketFalseStartTest : public SSLClientSocketTest {
protected:
- void TestFalseStart(const SpawnedTestServer::SSLOptions& server_options,
- const SSLConfig& client_config,
- bool expect_false_start) {
- SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS,
- server_options,
- base::FilePath());
- ASSERT_TRUE(test_server.Start());
-
- AddressList addr;
- ASSERT_TRUE(test_server.GetAddressList(&addr));
+ // Creates an SSLClientSocket with |client_config| attached to a
+ // FakeBlockingStreamSocket, returning both in |*out_raw_transport| and
+ // |*out_sock|. The FakeBlockingStreamSocket is owned by the SSLClientSocket,
+ // so |*out_raw_transport| is a raw pointer.
+ //
+ // The client socket will begin a connect using |callback| but stop before the
+ // server's finished message is received. The finished message will be blocked
+ // in |*out_raw_transport|. To complete the handshake and successfully read
+ // data, the caller must unblock reads on |*out_raw_transport|. (Note that, if
+ // the client successfully false started, |callback.WaitForResult()| will
+ // return OK without unblocking transport reads. But Read() will still block.)
+ //
+ // Must be called after StartTestServer is called.
+ void CreateAndConnectUntilServerFinishedReceived(
+ const SSLConfig& client_config,
+ TestCompletionCallback* callback,
+ FakeBlockingStreamSocket** out_raw_transport,
+ scoped_ptr<SSLClientSocket>* out_sock) {
+ CHECK(test_server());
- TestCompletionCallback callback;
scoped_ptr<StreamSocket> real_transport(
- new TCPClientSocket(addr, NULL, NetLog::Source()));
+ new TCPClientSocket(addr(), NULL, NetLog::Source()));
scoped_ptr<FakeBlockingStreamSocket> transport(
new FakeBlockingStreamSocket(real_transport.Pass()));
- int rv = callback.GetResult(transport->Connect(callback.callback()));
+ int rv = callback->GetResult(transport->Connect(callback->callback()));
EXPECT_EQ(OK, rv);
FakeBlockingStreamSocket* raw_transport = transport.get();
- scoped_ptr<SSLClientSocket> sock(
+ scoped_ptr<SSLClientSocket> sock =
CreateSSLClientSocket(transport.PassAs<StreamSocket>(),
- test_server.host_port_pair(),
- client_config));
+ test_server()->host_port_pair(),
+ client_config);
// Connect. Stop before the client processes the first server leg
// (ServerHello, etc.)
raw_transport->BlockReadResult();
- rv = sock->Connect(callback.callback());
+ rv = sock->Connect(callback->callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
raw_transport->WaitForReadResult();
// Release the ServerHello and wait for the client to write
// ClientKeyExchange, etc. (A proxy for waiting for the entirety of the
// server's leg to complete, since it may span multiple reads.)
- EXPECT_FALSE(callback.have_result());
+ EXPECT_FALSE(callback->have_result());
raw_transport->BlockWrite();
raw_transport->UnblockReadResult();
raw_transport->WaitForWrite();
// And, finally, release that and block the next server leg
- // (ChangeCipherSpec, Finished). Note: callback.have_result() may or may not
- // be true at this point depending on whether the SSL implementation waits
- // for the client second leg to clear the internal write buffer and hit the
- // network.
+ // (ChangeCipherSpec, Finished).
raw_transport->BlockReadResult();
raw_transport->UnblockWrite();
+ *out_raw_transport = raw_transport;
+ *out_sock = sock.Pass();
+ }
+
+ void TestFalseStart(const SpawnedTestServer::SSLOptions& server_options,
+ const SSLConfig& client_config,
+ bool expect_false_start) {
+ ASSERT_TRUE(StartTestServer(server_options));
+
+ TestCompletionCallback callback;
+ FakeBlockingStreamSocket* raw_transport = NULL;
+ scoped_ptr<SSLClientSocket> sock;
+ ASSERT_NO_FATAL_FAILURE(CreateAndConnectUntilServerFinishedReceived(
+ client_config, &callback, &raw_transport, &sock));
+
if (expect_false_start) {
// When False Starting, the handshake should complete before receiving the
// Change Cipher Spec and Finished messages.
- rv = callback.GetResult(rv);
+ //
+ // Note: callback.have_result() may not be true without waiting. The NSS
+ // state machine sometimes lives on a separate thread, so this thread may
+ // not yet have processed the signal that the handshake has completed.
+ int rv = callback.WaitForResult();
EXPECT_EQ(OK, rv);
EXPECT_TRUE(sock->IsConnected());
@@ -2458,7 +2496,8 @@ TEST_F(SSLClientSocketFalseStartTest, FalseStartEnabled) {
server_options.enable_npn = true;
SSLConfig client_config;
client_config.next_protos.push_back("http/1.1");
- TestFalseStart(server_options, client_config, true);
+ ASSERT_NO_FATAL_FAILURE(
+ TestFalseStart(server_options, client_config, true));
}
// Test that False Start is disabled without NPN.
@@ -2468,7 +2507,8 @@ TEST_F(SSLClientSocketFalseStartTest, NoNPN) {
SpawnedTestServer::SSLOptions::KEY_EXCHANGE_DHE_RSA;
SSLConfig client_config;
client_config.next_protos.clear();
- TestFalseStart(server_options, client_config, false);
+ ASSERT_NO_FATAL_FAILURE(
+ TestFalseStart(server_options, client_config, false));
}
// Test that False Start is disabled without a forward-secret cipher suite.
@@ -2479,7 +2519,80 @@ TEST_F(SSLClientSocketFalseStartTest, NoForwardSecrecy) {
server_options.enable_npn = true;
SSLConfig client_config;
client_config.next_protos.push_back("http/1.1");
- TestFalseStart(server_options, client_config, false);
+ ASSERT_NO_FATAL_FAILURE(
+ TestFalseStart(server_options, client_config, false));
+}
+
+// Test that sessions are resumable after receiving the server Finished message.
+TEST_F(SSLClientSocketFalseStartTest, SessionResumption) {
+ // Start a server.
+ SpawnedTestServer::SSLOptions server_options;
+ server_options.key_exchanges =
+ SpawnedTestServer::SSLOptions::KEY_EXCHANGE_DHE_RSA;
+ server_options.enable_npn = true;
+ SSLConfig client_config;
+ client_config.next_protos.push_back("http/1.1");
+
+ // Let a full handshake complete with False Start.
+ ASSERT_NO_FATAL_FAILURE(
+ TestFalseStart(server_options, client_config, true));
+
+ // Make a second connection.
+ TestCompletionCallback callback;
+ scoped_ptr<StreamSocket> transport2(
+ new TCPClientSocket(addr(), &log_, NetLog::Source()));
+ EXPECT_EQ(OK, callback.GetResult(transport2->Connect(callback.callback())));
+ scoped_ptr<SSLClientSocket> sock2 = CreateSSLClientSocket(
+ transport2.Pass(), test_server()->host_port_pair(), client_config);
+ ASSERT_TRUE(sock2.get());
+ EXPECT_EQ(OK, callback.GetResult(sock2->Connect(callback.callback())));
+
+ // It should resume the session.
+ SSLInfo ssl_info;
+ EXPECT_TRUE(sock2->GetSSLInfo(&ssl_info));
+ EXPECT_EQ(SSLInfo::HANDSHAKE_RESUME, ssl_info.handshake_type);
+}
+
+// Test that sessions are not resumable before receiving the server Finished
+// message.
+TEST_F(SSLClientSocketFalseStartTest, NoSessionResumptionBeforeFinish) {
+ // Start a server.
+ SpawnedTestServer::SSLOptions server_options;
+ server_options.key_exchanges =
+ SpawnedTestServer::SSLOptions::KEY_EXCHANGE_DHE_RSA;
+ server_options.enable_npn = true;
+ ASSERT_TRUE(StartTestServer(server_options));
+
+ SSLConfig client_config;
+ client_config.next_protos.push_back("http/1.1");
+
+ // Start a handshake up to the server Finished message.
+ TestCompletionCallback callback;
+ FakeBlockingStreamSocket* raw_transport1;
+ scoped_ptr<SSLClientSocket> sock1;
+ ASSERT_NO_FATAL_FAILURE(CreateAndConnectUntilServerFinishedReceived(
+ client_config, &callback, &raw_transport1, &sock1));
+ // Although raw_transport1 has the server Finished blocked, the handshake
+ // still completes.
+ EXPECT_EQ(OK, callback.WaitForResult());
+
+ // Drop the old socket. This is needed because the Python test server can't
+ // service two sockets in parallel.
+ sock1.reset();
+
+ // Start a second connection.
+ scoped_ptr<StreamSocket> transport2(
+ new TCPClientSocket(addr(), &log_, NetLog::Source()));
+ EXPECT_EQ(OK, callback.GetResult(transport2->Connect(callback.callback())));
+ scoped_ptr<SSLClientSocket> sock2 = CreateSSLClientSocket(
+ transport2.Pass(), test_server()->host_port_pair(), client_config);
+ EXPECT_EQ(OK, callback.GetResult(sock2->Connect(callback.callback())));
+
+ // No session resumption because the first connection never received a server
+ // Finished message.
+ SSLInfo ssl_info;
+ EXPECT_TRUE(sock2->GetSSLInfo(&ssl_info));
+ EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, ssl_info.handshake_type);
}
// Connect to a server using channel id. It should allow the connection.
« no previous file with comments | « no previous file | third_party/tlslite/README.chromium » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698