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

Unified Diff: net/socket/ssl_client_socket_tls_srp_unittest.cc

Issue 6804032: Add TLS-SRP (RFC 5054) support Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: remove "httpsv" scheme, minor NSS/OpenSSL changes Created 9 years, 8 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 | « net/socket/ssl_client_socket_nss.cc ('k') | net/socket/ssl_client_socket_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/socket/ssl_client_socket_tls_srp_unittest.cc
diff --git a/net/socket/ssl_client_socket_tls_srp_unittest.cc b/net/socket/ssl_client_socket_tls_srp_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..01e72137830d313ee438d05737157fc1d2eda33c
--- /dev/null
+++ b/net/socket/ssl_client_socket_tls_srp_unittest.cc
@@ -0,0 +1,312 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <arpa/inet.h>
+#include <netinet/tcp.h>
+#include <stdarg.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#include <sslt.h>
+
+#include <vector>
+#include <string>
+
+#include "base/eintr_wrapper.h"
+#include "base/base64.h"
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/path_service.h"
+#include "base/process_util.h"
+#include "base/string_util.h"
+#include "base/values.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_log.h"
+#include "net/base/net_log_unittest.h"
+#include "net/base/ssl_config_service.h"
+#include "net/base/test_completion_callback.h"
+#include "net/socket/client_socket_factory.h"
+#include "net/socket/ssl_client_socket.h"
+#include "net/socket/ssl_client_socket_nss.h"
+#include "net/socket/ssl_host_info.h"
+#include "net/socket/tcp_client_socket.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gtest/include/gtest/gtest-spi.h"
+#include "testing/platform_test.h"
+
+namespace net {
+
+// TestSSLHostInfo is an SSLHostInfo which stores a single state in memory and
+// pretends that certificate verification always succeeds.
+class TestSSLHostInfo : public SSLHostInfo {
+ public:
+ explicit TestSSLHostInfo(CertVerifier* cert_verifier)
+ : SSLHostInfo("example.com", kDefaultSSLConfig, cert_verifier) {
+ if (!saved_.empty())
+ Parse(saved_);
+ cert_verification_complete_ = true;
+ cert_verification_error_ = OK;
+ }
+
+ virtual void Start() {
+ }
+
+ virtual int WaitForDataReady(CompletionCallback*) { return OK; }
+
+ virtual void Persist() {
+ saved_ = Serialize();
+ }
+
+ static void Reset() {
+ saved_.clear();
+ }
+
+ private:
+ static SSLConfig kDefaultSSLConfig;
+ static std::string saved_;
+};
+
+std::string TestSSLHostInfo::saved_;
+
+SSLConfig TestSSLHostInfo::kDefaultSSLConfig;
+
+class SSLClientSocketTLSSRPTest : public PlatformTest {
+ public:
+ SSLClientSocketTLSSRPTest()
+ : child_(base::kNullProcessHandle),
+ socket_factory_(ClientSocketFactory::GetDefaultFactory()),
+ log_(CapturingNetLog::kUnbounded),
+ expected_exit_code_(0)
+ {
+ TestSSLHostInfo::Reset();
+ }
+
+ virtual void TearDown() {
+ if (child_ != base::kNullProcessHandle) {
+ int exit_code;
+ EXPECT_TRUE(base::WaitForExitCode(child_, &exit_code));
+ EXPECT_EQ(expected_exit_code_, exit_code);
+ }
+ }
+
+ protected:
+ void StartTLSSRPServer(const char* arg, ...) {
+ FilePath dir_exe;
+ PathService::Get(base::DIR_EXE, &dir_exe);
+ FilePath helper_binary = dir_exe.Append("openssl_helper");
+
+ std::vector<std::string> args;
+ args.push_back(helper_binary.value());
+
+ args.push_back("tls-srp");
+ args.push_back("--srpv-file");
+ args.push_back(GetDefaultSRPVFilePath());
+
+ // Additional arguments can override the --srpv-file set above.
+ va_list ap;
+ va_start(ap, arg);
+ while (arg) {
+ args.push_back(arg);
+ arg = va_arg(ap, const char*);
+ }
+ va_end(ap);
+
+ const int listener = socket(AF_INET, SOCK_STREAM, 0);
+ ASSERT_GE(listener, 0);
+ struct sockaddr_in sin;
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = PF_INET;
+ ASSERT_EQ(0, bind(listener, (struct sockaddr*) &sin, sizeof(sin)));
+ socklen_t socklen = sizeof(remote_);
+ ASSERT_EQ(0, getsockname(listener, (struct sockaddr*) &remote_, &socklen));
+ ASSERT_EQ(sizeof(remote_), socklen);
+ ASSERT_EQ(0, listen(listener, 1));
+
+ base::file_handle_mapping_vector mapping;
+ // The listening socket is installed as the child's fd 3.
+ mapping.push_back(std::make_pair(listener, 3));
+ base::LaunchApp(args, mapping, false /* don't wait */, &child_);
+ ASSERT_EQ(0, HANDLE_EINTR(close(listener)));
+ }
+
+ // GetDefaultSRPVFilePath returns the path to the default test SRPV file,
+ // ok.srpv
+ std::string GetDefaultSRPVFilePath() {
+ FilePath path;
+ PathService::Get(base::DIR_SOURCE_ROOT, &path);
+ path = path.Append("net");
+ path = path.Append("data");
+ path = path.Append("ssl");
+ path = path.Append("certificates");
+ path = path.Append("ok.srpv");
+ return path.value();
+ }
+
+ // LoadDefaultCert returns the DER encoded default certificate.
+ std::string LoadDefaultCert() {
+ FilePath path;
+ PathService::Get(base::DIR_SOURCE_ROOT, &path);
+ path = path.Append("net");
+ path = path.Append("data");
+ path = path.Append("ssl");
+ path = path.Append("certificates");
+ path = path.Append("ok_cert.pem");
+
+ std::string pem;
+ bool r = file_util::ReadFileToString(path, &pem);
+ CHECK(r) << "failed to read " << path.value();
+
+ static const char kStartMarker[] = "-----BEGIN CERTIFICATE-----\n";
+ static const char kEndMarker[] = "-----END CERTIFICATE-----\n";
+
+ std::string::size_type i = pem.find(kStartMarker);
+ std::string::size_type j = pem.find(kEndMarker);
+ CHECK(i != std::string::npos);
+ CHECK(j != std::string::npos);
+ CHECK_GT(j, i);
+ i += sizeof(kStartMarker) - 1;
+
+ std::string b64data = pem.substr(i, j - i);
+ ReplaceSubstringsAfterOffset(&b64data, 0 /* start offset */, "\n", "");
+
+ std::string der;
+ base::Base64Decode(b64data, &der);
+ return der;
+ }
+
+ void SetupSSLConfig() {
+ if (ssl_config_.allowed_bad_certs.size())
+ return;
+ const std::string der = LoadDefaultCert();
+ SSLConfig::CertAndStatus cert_and_status;
+ cert_and_status.cert =
+ X509Certificate::CreateFromBytes(der.data(), der.size());
+ cert_and_status.cert_status = ERR_CERT_AUTHORITY_INVALID;
+
+ ssl_config_.allowed_bad_certs.push_back(cert_and_status);
+ }
+
+ // PerformConnection makes an SSL connection to the openssl_helper binary and
+ // does a ping-pong test to check the the SSL socket is working correctly.
+ void PerformConnection(std::string username = "",
+ std::string password = "",
+ bool fail = false,
+ int expected_net_error = OK) {
+ client_ = socket(AF_INET, SOCK_STREAM, 0);
+ ASSERT_LE(0, client_);
+ ASSERT_EQ(
+ 0, connect(client_, (struct sockaddr*) &remote_, sizeof(remote_)));
+ int on = 1;
+ setsockopt(client_, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
+
+ SetupSSLConfig();
+ log_.Clear();
+
+ std::vector<uint8> localhost;
+ localhost.push_back(127);
+ localhost.push_back(0);
+ localhost.push_back(0);
+ localhost.push_back(1);
+ AddressList addr_list(localhost, 443, false);
+ TCPClientSocket* transport = new TCPClientSocket(
+ addr_list, &log_, NetLog::Source());
+
+ if (!username.empty()) {
+ ssl_config_.use_tls_auth = true;
+ ssl_config_.tls_username = username;
+ ssl_config_.tls_password = password;
+ ssl_config_.ssl3_enabled = false;
+ ssl_config_.tls1_enabled = true;
+ }
+
+ transport->AdoptSocket(client_);
+ scoped_ptr<SSLClientSocket> sock(
+ socket_factory_->CreateSSLClientSocket(
+ transport, HostPortPair("example.com", 443), ssl_config_,
+ new TestSSLHostInfo(&cert_verifier_), &cert_verifier_));
+
+ TestCompletionCallback callback;
+ int rv = sock->Connect(&callback);
+ if (rv != OK) {
+ ASSERT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_FALSE(sock->IsConnected());
+ rv = callback.WaitForResult();
+ EXPECT_EQ(expected_net_error, rv); // default expected_net_error is OK
+ return;
+ }
+ EXPECT_TRUE(sock->IsConnected());
+
+ static const char request_text[] = "whoami";
+ scoped_refptr<IOBuffer> request_buffer =
+ new IOBuffer(arraysize(request_text) - 1);
+ memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1);
+ rv = sock->Write(request_buffer, arraysize(request_text), &callback);
+ if (rv < 0) {
+ ASSERT_EQ(ERR_IO_PENDING, rv);
+ rv = callback.WaitForResult();
+ }
+ EXPECT_EQ(7, rv);
+
+ scoped_refptr<IOBuffer> reply_buffer = new IOBuffer(8);
+ rv = sock->Read(reply_buffer, 8, &callback);
+ if (rv < 0) {
+ ASSERT_EQ(ERR_IO_PENDING, rv);
+ rv = callback.WaitForResult();
+ }
+
+ std::string exp_response = (ssl_config_.use_tls_auth) ?
+ ssl_config_.tls_username : "not-using-tls-srp";
+
+ EXPECT_EQ((int)exp_response.size(), rv);
+ EXPECT_TRUE(memcmp(reply_buffer->data(), exp_response.data(),
+ exp_response.size()) == 0);
+
+ next_proto_status_ = sock->GetNextProto(&next_proto_);
+
+ sock->Disconnect();
+ }
+
+ base::ProcessHandle child_;
+ CertVerifier cert_verifier_;
+ ClientSocketFactory* const socket_factory_;
+ struct sockaddr_in remote_;
+ int client_;
+ SSLConfig ssl_config_;
+ CapturingNetLog log_;
+ SSLClientSocket::NextProtoStatus next_proto_status_;
+ std::string next_proto_;
+ int expected_exit_code_;
+};
+
+TEST_F(SSLClientSocketTLSSRPTest, NoCredentials) {
+ StartTLSSRPServer(NULL);
+ // Not a TLS-SRP connection.
+ PerformConnection("", "", true, ERR_SSL_UNKNOWN_PSK_IDENTITY_ALERT);
+ expected_exit_code_ = 1;
+}
+
+TEST_F(SSLClientSocketTLSSRPTest, GoodCredentials) {
+ StartTLSSRPServer(NULL);
+ PerformConnection("user", "secret");
+}
+
+// TODO(sqs): The current openssl_helper terminates the connection upon seeing
+// a username it doesn't know. It should instead either (1) make up (s,v) and
+// play along, or (2) send unknown_psk_identity. When it's fixed, the net error
+// below will need to change.
+TEST_F(SSLClientSocketTLSSRPTest, BadCredentials) {
+ StartTLSSRPServer(NULL);
+ PerformConnection("baduser", "secret", true,
+ ERR_SSL_UNKNOWN_PSK_IDENTITY_ALERT);
+ expected_exit_code_ = 1;
+}
+
+TEST_F(SSLClientSocketTLSSRPTest, GoodUsernameBadPassword) {
+ StartTLSSRPServer(NULL);
+ PerformConnection("user", "badsecret", true, ERR_SSL_BAD_RECORD_MAC_ALERT);
+ expected_exit_code_ = 1;
+}
+
+} // namespace net
« no previous file with comments | « net/socket/ssl_client_socket_nss.cc ('k') | net/socket/ssl_client_socket_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698