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

Unified Diff: net/socket/ssl_client_socket_openssl_unittest.cc

Issue 353713005: Implements new, more robust design for communicating between SSLConnectJobs. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Updated SSLClientSocket tests & fixed bug in SSLSessionCacheOpenSSL Created 6 years, 5 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
Index: net/socket/ssl_client_socket_openssl_unittest.cc
diff --git a/net/socket/ssl_client_socket_openssl_unittest.cc b/net/socket/ssl_client_socket_openssl_unittest.cc
index 00cf9f35cb4b612841207513f112780a405880df..1dfc48a24646d11d9c597c5b4dd5429feda6cab9 100644
--- a/net/socket/ssl_client_socket_openssl_unittest.cc
+++ b/net/socket/ssl_client_socket_openssl_unittest.cc
@@ -18,6 +18,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_handle.h"
#include "base/message_loop/message_loop_proxy.h"
+#include "base/run_loop.h"
wtc 2014/07/31 02:02:24 Do we need to include this?
#include "base/values.h"
#include "crypto/openssl_util.h"
#include "net/base/address_list.h"
@@ -38,6 +39,7 @@
#include "net/ssl/openssl_client_key_store.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "net/ssl/ssl_config_service.h"
+#include "net/socket/ssl_client_socket_test_util.cc"
wtc 2014/07/31 02:02:24 Delete this line. Note that you are including a .c
#include "net/test/cert_test_util.h"
#include "net/test/spawned_test_server/spawned_test_server.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -98,7 +100,8 @@ class SSLClientSocketOpenSSLClientAuthTest : public PlatformTest {
SSLClientSocketOpenSSLClientAuthTest()
: socket_factory_(net::ClientSocketFactory::GetDefaultFactory()),
cert_verifier_(new net::MockCertVerifier),
- transport_security_state_(new net::TransportSecurityState) {
+ transport_security_state_(new net::TransportSecurityState),
+ ran_handshake_completion_callback_(false) {
cert_verifier_->set_default_result(net::OK);
context_.cert_verifier = cert_verifier_.get();
context_.transport_security_state = transport_security_state_.get();
@@ -109,6 +112,11 @@ class SSLClientSocketOpenSSLClientAuthTest : public PlatformTest {
key_store_->Flush();
}
+ void RecordCompletedHandshake() {
+ ran_handshake_completion_callback_ = true;
+ printf("%s\n", "hi");
wtc 2014/07/31 02:02:24 Delete this debug printf statement. (By the way,
+ }
+
protected:
scoped_ptr<SSLClientSocket> CreateSSLClientSocket(
scoped_ptr<StreamSocket> transport_socket,
@@ -173,6 +181,10 @@ class SSLClientSocketOpenSSLClientAuthTest : public PlatformTest {
test_server_->host_port_pair(),
ssl_config);
+ sock_->SetHandshakeCompletionCallback(base::Bind(
+ &SSLClientSocketOpenSSLClientAuthTest::RecordCompletedHandshake,
+ base::Unretained(this)));
+
if (sock_->IsConnected()) {
LOG(ERROR) << "SSL Socket prematurely connected";
return false;
@@ -202,6 +214,7 @@ class SSLClientSocketOpenSSLClientAuthTest : public PlatformTest {
CapturingNetLog log_;
scoped_ptr<StreamSocket> transport_;
scoped_ptr<SSLClientSocket> sock_;
+ bool ran_handshake_completion_callback_;
};
// Connect to a server requesting client authentication, do not send
@@ -220,6 +233,7 @@ TEST_F(SSLClientSocketOpenSSLClientAuthTest, NoCert) {
EXPECT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
EXPECT_FALSE(sock_->IsConnected());
+ EXPECT_TRUE(ran_handshake_completion_callback_);
}
// Connect to a server requesting client authentication, and send it
@@ -277,7 +291,175 @@ TEST_F(SSLClientSocketOpenSSLClientAuthTest, SendGoodCert) {
sock_->Disconnect();
EXPECT_FALSE(sock_->IsConnected());
}
+
+TEST_F(SSLClientSocketOpenSSLClientAuthTest,
+ CompletionCallbackIsRun_WithFailure) {
+ SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS,
+ SpawnedTestServer::kLocalhost,
+ base::FilePath());
+ ASSERT_TRUE(test_server.Start());
+
+ AddressList addr;
+ ASSERT_TRUE(test_server.GetAddressList(&addr));
+
+ TestCompletionCallback callback;
+ scoped_ptr<StreamSocket> real_transport(
+ new TCPClientSocket(addr, NULL, NetLog::Source()));
+ scoped_ptr<SynchronousErrorStreamSocket> transport(
+ new SynchronousErrorStreamSocket(real_transport.Pass()));
+ int rv = callback.GetResult(transport->Connect(callback.callback()));
+ EXPECT_EQ(OK, rv);
+
+ // Disable TLS False Start to avoid handshake non-determinism.
+ SSLConfig ssl_config;
+ ssl_config.false_start_enabled = false;
+
+ SynchronousErrorStreamSocket* raw_transport = transport.get();
+ scoped_ptr<SSLClientSocket> sock(
+ CreateSSLClientSocket(transport.PassAs<StreamSocket>(),
+ test_server.host_port_pair(),
+ ssl_config));
+
+ sock->SetHandshakeCompletionCallback(base::Bind(
+ &SSLClientSocketOpenSSLClientAuthTest::RecordCompletedHandshake,
+ base::Unretained(this)));
+
+ rv = callback.GetResult(sock->Connect(callback.callback()));
+ EXPECT_EQ(OK, rv);
+ EXPECT_TRUE(sock->IsConnected());
+
+ const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
+ static const int kRequestTextSize =
+ static_cast<int>(arraysize(request_text) - 1);
+ scoped_refptr<IOBuffer> request_buffer(new IOBuffer(kRequestTextSize));
+ memcpy(request_buffer->data(), request_text, kRequestTextSize);
+
+ rv = callback.GetResult(
+ sock->Write(request_buffer.get(), kRequestTextSize, callback.callback()));
+ EXPECT_EQ(kRequestTextSize, rv);
+
+ // Simulate an unclean/forcible shutdown.
+ raw_transport->SetNextReadError(ERR_CONNECTION_RESET);
+
+ scoped_refptr<IOBuffer> buf(new IOBuffer(4096));
+
+ // Note: This test will hang if this bug has regressed. Simply checking that
+ // rv != ERR_IO_PENDING is insufficient, as ERR_IO_PENDING is a legitimate
+ // result when using a dedicated task runner for NSS.
+ rv = callback.GetResult(sock->Read(buf.get(), 4096, callback.callback()));
+
+ EXPECT_TRUE(ran_handshake_completion_callback_);
+}
+
+TEST_F(SSLClientSocketOpenSSLClientAuthTest,
+ CompletionCallbackIsRun_WithFalseStartFailure) {
+ SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS,
+ SpawnedTestServer::kLocalhost,
+ base::FilePath());
+ ASSERT_TRUE(test_server.Start());
+
+ AddressList addr;
+ ASSERT_TRUE(test_server.GetAddressList(&addr));
+
+ TestCompletionCallback callback;
+ scoped_ptr<StreamSocket> real_transport(
+ new TCPClientSocket(addr, NULL, NetLog::Source()));
+ // Note: |error_socket|'s ownership is handed to |transport|, but a pointer
+ // is retained in order to configure additional errors.
+ scoped_ptr<SynchronousErrorStreamSocket> error_socket(
+ new SynchronousErrorStreamSocket(real_transport.Pass()));
+ SynchronousErrorStreamSocket* raw_error_socket = error_socket.get();
+ scoped_ptr<FakeBlockingStreamSocket> transport(
+ new FakeBlockingStreamSocket(error_socket.PassAs<StreamSocket>()));
+ FakeBlockingStreamSocket* raw_transport = transport.get();
+ int rv = callback.GetResult(transport->Connect(callback.callback()));
+ EXPECT_EQ(OK, rv);
+
+ SSLConfig ssl_config;
+ ssl_config.false_start_enabled = true;
+
+ scoped_ptr<SSLClientSocket> sock(
+ CreateSSLClientSocket(transport.PassAs<StreamSocket>(),
+ test_server.host_port_pair(),
+ ssl_config));
+
+ sock->SetHandshakeCompletionCallback(base::Bind(
+ &SSLClientSocketOpenSSLClientAuthTest::RecordCompletedHandshake,
+ base::Unretained(this)));
+
+ rv = callback.GetResult(sock->Connect(callback.callback()));
+ EXPECT_EQ(OK, rv);
+ EXPECT_TRUE(sock->IsConnected());
+
+ const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
+ static const int kRequestTextSize =
+ static_cast<int>(arraysize(request_text) - 1);
+ scoped_refptr<IOBuffer> request_buffer(new IOBuffer(kRequestTextSize));
+ memcpy(request_buffer->data(), request_text, kRequestTextSize);
+
+ // Simulate an unclean/forcible shutdown on the underlying socket.
+ // However, simulate this error asynchronously.
+ raw_error_socket->SetNextWriteError(ERR_CONNECTION_RESET);
+ raw_transport->BlockWrite();
+
+ // This write should complete synchronously, because the TLS ciphertext
+ // can be created and placed into the outgoing buffers independent of the
+ // underlying transport.
+ rv = callback.GetResult(
+ sock->Write(request_buffer.get(), kRequestTextSize, callback.callback()));
+ EXPECT_EQ(kRequestTextSize, rv);
+
+ scoped_refptr<IOBuffer> buf(new IOBuffer(4096));
+
+ rv = sock->Read(buf.get(), 4096, callback.callback());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ // Now unblock the outgoing request, having it fail with the connection
+ // being reset.
+ raw_transport->UnblockWrite();
+
+ // Note: This will cause an inifite loop if this bug has regressed. Simply
+ // checking that rv != ERR_IO_PENDING is insufficient, as ERR_IO_PENDING
+ // is a legitimate result when using a dedicated task runner for NSS.
+ rv = callback.GetResult(rv);
+
+ EXPECT_TRUE(ran_handshake_completion_callback_);
+}
+
+// Connect to a server requesting client authentication. Send it a
+// matching certificate. It should allow the connection.
+TEST_F(SSLClientSocketOpenSSLClientAuthTest,
+ CompletionCallbackIsRun_WithSuccess) {
+ SpawnedTestServer::SSLOptions ssl_options;
+ ssl_options.request_client_certificate = true;
+ ssl_options.client_authorities.push_back(
+ GetTestClientCertsDirectory().AppendASCII("client_1_ca.pem"));
+
+ ASSERT_TRUE(ConnectToTestServer(ssl_options));
+
+ base::FilePath certs_dir = GetTestCertsDirectory();
+ SSLConfig ssl_config = kDefaultSSLConfig;
+ ssl_config.send_client_cert = true;
+ ssl_config.client_cert = ImportCertFromFile(certs_dir, "client_1.pem");
+
+ // This is required to ensure that signing works with the client
+ // certificate's private key.
+ OpenSSLClientKeyStore::ScopedEVP_PKEY client_private_key;
+ ASSERT_TRUE(LoadPrivateKeyOpenSSL(certs_dir.AppendASCII("client_1.key"),
+ &client_private_key));
+ EXPECT_TRUE(RecordPrivateKey(ssl_config, client_private_key.get()));
+
+ int rv;
+ ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv));
+ EXPECT_EQ(OK, rv);
+
+ EXPECT_TRUE(sock_->IsConnected());
+
+ EXPECT_TRUE(ran_handshake_completion_callback_);
+}
+
#endif // defined(USE_OPENSSL_CERTS)
} // namespace
+
} // namespace net

Powered by Google App Engine
This is Rietveld 408576698