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

Side by Side Diff: webrtc/base/ssladapter_unittest.cc

Issue 2877023002: Move webrtc/{base => rtc_base} (Closed)
Patch Set: update presubmit.py and DEPS include rules Created 3 years, 5 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 unified diff | Download patch
« no previous file with comments | « webrtc/base/ssladapter.cc ('k') | webrtc/base/sslfingerprint.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 }
OLDNEW
« no previous file with comments | « webrtc/base/ssladapter.cc ('k') | webrtc/base/sslfingerprint.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698