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