| Index: webrtc/base/ssladapter_unittest.cc
|
| diff --git a/webrtc/base/ssladapter_unittest.cc b/webrtc/base/ssladapter_unittest.cc
|
| deleted file mode 100644
|
| index 0eaac17885ac40d2e54c89cf8618b9dd2d473263..0000000000000000000000000000000000000000
|
| --- a/webrtc/base/ssladapter_unittest.cc
|
| +++ /dev/null
|
| @@ -1,459 +0,0 @@
|
| -/*
|
| - * Copyright 2014 The WebRTC Project Authors. All rights reserved.
|
| - *
|
| - * Use of this source code is governed by a BSD-style license
|
| - * that can be found in the LICENSE file in the root of the source
|
| - * tree. An additional intellectual property rights grant can be found
|
| - * in the file PATENTS. All contributing project authors may
|
| - * be found in the AUTHORS file in the root of the source tree.
|
| - */
|
| -
|
| -#include <memory>
|
| -#include <string>
|
| -
|
| -#include "webrtc/base/gunit.h"
|
| -#include "webrtc/base/ipaddress.h"
|
| -#include "webrtc/base/socketstream.h"
|
| -#include "webrtc/base/ssladapter.h"
|
| -#include "webrtc/base/sslidentity.h"
|
| -#include "webrtc/base/sslstreamadapter.h"
|
| -#include "webrtc/base/stream.h"
|
| -#include "webrtc/base/stringencode.h"
|
| -#include "webrtc/base/virtualsocketserver.h"
|
| -
|
| -static const int kTimeout = 5000;
|
| -
|
| -static rtc::AsyncSocket* CreateSocket(const rtc::SSLMode& ssl_mode) {
|
| - rtc::SocketAddress address(rtc::IPAddress(INADDR_ANY), 0);
|
| -
|
| - rtc::AsyncSocket* socket = rtc::Thread::Current()->
|
| - socketserver()->CreateAsyncSocket(
|
| - address.family(), (ssl_mode == rtc::SSL_MODE_DTLS) ?
|
| - SOCK_DGRAM : SOCK_STREAM);
|
| - socket->Bind(address);
|
| -
|
| - return socket;
|
| -}
|
| -
|
| -static std::string GetSSLProtocolName(const rtc::SSLMode& ssl_mode) {
|
| - return (ssl_mode == rtc::SSL_MODE_DTLS) ? "DTLS" : "TLS";
|
| -}
|
| -
|
| -class SSLAdapterTestDummyClient : public sigslot::has_slots<> {
|
| - public:
|
| - explicit SSLAdapterTestDummyClient(const rtc::SSLMode& ssl_mode)
|
| - : ssl_mode_(ssl_mode) {
|
| - rtc::AsyncSocket* socket = CreateSocket(ssl_mode_);
|
| -
|
| - ssl_adapter_.reset(rtc::SSLAdapter::Create(socket));
|
| -
|
| - ssl_adapter_->SetMode(ssl_mode_);
|
| -
|
| - // Ignore any certificate errors for the purpose of testing.
|
| - // Note: We do this only because we don't have a real certificate.
|
| - // NEVER USE THIS IN PRODUCTION CODE!
|
| - ssl_adapter_->set_ignore_bad_cert(true);
|
| -
|
| - ssl_adapter_->SignalReadEvent.connect(this,
|
| - &SSLAdapterTestDummyClient::OnSSLAdapterReadEvent);
|
| - ssl_adapter_->SignalCloseEvent.connect(this,
|
| - &SSLAdapterTestDummyClient::OnSSLAdapterCloseEvent);
|
| - }
|
| -
|
| - rtc::SocketAddress GetAddress() const {
|
| - return ssl_adapter_->GetLocalAddress();
|
| - }
|
| -
|
| - rtc::AsyncSocket::ConnState GetState() const {
|
| - return ssl_adapter_->GetState();
|
| - }
|
| -
|
| - const std::string& GetReceivedData() const {
|
| - return data_;
|
| - }
|
| -
|
| - int Connect(const std::string& hostname, const rtc::SocketAddress& address) {
|
| - LOG(LS_INFO) << "Initiating connection with " << address;
|
| -
|
| - int rv = ssl_adapter_->Connect(address);
|
| -
|
| - if (rv == 0) {
|
| - LOG(LS_INFO) << "Starting " << GetSSLProtocolName(ssl_mode_)
|
| - << " handshake with " << hostname;
|
| -
|
| - if (ssl_adapter_->StartSSL(hostname.c_str(), false) != 0) {
|
| - return -1;
|
| - }
|
| - }
|
| -
|
| - return rv;
|
| - }
|
| -
|
| - int Close() {
|
| - return ssl_adapter_->Close();
|
| - }
|
| -
|
| - int Send(const std::string& message) {
|
| - LOG(LS_INFO) << "Client sending '" << message << "'";
|
| -
|
| - return ssl_adapter_->Send(message.data(), message.length());
|
| - }
|
| -
|
| - void OnSSLAdapterReadEvent(rtc::AsyncSocket* socket) {
|
| - char buffer[4096] = "";
|
| -
|
| - // Read data received from the server and store it in our internal buffer.
|
| - int read = socket->Recv(buffer, sizeof(buffer) - 1, nullptr);
|
| - if (read != -1) {
|
| - buffer[read] = '\0';
|
| -
|
| - LOG(LS_INFO) << "Client received '" << buffer << "'";
|
| -
|
| - data_ += buffer;
|
| - }
|
| - }
|
| -
|
| - void OnSSLAdapterCloseEvent(rtc::AsyncSocket* socket, int error) {
|
| - // OpenSSLAdapter signals handshake failure with a close event, but without
|
| - // closing the socket! Let's close the socket here. This way GetState() can
|
| - // return CS_CLOSED after failure.
|
| - if (socket->GetState() != rtc::AsyncSocket::CS_CLOSED) {
|
| - socket->Close();
|
| - }
|
| - }
|
| -
|
| - private:
|
| - const rtc::SSLMode ssl_mode_;
|
| -
|
| - std::unique_ptr<rtc::SSLAdapter> ssl_adapter_;
|
| -
|
| - std::string data_;
|
| -};
|
| -
|
| -class SSLAdapterTestDummyServer : public sigslot::has_slots<> {
|
| - public:
|
| - explicit SSLAdapterTestDummyServer(const rtc::SSLMode& ssl_mode,
|
| - const rtc::KeyParams& key_params)
|
| - : ssl_mode_(ssl_mode) {
|
| - // Generate a key pair and a certificate for this host.
|
| - ssl_identity_.reset(rtc::SSLIdentity::Generate(GetHostname(), key_params));
|
| -
|
| - server_socket_.reset(CreateSocket(ssl_mode_));
|
| -
|
| - if (ssl_mode_ == rtc::SSL_MODE_TLS) {
|
| - server_socket_->SignalReadEvent.connect(this,
|
| - &SSLAdapterTestDummyServer::OnServerSocketReadEvent);
|
| -
|
| - server_socket_->Listen(1);
|
| - }
|
| -
|
| - LOG(LS_INFO) << ((ssl_mode_ == rtc::SSL_MODE_DTLS) ? "UDP" : "TCP")
|
| - << " server listening on " << server_socket_->GetLocalAddress();
|
| - }
|
| -
|
| - rtc::SocketAddress GetAddress() const {
|
| - return server_socket_->GetLocalAddress();
|
| - }
|
| -
|
| - std::string GetHostname() const {
|
| - // Since we don't have a real certificate anyway, the value here doesn't
|
| - // really matter.
|
| - return "example.com";
|
| - }
|
| -
|
| - const std::string& GetReceivedData() const {
|
| - return data_;
|
| - }
|
| -
|
| - int Send(const std::string& message) {
|
| - if (ssl_stream_adapter_ == nullptr ||
|
| - ssl_stream_adapter_->GetState() != rtc::SS_OPEN) {
|
| - // No connection yet.
|
| - return -1;
|
| - }
|
| -
|
| - LOG(LS_INFO) << "Server sending '" << message << "'";
|
| -
|
| - size_t written;
|
| - int error;
|
| -
|
| - rtc::StreamResult r = ssl_stream_adapter_->Write(message.data(),
|
| - message.length(), &written, &error);
|
| - if (r == rtc::SR_SUCCESS) {
|
| - return written;
|
| - } else {
|
| - return -1;
|
| - }
|
| - }
|
| -
|
| - void AcceptConnection(const rtc::SocketAddress& address) {
|
| - // Only a single connection is supported.
|
| - ASSERT_TRUE(ssl_stream_adapter_ == nullptr);
|
| -
|
| - // This is only for DTLS.
|
| - ASSERT_EQ(rtc::SSL_MODE_DTLS, ssl_mode_);
|
| -
|
| - // Transfer ownership of the socket to the SSLStreamAdapter object.
|
| - rtc::AsyncSocket* socket = server_socket_.release();
|
| -
|
| - socket->Connect(address);
|
| -
|
| - DoHandshake(socket);
|
| - }
|
| -
|
| - void OnServerSocketReadEvent(rtc::AsyncSocket* socket) {
|
| - // Only a single connection is supported.
|
| - ASSERT_TRUE(ssl_stream_adapter_ == nullptr);
|
| -
|
| - DoHandshake(server_socket_->Accept(nullptr));
|
| - }
|
| -
|
| - void OnSSLStreamAdapterEvent(rtc::StreamInterface* stream, int sig, int err) {
|
| - if (sig & rtc::SE_READ) {
|
| - char buffer[4096] = "";
|
| - size_t read;
|
| - int error;
|
| -
|
| - // Read data received from the client and store it in our internal
|
| - // buffer.
|
| - rtc::StreamResult r =
|
| - stream->Read(buffer, sizeof(buffer) - 1, &read, &error);
|
| - if (r == rtc::SR_SUCCESS) {
|
| - buffer[read] = '\0';
|
| - LOG(LS_INFO) << "Server received '" << buffer << "'";
|
| - data_ += buffer;
|
| - }
|
| - }
|
| - }
|
| -
|
| - private:
|
| - void DoHandshake(rtc::AsyncSocket* socket) {
|
| - rtc::SocketStream* stream = new rtc::SocketStream(socket);
|
| -
|
| - ssl_stream_adapter_.reset(rtc::SSLStreamAdapter::Create(stream));
|
| -
|
| - ssl_stream_adapter_->SetMode(ssl_mode_);
|
| - ssl_stream_adapter_->SetServerRole();
|
| -
|
| - // SSLStreamAdapter is normally used for peer-to-peer communication, but
|
| - // here we're testing communication between a client and a server
|
| - // (e.g. a WebRTC-based application and an RFC 5766 TURN server), where
|
| - // clients are not required to provide a certificate during handshake.
|
| - // Accordingly, we must disable client authentication here.
|
| - ssl_stream_adapter_->set_client_auth_enabled(false);
|
| -
|
| - ssl_stream_adapter_->SetIdentity(ssl_identity_->GetReference());
|
| -
|
| - // Set a bogus peer certificate digest.
|
| - unsigned char digest[20];
|
| - size_t digest_len = sizeof(digest);
|
| - ssl_stream_adapter_->SetPeerCertificateDigest(rtc::DIGEST_SHA_1, digest,
|
| - digest_len);
|
| -
|
| - ssl_stream_adapter_->StartSSL();
|
| -
|
| - ssl_stream_adapter_->SignalEvent.connect(this,
|
| - &SSLAdapterTestDummyServer::OnSSLStreamAdapterEvent);
|
| - }
|
| -
|
| - const rtc::SSLMode ssl_mode_;
|
| -
|
| - std::unique_ptr<rtc::AsyncSocket> server_socket_;
|
| - std::unique_ptr<rtc::SSLStreamAdapter> ssl_stream_adapter_;
|
| -
|
| - std::unique_ptr<rtc::SSLIdentity> ssl_identity_;
|
| -
|
| - std::string data_;
|
| -};
|
| -
|
| -class SSLAdapterTestBase : public testing::Test,
|
| - public sigslot::has_slots<> {
|
| - public:
|
| - explicit SSLAdapterTestBase(const rtc::SSLMode& ssl_mode,
|
| - const rtc::KeyParams& key_params)
|
| - : ssl_mode_(ssl_mode),
|
| - vss_(new rtc::VirtualSocketServer()),
|
| - thread_(vss_.get()),
|
| - server_(new SSLAdapterTestDummyServer(ssl_mode_, key_params)),
|
| - client_(new SSLAdapterTestDummyClient(ssl_mode_)),
|
| - handshake_wait_(kTimeout) {}
|
| -
|
| - void SetHandshakeWait(int wait) {
|
| - handshake_wait_ = wait;
|
| - }
|
| -
|
| - void TestHandshake(bool expect_success) {
|
| - int rv;
|
| -
|
| - // The initial state is CS_CLOSED
|
| - ASSERT_EQ(rtc::AsyncSocket::CS_CLOSED, client_->GetState());
|
| -
|
| - rv = client_->Connect(server_->GetHostname(), server_->GetAddress());
|
| - ASSERT_EQ(0, rv);
|
| -
|
| - // Now the state should be CS_CONNECTING
|
| - ASSERT_EQ(rtc::AsyncSocket::CS_CONNECTING, client_->GetState());
|
| -
|
| - if (ssl_mode_ == rtc::SSL_MODE_DTLS) {
|
| - // For DTLS, call AcceptConnection() with the client's address.
|
| - server_->AcceptConnection(client_->GetAddress());
|
| - }
|
| -
|
| - if (expect_success) {
|
| - // If expecting success, the client should end up in the CS_CONNECTED
|
| - // state after handshake.
|
| - EXPECT_EQ_WAIT(rtc::AsyncSocket::CS_CONNECTED, client_->GetState(),
|
| - handshake_wait_);
|
| -
|
| - LOG(LS_INFO) << GetSSLProtocolName(ssl_mode_) << " handshake complete.";
|
| -
|
| - } else {
|
| - // On handshake failure the client should end up in the CS_CLOSED state.
|
| - EXPECT_EQ_WAIT(rtc::AsyncSocket::CS_CLOSED, client_->GetState(),
|
| - handshake_wait_);
|
| -
|
| - LOG(LS_INFO) << GetSSLProtocolName(ssl_mode_) << " handshake failed.";
|
| - }
|
| - }
|
| -
|
| - void TestTransfer(const std::string& message) {
|
| - int rv;
|
| -
|
| - rv = client_->Send(message);
|
| - ASSERT_EQ(static_cast<int>(message.length()), rv);
|
| -
|
| - // The server should have received the client's message.
|
| - EXPECT_EQ_WAIT(message, server_->GetReceivedData(), kTimeout);
|
| -
|
| - rv = server_->Send(message);
|
| - ASSERT_EQ(static_cast<int>(message.length()), rv);
|
| -
|
| - // The client should have received the server's message.
|
| - EXPECT_EQ_WAIT(message, client_->GetReceivedData(), kTimeout);
|
| -
|
| - LOG(LS_INFO) << "Transfer complete.";
|
| - }
|
| -
|
| - protected:
|
| - const rtc::SSLMode ssl_mode_;
|
| -
|
| - std::unique_ptr<rtc::VirtualSocketServer> vss_;
|
| - rtc::AutoSocketServerThread thread_;
|
| - std::unique_ptr<SSLAdapterTestDummyServer> server_;
|
| - std::unique_ptr<SSLAdapterTestDummyClient> client_;
|
| -
|
| - int handshake_wait_;
|
| -};
|
| -
|
| -class SSLAdapterTestTLS_RSA : public SSLAdapterTestBase {
|
| - public:
|
| - SSLAdapterTestTLS_RSA()
|
| - : SSLAdapterTestBase(rtc::SSL_MODE_TLS, rtc::KeyParams::RSA()) {}
|
| -};
|
| -
|
| -class SSLAdapterTestTLS_ECDSA : public SSLAdapterTestBase {
|
| - public:
|
| - SSLAdapterTestTLS_ECDSA()
|
| - : SSLAdapterTestBase(rtc::SSL_MODE_TLS, rtc::KeyParams::ECDSA()) {}
|
| -};
|
| -
|
| -class SSLAdapterTestDTLS_RSA : public SSLAdapterTestBase {
|
| - public:
|
| - SSLAdapterTestDTLS_RSA()
|
| - : SSLAdapterTestBase(rtc::SSL_MODE_DTLS, rtc::KeyParams::RSA()) {}
|
| -};
|
| -
|
| -class SSLAdapterTestDTLS_ECDSA : public SSLAdapterTestBase {
|
| - public:
|
| - SSLAdapterTestDTLS_ECDSA()
|
| - : SSLAdapterTestBase(rtc::SSL_MODE_DTLS, rtc::KeyParams::ECDSA()) {}
|
| -};
|
| -
|
| -// Basic tests: TLS
|
| -
|
| -// Test that handshake works, using RSA
|
| -TEST_F(SSLAdapterTestTLS_RSA, TestTLSConnect) {
|
| - TestHandshake(true);
|
| -}
|
| -
|
| -// Test that handshake works, using ECDSA
|
| -TEST_F(SSLAdapterTestTLS_ECDSA, TestTLSConnect) {
|
| - TestHandshake(true);
|
| -}
|
| -
|
| -// Test transfer between client and server, using RSA
|
| -TEST_F(SSLAdapterTestTLS_RSA, TestTLSTransfer) {
|
| - TestHandshake(true);
|
| - TestTransfer("Hello, world!");
|
| -}
|
| -
|
| -TEST_F(SSLAdapterTestTLS_RSA, TestTLSTransferWithBlockedSocket) {
|
| - TestHandshake(true);
|
| -
|
| - // Tell the underlying socket to simulate being blocked.
|
| - vss_->SetSendingBlocked(true);
|
| -
|
| - std::string expected;
|
| - int rv;
|
| - // Send messages until the SSL socket adapter starts applying backpressure.
|
| - // Note that this may not occur immediately since there may be some amount of
|
| - // intermediate buffering (either in our code or in BoringSSL).
|
| - for (int i = 0; i < 1024; ++i) {
|
| - std::string message = "Hello, world: " + rtc::ToString(i);
|
| - rv = client_->Send(message);
|
| - if (rv != static_cast<int>(message.size())) {
|
| - // This test assumes either the whole message or none of it is sent.
|
| - ASSERT_EQ(-1, rv);
|
| - break;
|
| - }
|
| - expected += message;
|
| - }
|
| - // Assert that the loop above exited due to Send returning -1.
|
| - ASSERT_EQ(-1, rv);
|
| -
|
| - // Try sending another message while blocked. -1 should be returned again and
|
| - // it shouldn't end up received by the server later.
|
| - EXPECT_EQ(-1, client_->Send("Never sent"));
|
| -
|
| - // Unblock the underlying socket. All of the buffered messages should be sent
|
| - // without any further action.
|
| - vss_->SetSendingBlocked(false);
|
| - EXPECT_EQ_WAIT(expected, server_->GetReceivedData(), kTimeout);
|
| -
|
| - // Send another message. This previously wasn't working
|
| - std::string final_message = "Fin.";
|
| - expected += final_message;
|
| - EXPECT_EQ(static_cast<int>(final_message.size()),
|
| - client_->Send(final_message));
|
| - EXPECT_EQ_WAIT(expected, server_->GetReceivedData(), kTimeout);
|
| -}
|
| -
|
| -// Test transfer between client and server, using ECDSA
|
| -TEST_F(SSLAdapterTestTLS_ECDSA, TestTLSTransfer) {
|
| - TestHandshake(true);
|
| - TestTransfer("Hello, world!");
|
| -}
|
| -
|
| -// Basic tests: DTLS
|
| -
|
| -// Test that handshake works, using RSA
|
| -TEST_F(SSLAdapterTestDTLS_RSA, TestDTLSConnect) {
|
| - TestHandshake(true);
|
| -}
|
| -
|
| -// Test that handshake works, using ECDSA
|
| -TEST_F(SSLAdapterTestDTLS_ECDSA, TestDTLSConnect) {
|
| - TestHandshake(true);
|
| -}
|
| -
|
| -// Test transfer between client and server, using RSA
|
| -TEST_F(SSLAdapterTestDTLS_RSA, TestDTLSTransfer) {
|
| - TestHandshake(true);
|
| - TestTransfer("Hello, world!");
|
| -}
|
| -
|
| -// Test transfer between client and server, using ECDSA
|
| -TEST_F(SSLAdapterTestDTLS_ECDSA, TestDTLSTransfer) {
|
| - TestHandshake(true);
|
| - TestTransfer("Hello, world!");
|
| -}
|
|
|