OLD | NEW |
| (Empty) |
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 <memory> | |
12 #include <string> | |
13 | |
14 #include "webrtc/base/gunit.h" | |
15 #include "webrtc/base/ipaddress.h" | |
16 #include "webrtc/base/socketstream.h" | |
17 #include "webrtc/base/ssladapter.h" | |
18 #include "webrtc/base/sslidentity.h" | |
19 #include "webrtc/base/sslstreamadapter.h" | |
20 #include "webrtc/base/stream.h" | |
21 #include "webrtc/base/stringencode.h" | |
22 #include "webrtc/base/virtualsocketserver.h" | |
23 | |
24 static const int kTimeout = 5000; | |
25 | |
26 static rtc::AsyncSocket* CreateSocket(const rtc::SSLMode& ssl_mode) { | |
27 rtc::SocketAddress address(rtc::IPAddress(INADDR_ANY), 0); | |
28 | |
29 rtc::AsyncSocket* socket = rtc::Thread::Current()-> | |
30 socketserver()->CreateAsyncSocket( | |
31 address.family(), (ssl_mode == rtc::SSL_MODE_DTLS) ? | |
32 SOCK_DGRAM : SOCK_STREAM); | |
33 socket->Bind(address); | |
34 | |
35 return socket; | |
36 } | |
37 | |
38 static std::string GetSSLProtocolName(const rtc::SSLMode& ssl_mode) { | |
39 return (ssl_mode == rtc::SSL_MODE_DTLS) ? "DTLS" : "TLS"; | |
40 } | |
41 | |
42 class SSLAdapterTestDummyClient : public sigslot::has_slots<> { | |
43 public: | |
44 explicit SSLAdapterTestDummyClient(const rtc::SSLMode& ssl_mode) | |
45 : ssl_mode_(ssl_mode) { | |
46 rtc::AsyncSocket* socket = CreateSocket(ssl_mode_); | |
47 | |
48 ssl_adapter_.reset(rtc::SSLAdapter::Create(socket)); | |
49 | |
50 ssl_adapter_->SetMode(ssl_mode_); | |
51 | |
52 // Ignore any certificate errors for the purpose of testing. | |
53 // Note: We do this only because we don't have a real certificate. | |
54 // NEVER USE THIS IN PRODUCTION CODE! | |
55 ssl_adapter_->set_ignore_bad_cert(true); | |
56 | |
57 ssl_adapter_->SignalReadEvent.connect(this, | |
58 &SSLAdapterTestDummyClient::OnSSLAdapterReadEvent); | |
59 ssl_adapter_->SignalCloseEvent.connect(this, | |
60 &SSLAdapterTestDummyClient::OnSSLAdapterCloseEvent); | |
61 } | |
62 | |
63 rtc::SocketAddress GetAddress() const { | |
64 return ssl_adapter_->GetLocalAddress(); | |
65 } | |
66 | |
67 rtc::AsyncSocket::ConnState GetState() const { | |
68 return ssl_adapter_->GetState(); | |
69 } | |
70 | |
71 const std::string& GetReceivedData() const { | |
72 return data_; | |
73 } | |
74 | |
75 int Connect(const std::string& hostname, const rtc::SocketAddress& address) { | |
76 LOG(LS_INFO) << "Initiating connection with " << address; | |
77 | |
78 int rv = ssl_adapter_->Connect(address); | |
79 | |
80 if (rv == 0) { | |
81 LOG(LS_INFO) << "Starting " << GetSSLProtocolName(ssl_mode_) | |
82 << " handshake with " << hostname; | |
83 | |
84 if (ssl_adapter_->StartSSL(hostname.c_str(), false) != 0) { | |
85 return -1; | |
86 } | |
87 } | |
88 | |
89 return rv; | |
90 } | |
91 | |
92 int Close() { | |
93 return ssl_adapter_->Close(); | |
94 } | |
95 | |
96 int Send(const std::string& message) { | |
97 LOG(LS_INFO) << "Client sending '" << message << "'"; | |
98 | |
99 return ssl_adapter_->Send(message.data(), message.length()); | |
100 } | |
101 | |
102 void OnSSLAdapterReadEvent(rtc::AsyncSocket* socket) { | |
103 char buffer[4096] = ""; | |
104 | |
105 // Read data received from the server and store it in our internal buffer. | |
106 int read = socket->Recv(buffer, sizeof(buffer) - 1, nullptr); | |
107 if (read != -1) { | |
108 buffer[read] = '\0'; | |
109 | |
110 LOG(LS_INFO) << "Client received '" << buffer << "'"; | |
111 | |
112 data_ += buffer; | |
113 } | |
114 } | |
115 | |
116 void OnSSLAdapterCloseEvent(rtc::AsyncSocket* socket, int error) { | |
117 // OpenSSLAdapter signals handshake failure with a close event, but without | |
118 // closing the socket! Let's close the socket here. This way GetState() can | |
119 // return CS_CLOSED after failure. | |
120 if (socket->GetState() != rtc::AsyncSocket::CS_CLOSED) { | |
121 socket->Close(); | |
122 } | |
123 } | |
124 | |
125 private: | |
126 const rtc::SSLMode ssl_mode_; | |
127 | |
128 std::unique_ptr<rtc::SSLAdapter> ssl_adapter_; | |
129 | |
130 std::string data_; | |
131 }; | |
132 | |
133 class SSLAdapterTestDummyServer : public sigslot::has_slots<> { | |
134 public: | |
135 explicit SSLAdapterTestDummyServer(const rtc::SSLMode& ssl_mode, | |
136 const rtc::KeyParams& key_params) | |
137 : ssl_mode_(ssl_mode) { | |
138 // Generate a key pair and a certificate for this host. | |
139 ssl_identity_.reset(rtc::SSLIdentity::Generate(GetHostname(), key_params)); | |
140 | |
141 server_socket_.reset(CreateSocket(ssl_mode_)); | |
142 | |
143 if (ssl_mode_ == rtc::SSL_MODE_TLS) { | |
144 server_socket_->SignalReadEvent.connect(this, | |
145 &SSLAdapterTestDummyServer::OnServerSocketReadEvent); | |
146 | |
147 server_socket_->Listen(1); | |
148 } | |
149 | |
150 LOG(LS_INFO) << ((ssl_mode_ == rtc::SSL_MODE_DTLS) ? "UDP" : "TCP") | |
151 << " server listening on " << server_socket_->GetLocalAddress(); | |
152 } | |
153 | |
154 rtc::SocketAddress GetAddress() const { | |
155 return server_socket_->GetLocalAddress(); | |
156 } | |
157 | |
158 std::string GetHostname() const { | |
159 // Since we don't have a real certificate anyway, the value here doesn't | |
160 // really matter. | |
161 return "example.com"; | |
162 } | |
163 | |
164 const std::string& GetReceivedData() const { | |
165 return data_; | |
166 } | |
167 | |
168 int Send(const std::string& message) { | |
169 if (ssl_stream_adapter_ == nullptr || | |
170 ssl_stream_adapter_->GetState() != rtc::SS_OPEN) { | |
171 // No connection yet. | |
172 return -1; | |
173 } | |
174 | |
175 LOG(LS_INFO) << "Server sending '" << message << "'"; | |
176 | |
177 size_t written; | |
178 int error; | |
179 | |
180 rtc::StreamResult r = ssl_stream_adapter_->Write(message.data(), | |
181 message.length(), &written, &error); | |
182 if (r == rtc::SR_SUCCESS) { | |
183 return written; | |
184 } else { | |
185 return -1; | |
186 } | |
187 } | |
188 | |
189 void AcceptConnection(const rtc::SocketAddress& address) { | |
190 // Only a single connection is supported. | |
191 ASSERT_TRUE(ssl_stream_adapter_ == nullptr); | |
192 | |
193 // This is only for DTLS. | |
194 ASSERT_EQ(rtc::SSL_MODE_DTLS, ssl_mode_); | |
195 | |
196 // Transfer ownership of the socket to the SSLStreamAdapter object. | |
197 rtc::AsyncSocket* socket = server_socket_.release(); | |
198 | |
199 socket->Connect(address); | |
200 | |
201 DoHandshake(socket); | |
202 } | |
203 | |
204 void OnServerSocketReadEvent(rtc::AsyncSocket* socket) { | |
205 // Only a single connection is supported. | |
206 ASSERT_TRUE(ssl_stream_adapter_ == nullptr); | |
207 | |
208 DoHandshake(server_socket_->Accept(nullptr)); | |
209 } | |
210 | |
211 void OnSSLStreamAdapterEvent(rtc::StreamInterface* stream, int sig, int err) { | |
212 if (sig & rtc::SE_READ) { | |
213 char buffer[4096] = ""; | |
214 size_t read; | |
215 int error; | |
216 | |
217 // Read data received from the client and store it in our internal | |
218 // buffer. | |
219 rtc::StreamResult r = | |
220 stream->Read(buffer, sizeof(buffer) - 1, &read, &error); | |
221 if (r == rtc::SR_SUCCESS) { | |
222 buffer[read] = '\0'; | |
223 LOG(LS_INFO) << "Server received '" << buffer << "'"; | |
224 data_ += buffer; | |
225 } | |
226 } | |
227 } | |
228 | |
229 private: | |
230 void DoHandshake(rtc::AsyncSocket* socket) { | |
231 rtc::SocketStream* stream = new rtc::SocketStream(socket); | |
232 | |
233 ssl_stream_adapter_.reset(rtc::SSLStreamAdapter::Create(stream)); | |
234 | |
235 ssl_stream_adapter_->SetMode(ssl_mode_); | |
236 ssl_stream_adapter_->SetServerRole(); | |
237 | |
238 // SSLStreamAdapter is normally used for peer-to-peer communication, but | |
239 // here we're testing communication between a client and a server | |
240 // (e.g. a WebRTC-based application and an RFC 5766 TURN server), where | |
241 // clients are not required to provide a certificate during handshake. | |
242 // Accordingly, we must disable client authentication here. | |
243 ssl_stream_adapter_->set_client_auth_enabled(false); | |
244 | |
245 ssl_stream_adapter_->SetIdentity(ssl_identity_->GetReference()); | |
246 | |
247 // Set a bogus peer certificate digest. | |
248 unsigned char digest[20]; | |
249 size_t digest_len = sizeof(digest); | |
250 ssl_stream_adapter_->SetPeerCertificateDigest(rtc::DIGEST_SHA_1, digest, | |
251 digest_len); | |
252 | |
253 ssl_stream_adapter_->StartSSL(); | |
254 | |
255 ssl_stream_adapter_->SignalEvent.connect(this, | |
256 &SSLAdapterTestDummyServer::OnSSLStreamAdapterEvent); | |
257 } | |
258 | |
259 const rtc::SSLMode ssl_mode_; | |
260 | |
261 std::unique_ptr<rtc::AsyncSocket> server_socket_; | |
262 std::unique_ptr<rtc::SSLStreamAdapter> ssl_stream_adapter_; | |
263 | |
264 std::unique_ptr<rtc::SSLIdentity> ssl_identity_; | |
265 | |
266 std::string data_; | |
267 }; | |
268 | |
269 class SSLAdapterTestBase : public testing::Test, | |
270 public sigslot::has_slots<> { | |
271 public: | |
272 explicit SSLAdapterTestBase(const rtc::SSLMode& ssl_mode, | |
273 const rtc::KeyParams& key_params) | |
274 : ssl_mode_(ssl_mode), | |
275 vss_(new rtc::VirtualSocketServer()), | |
276 thread_(vss_.get()), | |
277 server_(new SSLAdapterTestDummyServer(ssl_mode_, key_params)), | |
278 client_(new SSLAdapterTestDummyClient(ssl_mode_)), | |
279 handshake_wait_(kTimeout) {} | |
280 | |
281 void SetHandshakeWait(int wait) { | |
282 handshake_wait_ = wait; | |
283 } | |
284 | |
285 void TestHandshake(bool expect_success) { | |
286 int rv; | |
287 | |
288 // The initial state is CS_CLOSED | |
289 ASSERT_EQ(rtc::AsyncSocket::CS_CLOSED, client_->GetState()); | |
290 | |
291 rv = client_->Connect(server_->GetHostname(), server_->GetAddress()); | |
292 ASSERT_EQ(0, rv); | |
293 | |
294 // Now the state should be CS_CONNECTING | |
295 ASSERT_EQ(rtc::AsyncSocket::CS_CONNECTING, client_->GetState()); | |
296 | |
297 if (ssl_mode_ == rtc::SSL_MODE_DTLS) { | |
298 // For DTLS, call AcceptConnection() with the client's address. | |
299 server_->AcceptConnection(client_->GetAddress()); | |
300 } | |
301 | |
302 if (expect_success) { | |
303 // If expecting success, the client should end up in the CS_CONNECTED | |
304 // state after handshake. | |
305 EXPECT_EQ_WAIT(rtc::AsyncSocket::CS_CONNECTED, client_->GetState(), | |
306 handshake_wait_); | |
307 | |
308 LOG(LS_INFO) << GetSSLProtocolName(ssl_mode_) << " handshake complete."; | |
309 | |
310 } else { | |
311 // On handshake failure the client should end up in the CS_CLOSED state. | |
312 EXPECT_EQ_WAIT(rtc::AsyncSocket::CS_CLOSED, client_->GetState(), | |
313 handshake_wait_); | |
314 | |
315 LOG(LS_INFO) << GetSSLProtocolName(ssl_mode_) << " handshake failed."; | |
316 } | |
317 } | |
318 | |
319 void TestTransfer(const std::string& message) { | |
320 int rv; | |
321 | |
322 rv = client_->Send(message); | |
323 ASSERT_EQ(static_cast<int>(message.length()), rv); | |
324 | |
325 // The server should have received the client's message. | |
326 EXPECT_EQ_WAIT(message, server_->GetReceivedData(), kTimeout); | |
327 | |
328 rv = server_->Send(message); | |
329 ASSERT_EQ(static_cast<int>(message.length()), rv); | |
330 | |
331 // The client should have received the server's message. | |
332 EXPECT_EQ_WAIT(message, client_->GetReceivedData(), kTimeout); | |
333 | |
334 LOG(LS_INFO) << "Transfer complete."; | |
335 } | |
336 | |
337 protected: | |
338 const rtc::SSLMode ssl_mode_; | |
339 | |
340 std::unique_ptr<rtc::VirtualSocketServer> vss_; | |
341 rtc::AutoSocketServerThread thread_; | |
342 std::unique_ptr<SSLAdapterTestDummyServer> server_; | |
343 std::unique_ptr<SSLAdapterTestDummyClient> client_; | |
344 | |
345 int handshake_wait_; | |
346 }; | |
347 | |
348 class SSLAdapterTestTLS_RSA : public SSLAdapterTestBase { | |
349 public: | |
350 SSLAdapterTestTLS_RSA() | |
351 : SSLAdapterTestBase(rtc::SSL_MODE_TLS, rtc::KeyParams::RSA()) {} | |
352 }; | |
353 | |
354 class SSLAdapterTestTLS_ECDSA : public SSLAdapterTestBase { | |
355 public: | |
356 SSLAdapterTestTLS_ECDSA() | |
357 : SSLAdapterTestBase(rtc::SSL_MODE_TLS, rtc::KeyParams::ECDSA()) {} | |
358 }; | |
359 | |
360 class SSLAdapterTestDTLS_RSA : public SSLAdapterTestBase { | |
361 public: | |
362 SSLAdapterTestDTLS_RSA() | |
363 : SSLAdapterTestBase(rtc::SSL_MODE_DTLS, rtc::KeyParams::RSA()) {} | |
364 }; | |
365 | |
366 class SSLAdapterTestDTLS_ECDSA : public SSLAdapterTestBase { | |
367 public: | |
368 SSLAdapterTestDTLS_ECDSA() | |
369 : SSLAdapterTestBase(rtc::SSL_MODE_DTLS, rtc::KeyParams::ECDSA()) {} | |
370 }; | |
371 | |
372 // Basic tests: TLS | |
373 | |
374 // Test that handshake works, using RSA | |
375 TEST_F(SSLAdapterTestTLS_RSA, TestTLSConnect) { | |
376 TestHandshake(true); | |
377 } | |
378 | |
379 // Test that handshake works, using ECDSA | |
380 TEST_F(SSLAdapterTestTLS_ECDSA, TestTLSConnect) { | |
381 TestHandshake(true); | |
382 } | |
383 | |
384 // Test transfer between client and server, using RSA | |
385 TEST_F(SSLAdapterTestTLS_RSA, TestTLSTransfer) { | |
386 TestHandshake(true); | |
387 TestTransfer("Hello, world!"); | |
388 } | |
389 | |
390 TEST_F(SSLAdapterTestTLS_RSA, TestTLSTransferWithBlockedSocket) { | |
391 TestHandshake(true); | |
392 | |
393 // Tell the underlying socket to simulate being blocked. | |
394 vss_->SetSendingBlocked(true); | |
395 | |
396 std::string expected; | |
397 int rv; | |
398 // Send messages until the SSL socket adapter starts applying backpressure. | |
399 // Note that this may not occur immediately since there may be some amount of | |
400 // intermediate buffering (either in our code or in BoringSSL). | |
401 for (int i = 0; i < 1024; ++i) { | |
402 std::string message = "Hello, world: " + rtc::ToString(i); | |
403 rv = client_->Send(message); | |
404 if (rv != static_cast<int>(message.size())) { | |
405 // This test assumes either the whole message or none of it is sent. | |
406 ASSERT_EQ(-1, rv); | |
407 break; | |
408 } | |
409 expected += message; | |
410 } | |
411 // Assert that the loop above exited due to Send returning -1. | |
412 ASSERT_EQ(-1, rv); | |
413 | |
414 // Try sending another message while blocked. -1 should be returned again and | |
415 // it shouldn't end up received by the server later. | |
416 EXPECT_EQ(-1, client_->Send("Never sent")); | |
417 | |
418 // Unblock the underlying socket. All of the buffered messages should be sent | |
419 // without any further action. | |
420 vss_->SetSendingBlocked(false); | |
421 EXPECT_EQ_WAIT(expected, server_->GetReceivedData(), kTimeout); | |
422 | |
423 // Send another message. This previously wasn't working | |
424 std::string final_message = "Fin."; | |
425 expected += final_message; | |
426 EXPECT_EQ(static_cast<int>(final_message.size()), | |
427 client_->Send(final_message)); | |
428 EXPECT_EQ_WAIT(expected, server_->GetReceivedData(), kTimeout); | |
429 } | |
430 | |
431 // Test transfer between client and server, using ECDSA | |
432 TEST_F(SSLAdapterTestTLS_ECDSA, TestTLSTransfer) { | |
433 TestHandshake(true); | |
434 TestTransfer("Hello, world!"); | |
435 } | |
436 | |
437 // Basic tests: DTLS | |
438 | |
439 // Test that handshake works, using RSA | |
440 TEST_F(SSLAdapterTestDTLS_RSA, TestDTLSConnect) { | |
441 TestHandshake(true); | |
442 } | |
443 | |
444 // Test that handshake works, using ECDSA | |
445 TEST_F(SSLAdapterTestDTLS_ECDSA, TestDTLSConnect) { | |
446 TestHandshake(true); | |
447 } | |
448 | |
449 // Test transfer between client and server, using RSA | |
450 TEST_F(SSLAdapterTestDTLS_RSA, TestDTLSTransfer) { | |
451 TestHandshake(true); | |
452 TestTransfer("Hello, world!"); | |
453 } | |
454 | |
455 // Test transfer between client and server, using ECDSA | |
456 TEST_F(SSLAdapterTestDTLS_ECDSA, TestDTLSTransfer) { | |
457 TestHandshake(true); | |
458 TestTransfer("Hello, world!"); | |
459 } | |
OLD | NEW |