Home | History | Annotate | Download | only in base
      1 /*
      2  *  Copyright 2014 The WebRTC Project Authors. All rights reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include <string>
     12 
     13 #include "webrtc/base/gunit.h"
     14 #include "webrtc/base/ipaddress.h"
     15 #include "webrtc/base/socketstream.h"
     16 #include "webrtc/base/ssladapter.h"
     17 #include "webrtc/base/sslstreamadapter.h"
     18 #include "webrtc/base/stream.h"
     19 #include "webrtc/base/virtualsocketserver.h"
     20 
     21 static const int kTimeout = 5000;
     22 
     23 static rtc::AsyncSocket* CreateSocket(const rtc::SSLMode& ssl_mode) {
     24   rtc::SocketAddress address(rtc::IPAddress(INADDR_ANY), 0);
     25 
     26   rtc::AsyncSocket* socket = rtc::Thread::Current()->
     27       socketserver()->CreateAsyncSocket(
     28       address.family(), (ssl_mode == rtc::SSL_MODE_DTLS) ?
     29       SOCK_DGRAM : SOCK_STREAM);
     30   socket->Bind(address);
     31 
     32   return socket;
     33 }
     34 
     35 static std::string GetSSLProtocolName(const rtc::SSLMode& ssl_mode) {
     36   return (ssl_mode == rtc::SSL_MODE_DTLS) ? "DTLS" : "TLS";
     37 }
     38 
     39 class SSLAdapterTestDummyClient : public sigslot::has_slots<> {
     40  public:
     41   explicit SSLAdapterTestDummyClient(const rtc::SSLMode& ssl_mode)
     42       : ssl_mode_(ssl_mode) {
     43     rtc::AsyncSocket* socket = CreateSocket(ssl_mode_);
     44 
     45     ssl_adapter_.reset(rtc::SSLAdapter::Create(socket));
     46 
     47     // Ignore any certificate errors for the purpose of testing.
     48     // Note: We do this only because we don't have a real certificate.
     49     // NEVER USE THIS IN PRODUCTION CODE!
     50     ssl_adapter_->set_ignore_bad_cert(true);
     51 
     52     ssl_adapter_->SignalReadEvent.connect(this,
     53         &SSLAdapterTestDummyClient::OnSSLAdapterReadEvent);
     54     ssl_adapter_->SignalCloseEvent.connect(this,
     55         &SSLAdapterTestDummyClient::OnSSLAdapterCloseEvent);
     56   }
     57 
     58   rtc::AsyncSocket::ConnState GetState() const {
     59     return ssl_adapter_->GetState();
     60   }
     61 
     62   const std::string& GetReceivedData() const {
     63     return data_;
     64   }
     65 
     66   int Connect(const std::string& hostname, const rtc::SocketAddress& address) {
     67     LOG(LS_INFO) << "Starting " << GetSSLProtocolName(ssl_mode_)
     68         << " handshake with " << hostname;
     69 
     70     if (ssl_adapter_->StartSSL(hostname.c_str(), false) != 0) {
     71       return -1;
     72     }
     73 
     74     LOG(LS_INFO) << "Initiating connection with " << address;
     75 
     76     return ssl_adapter_->Connect(address);
     77   }
     78 
     79   int Close() {
     80     return ssl_adapter_->Close();
     81   }
     82 
     83   int Send(const std::string& message) {
     84     LOG(LS_INFO) << "Client sending '" << message << "'";
     85 
     86     return ssl_adapter_->Send(message.data(), message.length());
     87   }
     88 
     89   void OnSSLAdapterReadEvent(rtc::AsyncSocket* socket) {
     90     char buffer[4096] = "";
     91 
     92     // Read data received from the server and store it in our internal buffer.
     93     int read = socket->Recv(buffer, sizeof(buffer) - 1);
     94     if (read != -1) {
     95       buffer[read] = '\0';
     96 
     97       LOG(LS_INFO) << "Client received '" << buffer << "'";
     98 
     99       data_ += buffer;
    100     }
    101   }
    102 
    103   void OnSSLAdapterCloseEvent(rtc::AsyncSocket* socket, int error) {
    104     // OpenSSLAdapter signals handshake failure with a close event, but without
    105     // closing the socket! Let's close the socket here. This way GetState() can
    106     // return CS_CLOSED after failure.
    107     if (socket->GetState() != rtc::AsyncSocket::CS_CLOSED) {
    108       socket->Close();
    109     }
    110   }
    111 
    112  private:
    113   const rtc::SSLMode ssl_mode_;
    114 
    115   rtc::scoped_ptr<rtc::SSLAdapter> ssl_adapter_;
    116 
    117   std::string data_;
    118 };
    119 
    120 class SSLAdapterTestDummyServer : public sigslot::has_slots<> {
    121  public:
    122   explicit SSLAdapterTestDummyServer(const rtc::SSLMode& ssl_mode)
    123       : ssl_mode_(ssl_mode) {
    124     // Generate a key pair and a certificate for this host.
    125     ssl_identity_.reset(rtc::SSLIdentity::Generate(GetHostname()));
    126 
    127     server_socket_.reset(CreateSocket(ssl_mode_));
    128 
    129     server_socket_->SignalReadEvent.connect(this,
    130         &SSLAdapterTestDummyServer::OnServerSocketReadEvent);
    131 
    132     server_socket_->Listen(1);
    133 
    134     LOG(LS_INFO) << ((ssl_mode_ == rtc::SSL_MODE_DTLS) ? "UDP" : "TCP")
    135         << " server listening on " << server_socket_->GetLocalAddress();
    136   }
    137 
    138   rtc::SocketAddress GetAddress() const {
    139     return server_socket_->GetLocalAddress();
    140   }
    141 
    142   std::string GetHostname() const {
    143     // Since we don't have a real certificate anyway, the value here doesn't
    144     // really matter.
    145     return "example.com";
    146   }
    147 
    148   const std::string& GetReceivedData() const {
    149     return data_;
    150   }
    151 
    152   int Send(const std::string& message) {
    153     if (ssl_stream_adapter_ == NULL
    154         || ssl_stream_adapter_->GetState() != rtc::SS_OPEN) {
    155       // No connection yet.
    156       return -1;
    157     }
    158 
    159     LOG(LS_INFO) << "Server sending '" << message << "'";
    160 
    161     size_t written;
    162     int error;
    163 
    164     rtc::StreamResult r = ssl_stream_adapter_->Write(message.data(),
    165         message.length(), &written, &error);
    166     if (r == rtc::SR_SUCCESS) {
    167       return written;
    168     } else {
    169       return -1;
    170     }
    171   }
    172 
    173   void OnServerSocketReadEvent(rtc::AsyncSocket* socket) {
    174     if (ssl_stream_adapter_ != NULL) {
    175       // Only a single connection is supported.
    176       return;
    177     }
    178 
    179     rtc::SocketAddress address;
    180     rtc::AsyncSocket* new_socket = socket->Accept(&address);
    181     rtc::SocketStream* stream = new rtc::SocketStream(new_socket);
    182 
    183     ssl_stream_adapter_.reset(rtc::SSLStreamAdapter::Create(stream));
    184     ssl_stream_adapter_->SetServerRole();
    185 
    186     // SSLStreamAdapter is normally used for peer-to-peer communication, but
    187     // here we're testing communication between a client and a server
    188     // (e.g. a WebRTC-based application and an RFC 5766 TURN server), where
    189     // clients are not required to provide a certificate during handshake.
    190     // Accordingly, we must disable client authentication here.
    191     ssl_stream_adapter_->set_client_auth_enabled(false);
    192 
    193     ssl_stream_adapter_->SetIdentity(ssl_identity_->GetReference());
    194 
    195     // Set a bogus peer certificate digest.
    196     unsigned char digest[20];
    197     size_t digest_len = sizeof(digest);
    198     ssl_stream_adapter_->SetPeerCertificateDigest(rtc::DIGEST_SHA_1, digest,
    199         digest_len);
    200 
    201     ssl_stream_adapter_->StartSSLWithPeer();
    202 
    203     ssl_stream_adapter_->SignalEvent.connect(this,
    204         &SSLAdapterTestDummyServer::OnSSLStreamAdapterEvent);
    205   }
    206 
    207   void OnSSLStreamAdapterEvent(rtc::StreamInterface* stream, int sig, int err) {
    208     if (sig & rtc::SE_READ) {
    209       char buffer[4096] = "";
    210 
    211       size_t read;
    212       int error;
    213 
    214       // Read data received from the client and store it in our internal
    215       // buffer.
    216       rtc::StreamResult r = stream->Read(buffer,
    217           sizeof(buffer) - 1, &read, &error);
    218       if (r == rtc::SR_SUCCESS) {
    219         buffer[read] = '\0';
    220 
    221         LOG(LS_INFO) << "Server received '" << buffer << "'";
    222 
    223         data_ += buffer;
    224       }
    225     }
    226   }
    227 
    228  private:
    229   const rtc::SSLMode ssl_mode_;
    230 
    231   rtc::scoped_ptr<rtc::AsyncSocket> server_socket_;
    232   rtc::scoped_ptr<rtc::SSLStreamAdapter> ssl_stream_adapter_;
    233 
    234   rtc::scoped_ptr<rtc::SSLIdentity> ssl_identity_;
    235 
    236   std::string data_;
    237 };
    238 
    239 class SSLAdapterTestBase : public testing::Test,
    240                            public sigslot::has_slots<> {
    241  public:
    242   explicit SSLAdapterTestBase(const rtc::SSLMode& ssl_mode)
    243       : ssl_mode_(ssl_mode),
    244         ss_scope_(new rtc::VirtualSocketServer(NULL)),
    245         server_(new SSLAdapterTestDummyServer(ssl_mode_)),
    246         client_(new SSLAdapterTestDummyClient(ssl_mode_)),
    247         handshake_wait_(kTimeout) {
    248   }
    249 
    250   static void SetUpTestCase() {
    251     rtc::InitializeSSL();
    252   }
    253 
    254   static void TearDownTestCase() {
    255     rtc::CleanupSSL();
    256   }
    257 
    258   void SetHandshakeWait(int wait) {
    259     handshake_wait_ = wait;
    260   }
    261 
    262   void TestHandshake(bool expect_success) {
    263     int rv;
    264 
    265     // The initial state is CS_CLOSED
    266     ASSERT_EQ(rtc::AsyncSocket::CS_CLOSED, client_->GetState());
    267 
    268     rv = client_->Connect(server_->GetHostname(), server_->GetAddress());
    269     ASSERT_EQ(0, rv);
    270 
    271     // Now the state should be CS_CONNECTING
    272     ASSERT_EQ(rtc::AsyncSocket::CS_CONNECTING, client_->GetState());
    273 
    274     if (expect_success) {
    275       // If expecting success, the client should end up in the CS_CONNECTED
    276       // state after handshake.
    277       EXPECT_EQ_WAIT(rtc::AsyncSocket::CS_CONNECTED, client_->GetState(),
    278           handshake_wait_);
    279 
    280       LOG(LS_INFO) << GetSSLProtocolName(ssl_mode_) << " handshake complete.";
    281 
    282     } else {
    283       // On handshake failure the client should end up in the CS_CLOSED state.
    284       EXPECT_EQ_WAIT(rtc::AsyncSocket::CS_CLOSED, client_->GetState(),
    285           handshake_wait_);
    286 
    287       LOG(LS_INFO) << GetSSLProtocolName(ssl_mode_) << " handshake failed.";
    288     }
    289   }
    290 
    291   void TestTransfer(const std::string& message) {
    292     int rv;
    293 
    294     rv = client_->Send(message);
    295     ASSERT_EQ(static_cast<int>(message.length()), rv);
    296 
    297     // The server should have received the client's message.
    298     EXPECT_EQ_WAIT(message, server_->GetReceivedData(), kTimeout);
    299 
    300     rv = server_->Send(message);
    301     ASSERT_EQ(static_cast<int>(message.length()), rv);
    302 
    303     // The client should have received the server's message.
    304     EXPECT_EQ_WAIT(message, client_->GetReceivedData(), kTimeout);
    305 
    306     LOG(LS_INFO) << "Transfer complete.";
    307   }
    308 
    309  private:
    310   const rtc::SSLMode ssl_mode_;
    311 
    312   const rtc::SocketServerScope ss_scope_;
    313 
    314   rtc::scoped_ptr<SSLAdapterTestDummyServer> server_;
    315   rtc::scoped_ptr<SSLAdapterTestDummyClient> client_;
    316 
    317   int handshake_wait_;
    318 };
    319 
    320 class SSLAdapterTestTLS : public SSLAdapterTestBase {
    321  public:
    322   SSLAdapterTestTLS() : SSLAdapterTestBase(rtc::SSL_MODE_TLS) {}
    323 };
    324 
    325 
    326 #if SSL_USE_OPENSSL
    327 
    328 // Basic tests: TLS
    329 
    330 // Test that handshake works
    331 TEST_F(SSLAdapterTestTLS, TestTLSConnect) {
    332   TestHandshake(true);
    333 }
    334 
    335 // Test transfer between client and server
    336 TEST_F(SSLAdapterTestTLS, TestTLSTransfer) {
    337   TestHandshake(true);
    338   TestTransfer("Hello, world!");
    339 }
    340 
    341 #endif  // SSL_USE_OPENSSL
    342 
    343