blob: 430191641a72d7f4203a7ce466f23af2055cfb9e [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
2 * Copyright 2008 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#if HAVE_OPENSSL_SSL_H
12
13#include "webrtc/base/openssladapter.h"
14
15#if defined(WEBRTC_POSIX)
16#include <unistd.h>
17#endif
18
19// Must be included first before openssl headers.
20#include "webrtc/base/win32.h" // NOLINT
21
22#include <openssl/bio.h>
23#include <openssl/crypto.h>
24#include <openssl/err.h>
25#include <openssl/opensslv.h>
26#include <openssl/rand.h>
henrike@webrtc.orgd5a05062014-06-30 20:38:56 +000027#include <openssl/x509.h>
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000028#include <openssl/x509v3.h>
29
tfarina5237aaf2015-11-10 23:44:30 -080030#include "webrtc/base/arraysize.h"
nisseede5da42017-01-12 05:15:36 -080031#include "webrtc/base/checks.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000032#include "webrtc/base/common.h"
33#include "webrtc/base/logging.h"
34#include "webrtc/base/openssl.h"
Tommid44c0772016-03-11 17:12:32 -080035#include "webrtc/base/safe_conversions.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000036#include "webrtc/base/sslroots.h"
37#include "webrtc/base/stringutils.h"
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +000038#include "webrtc/base/thread.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000039
Torbjorn Granlund9adc91d2016-03-24 14:05:06 +010040#ifndef OPENSSL_IS_BORINGSSL
41
42// TODO: Use a nicer abstraction for mutex.
43
44#if defined(WEBRTC_WIN)
45 #define MUTEX_TYPE HANDLE
46 #define MUTEX_SETUP(x) (x) = CreateMutex(NULL, FALSE, NULL)
47 #define MUTEX_CLEANUP(x) CloseHandle(x)
48 #define MUTEX_LOCK(x) WaitForSingleObject((x), INFINITE)
49 #define MUTEX_UNLOCK(x) ReleaseMutex(x)
50 #define THREAD_ID GetCurrentThreadId()
51#elif defined(WEBRTC_POSIX)
52 #define MUTEX_TYPE pthread_mutex_t
53 #define MUTEX_SETUP(x) pthread_mutex_init(&(x), NULL)
54 #define MUTEX_CLEANUP(x) pthread_mutex_destroy(&(x))
55 #define MUTEX_LOCK(x) pthread_mutex_lock(&(x))
56 #define MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x))
57 #define THREAD_ID pthread_self()
58#else
59 #error You must define mutex operations appropriate for your platform!
60#endif
61
62struct CRYPTO_dynlock_value {
63 MUTEX_TYPE mutex;
64};
65
66#endif // #ifndef OPENSSL_IS_BORINGSSL
67
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000068//////////////////////////////////////////////////////////////////////
69// SocketBIO
70//////////////////////////////////////////////////////////////////////
71
72static int socket_write(BIO* h, const char* buf, int num);
73static int socket_read(BIO* h, char* buf, int size);
74static int socket_puts(BIO* h, const char* str);
75static long socket_ctrl(BIO* h, int cmd, long arg1, void* arg2);
76static int socket_new(BIO* h);
77static int socket_free(BIO* data);
78
davidben@webrtc.org36d5c3c2015-01-22 23:06:17 +000079// TODO(davidben): This should be const once BoringSSL is assumed.
80static BIO_METHOD methods_socket = {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000081 BIO_TYPE_BIO,
82 "socket",
83 socket_write,
84 socket_read,
85 socket_puts,
86 0,
87 socket_ctrl,
88 socket_new,
89 socket_free,
90 NULL,
91};
92
davidben@webrtc.org36d5c3c2015-01-22 23:06:17 +000093static BIO_METHOD* BIO_s_socket2() { return(&methods_socket); }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000094
henrike@webrtc.orgc50bf7c2014-05-14 18:24:13 +000095static BIO* BIO_new_socket(rtc::AsyncSocket* socket) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000096 BIO* ret = BIO_new(BIO_s_socket2());
97 if (ret == NULL) {
98 return NULL;
99 }
100 ret->ptr = socket;
101 return ret;
102}
103
104static int socket_new(BIO* b) {
105 b->shutdown = 0;
106 b->init = 1;
107 b->num = 0; // 1 means socket closed
108 b->ptr = 0;
109 return 1;
110}
111
112static int socket_free(BIO* b) {
113 if (b == NULL)
114 return 0;
115 return 1;
116}
117
118static int socket_read(BIO* b, char* out, int outl) {
119 if (!out)
120 return -1;
121 rtc::AsyncSocket* socket = static_cast<rtc::AsyncSocket*>(b->ptr);
122 BIO_clear_retry_flags(b);
Stefan Holmer9131efd2016-05-23 18:19:26 +0200123 int result = socket->Recv(out, outl, nullptr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000124 if (result > 0) {
125 return result;
126 } else if (result == 0) {
127 b->num = 1;
128 } else if (socket->IsBlocking()) {
129 BIO_set_retry_read(b);
130 }
131 return -1;
132}
133
134static int socket_write(BIO* b, const char* in, int inl) {
135 if (!in)
136 return -1;
137 rtc::AsyncSocket* socket = static_cast<rtc::AsyncSocket*>(b->ptr);
138 BIO_clear_retry_flags(b);
139 int result = socket->Send(in, inl);
140 if (result > 0) {
141 return result;
142 } else if (socket->IsBlocking()) {
143 BIO_set_retry_write(b);
144 }
145 return -1;
146}
147
148static int socket_puts(BIO* b, const char* str) {
henrike@webrtc.orgd89b69a2014-11-06 17:23:09 +0000149 return socket_write(b, str, rtc::checked_cast<int>(strlen(str)));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000150}
151
152static long socket_ctrl(BIO* b, int cmd, long num, void* ptr) {
henrike@webrtc.org14abcc72014-05-16 16:54:44 +0000153 RTC_UNUSED(num);
154 RTC_UNUSED(ptr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000155
156 switch (cmd) {
157 case BIO_CTRL_RESET:
158 return 0;
159 case BIO_CTRL_EOF:
160 return b->num;
161 case BIO_CTRL_WPENDING:
162 case BIO_CTRL_PENDING:
163 return 0;
164 case BIO_CTRL_FLUSH:
165 return 1;
166 default:
167 return 0;
168 }
169}
170
171/////////////////////////////////////////////////////////////////////////////
172// OpenSSLAdapter
173/////////////////////////////////////////////////////////////////////////////
174
175namespace rtc {
176
Torbjorn Granlund9adc91d2016-03-24 14:05:06 +0100177#ifndef OPENSSL_IS_BORINGSSL
178
179// This array will store all of the mutexes available to OpenSSL.
180static MUTEX_TYPE* mutex_buf = NULL;
181
182static void locking_function(int mode, int n, const char * file, int line) {
183 if (mode & CRYPTO_LOCK) {
184 MUTEX_LOCK(mutex_buf[n]);
185 } else {
186 MUTEX_UNLOCK(mutex_buf[n]);
187 }
188}
189
190static unsigned long id_function() { // NOLINT
191 // Use old-style C cast because THREAD_ID's type varies with the platform,
192 // in some cases requiring static_cast, and in others requiring
193 // reinterpret_cast.
194 return (unsigned long)THREAD_ID; // NOLINT
195}
196
197static CRYPTO_dynlock_value* dyn_create_function(const char* file, int line) {
198 CRYPTO_dynlock_value* value = new CRYPTO_dynlock_value;
199 if (!value)
200 return NULL;
201 MUTEX_SETUP(value->mutex);
202 return value;
203}
204
205static void dyn_lock_function(int mode, CRYPTO_dynlock_value* l,
206 const char* file, int line) {
207 if (mode & CRYPTO_LOCK) {
208 MUTEX_LOCK(l->mutex);
209 } else {
210 MUTEX_UNLOCK(l->mutex);
211 }
212}
213
214static void dyn_destroy_function(CRYPTO_dynlock_value* l,
215 const char* file, int line) {
216 MUTEX_CLEANUP(l->mutex);
217 delete l;
218}
219
220#endif // #ifndef OPENSSL_IS_BORINGSSL
221
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000222VerificationCallback OpenSSLAdapter::custom_verify_callback_ = NULL;
223
224bool OpenSSLAdapter::InitializeSSL(VerificationCallback callback) {
Torbjorn Granlund9adc91d2016-03-24 14:05:06 +0100225 if (!InitializeSSLThread() || !SSL_library_init())
226 return false;
227#if !defined(ADDRESS_SANITIZER) || !defined(WEBRTC_MAC) || defined(WEBRTC_IOS)
228 // Loading the error strings crashes mac_asan. Omit this debugging aid there.
229 SSL_load_error_strings();
230#endif
231 ERR_load_BIO_strings();
232 OpenSSL_add_all_algorithms();
233 RAND_poll();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000234 custom_verify_callback_ = callback;
235 return true;
236}
237
Torbjorn Granlund9adc91d2016-03-24 14:05:06 +0100238bool OpenSSLAdapter::InitializeSSLThread() {
239 // BoringSSL is doing the locking internally, so the callbacks are not used
240 // in this case (and are no-ops anyways).
241#ifndef OPENSSL_IS_BORINGSSL
242 mutex_buf = new MUTEX_TYPE[CRYPTO_num_locks()];
243 if (!mutex_buf)
244 return false;
245 for (int i = 0; i < CRYPTO_num_locks(); ++i)
246 MUTEX_SETUP(mutex_buf[i]);
247
248 // we need to cast our id_function to return an unsigned long -- pthread_t is
249 // a pointer
250 CRYPTO_set_id_callback(id_function);
251 CRYPTO_set_locking_callback(locking_function);
252 CRYPTO_set_dynlock_create_callback(dyn_create_function);
253 CRYPTO_set_dynlock_lock_callback(dyn_lock_function);
254 CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function);
255#endif // #ifndef OPENSSL_IS_BORINGSSL
256 return true;
257}
258
259bool OpenSSLAdapter::CleanupSSL() {
260#ifndef OPENSSL_IS_BORINGSSL
261 if (!mutex_buf)
262 return false;
263 CRYPTO_set_id_callback(NULL);
264 CRYPTO_set_locking_callback(NULL);
265 CRYPTO_set_dynlock_create_callback(NULL);
266 CRYPTO_set_dynlock_lock_callback(NULL);
267 CRYPTO_set_dynlock_destroy_callback(NULL);
268 for (int i = 0; i < CRYPTO_num_locks(); ++i)
269 MUTEX_CLEANUP(mutex_buf[i]);
270 delete [] mutex_buf;
271 mutex_buf = NULL;
272#endif // #ifndef OPENSSL_IS_BORINGSSL
273 return true;
274}
275
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000276OpenSSLAdapter::OpenSSLAdapter(AsyncSocket* socket)
277 : SSLAdapter(socket),
278 state_(SSL_NONE),
279 ssl_read_needs_write_(false),
280 ssl_write_needs_read_(false),
281 restartable_(false),
282 ssl_(NULL), ssl_ctx_(NULL),
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000283 ssl_mode_(SSL_MODE_TLS),
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000284 custom_verification_succeeded_(false) {
285}
286
287OpenSSLAdapter::~OpenSSLAdapter() {
288 Cleanup();
289}
290
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000291void
292OpenSSLAdapter::SetMode(SSLMode mode) {
nisseede5da42017-01-12 05:15:36 -0800293 RTC_DCHECK(state_ == SSL_NONE);
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000294 ssl_mode_ = mode;
295}
296
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000297int
298OpenSSLAdapter::StartSSL(const char* hostname, bool restartable) {
299 if (state_ != SSL_NONE)
300 return -1;
301
302 ssl_host_name_ = hostname;
303 restartable_ = restartable;
304
305 if (socket_->GetState() != Socket::CS_CONNECTED) {
306 state_ = SSL_WAIT;
307 return 0;
308 }
309
310 state_ = SSL_CONNECTING;
311 if (int err = BeginSSL()) {
312 Error("BeginSSL", err, false);
313 return err;
314 }
315
316 return 0;
317}
318
319int
320OpenSSLAdapter::BeginSSL() {
321 LOG(LS_INFO) << "BeginSSL: " << ssl_host_name_;
nisseede5da42017-01-12 05:15:36 -0800322 RTC_DCHECK(state_ == SSL_CONNECTING);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000323
324 int err = 0;
325 BIO* bio = NULL;
326
327 // First set up the context
328 if (!ssl_ctx_)
329 ssl_ctx_ = SetupSSLContext();
330
331 if (!ssl_ctx_) {
332 err = -1;
333 goto ssl_error;
334 }
335
Peter Boström0b518bf2016-01-27 12:35:40 +0100336 bio = BIO_new_socket(socket_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000337 if (!bio) {
338 err = -1;
339 goto ssl_error;
340 }
341
342 ssl_ = SSL_new(ssl_ctx_);
343 if (!ssl_) {
344 err = -1;
345 goto ssl_error;
346 }
347
348 SSL_set_app_data(ssl_, this);
349
350 SSL_set_bio(ssl_, bio, bio);
351 SSL_set_mode(ssl_, SSL_MODE_ENABLE_PARTIAL_WRITE |
352 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
353
354 // the SSL object owns the bio now
355 bio = NULL;
356
357 // Do the connect
358 err = ContinueSSL();
359 if (err != 0)
360 goto ssl_error;
361
362 return err;
363
364ssl_error:
365 Cleanup();
366 if (bio)
367 BIO_free(bio);
368
369 return err;
370}
371
372int
373OpenSSLAdapter::ContinueSSL() {
nisseede5da42017-01-12 05:15:36 -0800374 RTC_DCHECK(state_ == SSL_CONNECTING);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000375
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000376 // Clear the DTLS timer
377 Thread::Current()->Clear(this, MSG_TIMEOUT);
378
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000379 int code = SSL_connect(ssl_);
380 switch (SSL_get_error(ssl_, code)) {
381 case SSL_ERROR_NONE:
382 if (!SSLPostConnectionCheck(ssl_, ssl_host_name_.c_str())) {
383 LOG(LS_ERROR) << "TLS post connection check failed";
384 // make sure we close the socket
385 Cleanup();
386 // The connect failed so return -1 to shut down the socket
387 return -1;
388 }
389
390 state_ = SSL_CONNECTED;
391 AsyncSocketAdapter::OnConnectEvent(this);
392#if 0 // TODO: worry about this
393 // Don't let ourselves go away during the callbacks
394 PRefPtr<OpenSSLAdapter> lock(this);
395 LOG(LS_INFO) << " -- onStreamReadable";
396 AsyncSocketAdapter::OnReadEvent(this);
397 LOG(LS_INFO) << " -- onStreamWriteable";
398 AsyncSocketAdapter::OnWriteEvent(this);
399#endif
400 break;
401
402 case SSL_ERROR_WANT_READ:
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000403 LOG(LS_VERBOSE) << " -- error want read";
404 struct timeval timeout;
405 if (DTLSv1_get_timeout(ssl_, &timeout)) {
406 int delay = timeout.tv_sec * 1000 + timeout.tv_usec/1000;
407
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700408 Thread::Current()->PostDelayed(RTC_FROM_HERE, delay, this, MSG_TIMEOUT,
409 0);
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000410 }
411 break;
412
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000413 case SSL_ERROR_WANT_WRITE:
414 break;
415
416 case SSL_ERROR_ZERO_RETURN:
417 default:
418 LOG(LS_WARNING) << "ContinueSSL -- error " << code;
419 return (code != 0) ? code : -1;
420 }
421
422 return 0;
423}
424
425void
426OpenSSLAdapter::Error(const char* context, int err, bool signal) {
427 LOG(LS_WARNING) << "OpenSSLAdapter::Error("
428 << context << ", " << err << ")";
429 state_ = SSL_ERROR;
430 SetError(err);
431 if (signal)
432 AsyncSocketAdapter::OnCloseEvent(this, err);
433}
434
435void
436OpenSSLAdapter::Cleanup() {
437 LOG(LS_INFO) << "Cleanup";
438
439 state_ = SSL_NONE;
440 ssl_read_needs_write_ = false;
441 ssl_write_needs_read_ = false;
442 custom_verification_succeeded_ = false;
443
444 if (ssl_) {
445 SSL_free(ssl_);
446 ssl_ = NULL;
447 }
448
449 if (ssl_ctx_) {
450 SSL_CTX_free(ssl_ctx_);
451 ssl_ctx_ = NULL;
452 }
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000453
454 // Clear the DTLS timer
455 Thread::Current()->Clear(this, MSG_TIMEOUT);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000456}
457
458//
459// AsyncSocket Implementation
460//
461
462int
463OpenSSLAdapter::Send(const void* pv, size_t cb) {
464 //LOG(LS_INFO) << "OpenSSLAdapter::Send(" << cb << ")";
465
466 switch (state_) {
467 case SSL_NONE:
468 return AsyncSocketAdapter::Send(pv, cb);
469
470 case SSL_WAIT:
471 case SSL_CONNECTING:
skvladc309e0e2016-07-28 17:15:20 -0700472 SetError(ENOTCONN);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000473 return SOCKET_ERROR;
474
475 case SSL_CONNECTED:
476 break;
477
478 case SSL_ERROR:
479 default:
480 return SOCKET_ERROR;
481 }
482
483 // OpenSSL will return an error if we try to write zero bytes
484 if (cb == 0)
485 return 0;
486
487 ssl_write_needs_read_ = false;
488
henrike@webrtc.orgd89b69a2014-11-06 17:23:09 +0000489 int code = SSL_write(ssl_, pv, checked_cast<int>(cb));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000490 switch (SSL_get_error(ssl_, code)) {
491 case SSL_ERROR_NONE:
492 //LOG(LS_INFO) << " -- success";
493 return code;
494 case SSL_ERROR_WANT_READ:
495 //LOG(LS_INFO) << " -- error want read";
496 ssl_write_needs_read_ = true;
497 SetError(EWOULDBLOCK);
498 break;
499 case SSL_ERROR_WANT_WRITE:
500 //LOG(LS_INFO) << " -- error want write";
501 SetError(EWOULDBLOCK);
502 break;
503 case SSL_ERROR_ZERO_RETURN:
504 //LOG(LS_INFO) << " -- remote side closed";
505 SetError(EWOULDBLOCK);
506 // do we need to signal closure?
507 break;
508 default:
509 //LOG(LS_INFO) << " -- error " << code;
510 Error("SSL_write", (code ? code : -1), false);
511 break;
512 }
513
514 return SOCKET_ERROR;
515}
516
517int
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000518OpenSSLAdapter::SendTo(const void* pv, size_t cb, const SocketAddress& addr) {
519 if (socket_->GetState() == Socket::CS_CONNECTED &&
520 addr == socket_->GetRemoteAddress()) {
521 return Send(pv, cb);
522 }
523
524 SetError(ENOTCONN);
525
526 return SOCKET_ERROR;
527}
528
Stefan Holmer9131efd2016-05-23 18:19:26 +0200529int OpenSSLAdapter::Recv(void* pv, size_t cb, int64_t* timestamp) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000530 //LOG(LS_INFO) << "OpenSSLAdapter::Recv(" << cb << ")";
531 switch (state_) {
532
533 case SSL_NONE:
Stefan Holmer9131efd2016-05-23 18:19:26 +0200534 return AsyncSocketAdapter::Recv(pv, cb, timestamp);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000535
536 case SSL_WAIT:
537 case SSL_CONNECTING:
skvladc309e0e2016-07-28 17:15:20 -0700538 SetError(ENOTCONN);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000539 return SOCKET_ERROR;
540
541 case SSL_CONNECTED:
542 break;
543
544 case SSL_ERROR:
545 default:
546 return SOCKET_ERROR;
547 }
548
549 // Don't trust OpenSSL with zero byte reads
550 if (cb == 0)
551 return 0;
552
553 ssl_read_needs_write_ = false;
554
henrike@webrtc.orgd89b69a2014-11-06 17:23:09 +0000555 int code = SSL_read(ssl_, pv, checked_cast<int>(cb));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000556 switch (SSL_get_error(ssl_, code)) {
557 case SSL_ERROR_NONE:
558 //LOG(LS_INFO) << " -- success";
559 return code;
560 case SSL_ERROR_WANT_READ:
561 //LOG(LS_INFO) << " -- error want read";
562 SetError(EWOULDBLOCK);
563 break;
564 case SSL_ERROR_WANT_WRITE:
565 //LOG(LS_INFO) << " -- error want write";
566 ssl_read_needs_write_ = true;
567 SetError(EWOULDBLOCK);
568 break;
569 case SSL_ERROR_ZERO_RETURN:
570 //LOG(LS_INFO) << " -- remote side closed";
571 SetError(EWOULDBLOCK);
572 // do we need to signal closure?
573 break;
574 default:
575 //LOG(LS_INFO) << " -- error " << code;
576 Error("SSL_read", (code ? code : -1), false);
577 break;
578 }
579
580 return SOCKET_ERROR;
581}
582
Stefan Holmer9131efd2016-05-23 18:19:26 +0200583int OpenSSLAdapter::RecvFrom(void* pv,
584 size_t cb,
585 SocketAddress* paddr,
586 int64_t* timestamp) {
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000587 if (socket_->GetState() == Socket::CS_CONNECTED) {
Stefan Holmer9131efd2016-05-23 18:19:26 +0200588 int ret = Recv(pv, cb, timestamp);
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000589
590 *paddr = GetRemoteAddress();
591
592 return ret;
593 }
594
595 SetError(ENOTCONN);
596
597 return SOCKET_ERROR;
598}
599
600int
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000601OpenSSLAdapter::Close() {
602 Cleanup();
603 state_ = restartable_ ? SSL_WAIT : SSL_NONE;
604 return AsyncSocketAdapter::Close();
605}
606
607Socket::ConnState
608OpenSSLAdapter::GetState() const {
609 //if (signal_close_)
610 // return CS_CONNECTED;
611 ConnState state = socket_->GetState();
612 if ((state == CS_CONNECTED)
613 && ((state_ == SSL_WAIT) || (state_ == SSL_CONNECTING)))
614 state = CS_CONNECTING;
615 return state;
616}
617
618void
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000619OpenSSLAdapter::OnMessage(Message* msg) {
620 if (MSG_TIMEOUT == msg->message_id) {
621 LOG(LS_INFO) << "DTLS timeout expired";
622 DTLSv1_handle_timeout(ssl_);
623 ContinueSSL();
624 }
625}
626
627void
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000628OpenSSLAdapter::OnConnectEvent(AsyncSocket* socket) {
629 LOG(LS_INFO) << "OpenSSLAdapter::OnConnectEvent";
630 if (state_ != SSL_WAIT) {
nisseede5da42017-01-12 05:15:36 -0800631 RTC_DCHECK(state_ == SSL_NONE);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000632 AsyncSocketAdapter::OnConnectEvent(socket);
633 return;
634 }
635
636 state_ = SSL_CONNECTING;
637 if (int err = BeginSSL()) {
638 AsyncSocketAdapter::OnCloseEvent(socket, err);
639 }
640}
641
642void
643OpenSSLAdapter::OnReadEvent(AsyncSocket* socket) {
644 //LOG(LS_INFO) << "OpenSSLAdapter::OnReadEvent";
645
646 if (state_ == SSL_NONE) {
647 AsyncSocketAdapter::OnReadEvent(socket);
648 return;
649 }
650
651 if (state_ == SSL_CONNECTING) {
652 if (int err = ContinueSSL()) {
653 Error("ContinueSSL", err);
654 }
655 return;
656 }
657
658 if (state_ != SSL_CONNECTED)
659 return;
660
661 // Don't let ourselves go away during the callbacks
662 //PRefPtr<OpenSSLAdapter> lock(this); // TODO: fix this
663 if (ssl_write_needs_read_) {
664 //LOG(LS_INFO) << " -- onStreamWriteable";
665 AsyncSocketAdapter::OnWriteEvent(socket);
666 }
667
668 //LOG(LS_INFO) << " -- onStreamReadable";
669 AsyncSocketAdapter::OnReadEvent(socket);
670}
671
672void
673OpenSSLAdapter::OnWriteEvent(AsyncSocket* socket) {
674 //LOG(LS_INFO) << "OpenSSLAdapter::OnWriteEvent";
675
676 if (state_ == SSL_NONE) {
677 AsyncSocketAdapter::OnWriteEvent(socket);
678 return;
679 }
680
681 if (state_ == SSL_CONNECTING) {
682 if (int err = ContinueSSL()) {
683 Error("ContinueSSL", err);
684 }
685 return;
686 }
687
688 if (state_ != SSL_CONNECTED)
689 return;
690
691 // Don't let ourselves go away during the callbacks
692 //PRefPtr<OpenSSLAdapter> lock(this); // TODO: fix this
693
694 if (ssl_read_needs_write_) {
695 //LOG(LS_INFO) << " -- onStreamReadable";
696 AsyncSocketAdapter::OnReadEvent(socket);
697 }
698
699 //LOG(LS_INFO) << " -- onStreamWriteable";
700 AsyncSocketAdapter::OnWriteEvent(socket);
701}
702
703void
704OpenSSLAdapter::OnCloseEvent(AsyncSocket* socket, int err) {
705 LOG(LS_INFO) << "OpenSSLAdapter::OnCloseEvent(" << err << ")";
706 AsyncSocketAdapter::OnCloseEvent(socket, err);
707}
708
709// This code is taken from the "Network Security with OpenSSL"
710// sample in chapter 5
711
712bool OpenSSLAdapter::VerifyServerName(SSL* ssl, const char* host,
713 bool ignore_bad_cert) {
714 if (!host)
715 return false;
716
717 // Checking the return from SSL_get_peer_certificate here is not strictly
718 // necessary. With our setup, it is not possible for it to return
719 // NULL. However, it is good form to check the return.
720 X509* certificate = SSL_get_peer_certificate(ssl);
721 if (!certificate)
722 return false;
723
724 // Logging certificates is extremely verbose. So it is disabled by default.
725#ifdef LOG_CERTIFICATES
726 {
727 LOG(LS_INFO) << "Certificate from server:";
728 BIO* mem = BIO_new(BIO_s_mem());
729 X509_print_ex(mem, certificate, XN_FLAG_SEP_CPLUS_SPC, X509_FLAG_NO_HEADER);
730 BIO_write(mem, "\0", 1);
731 char* buffer;
732 BIO_get_mem_data(mem, &buffer);
733 LOG(LS_INFO) << buffer;
734 BIO_free(mem);
735
736 char* cipher_description =
737 SSL_CIPHER_description(SSL_get_current_cipher(ssl), NULL, 128);
738 LOG(LS_INFO) << "Cipher: " << cipher_description;
739 OPENSSL_free(cipher_description);
740 }
741#endif
742
743 bool ok = false;
744 int extension_count = X509_get_ext_count(certificate);
745 for (int i = 0; i < extension_count; ++i) {
746 X509_EXTENSION* extension = X509_get_ext(certificate, i);
747 int extension_nid = OBJ_obj2nid(X509_EXTENSION_get_object(extension));
748
749 if (extension_nid == NID_subject_alt_name) {
750 const X509V3_EXT_METHOD* meth = X509V3_EXT_get(extension);
751 if (!meth)
752 break;
753
754 void* ext_str = NULL;
755
756 // We assign this to a local variable, instead of passing the address
757 // directly to ASN1_item_d2i.
758 // See http://readlist.com/lists/openssl.org/openssl-users/0/4761.html.
759 unsigned char* ext_value_data = extension->value->data;
760
761 const unsigned char **ext_value_data_ptr =
762 (const_cast<const unsigned char **>(&ext_value_data));
763
764 if (meth->it) {
765 ext_str = ASN1_item_d2i(NULL, ext_value_data_ptr,
766 extension->value->length,
767 ASN1_ITEM_ptr(meth->it));
768 } else {
769 ext_str = meth->d2i(NULL, ext_value_data_ptr, extension->value->length);
770 }
771
772 STACK_OF(CONF_VALUE)* value = meth->i2v(meth, ext_str, NULL);
henrike@webrtc.org92a9bac2014-07-14 22:03:57 +0000773
774 // Cast to size_t to be compilable for both OpenSSL and BoringSSL.
775 for (size_t j = 0; j < static_cast<size_t>(sk_CONF_VALUE_num(value));
776 ++j) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000777 CONF_VALUE* nval = sk_CONF_VALUE_value(value, j);
778 // The value for nval can contain wildcards
779 if (!strcmp(nval->name, "DNS") && string_match(host, nval->value)) {
780 ok = true;
781 break;
782 }
783 }
784 sk_CONF_VALUE_pop_free(value, X509V3_conf_free);
785 value = NULL;
786
787 if (meth->it) {
788 ASN1_item_free(reinterpret_cast<ASN1_VALUE*>(ext_str),
789 ASN1_ITEM_ptr(meth->it));
790 } else {
791 meth->ext_free(ext_str);
792 }
793 ext_str = NULL;
794 }
795 if (ok)
796 break;
797 }
798
799 char data[256];
henrike@webrtc.orgd5a05062014-06-30 20:38:56 +0000800 X509_NAME* subject;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000801 if (!ok
802 && ((subject = X509_get_subject_name(certificate)) != NULL)
803 && (X509_NAME_get_text_by_NID(subject, NID_commonName,
804 data, sizeof(data)) > 0)) {
805 data[sizeof(data)-1] = 0;
806 if (_stricmp(data, host) == 0)
807 ok = true;
808 }
809
810 X509_free(certificate);
811
812 // This should only ever be turned on for debugging and development.
813 if (!ok && ignore_bad_cert) {
814 LOG(LS_WARNING) << "TLS certificate check FAILED. "
815 << "Allowing connection anyway.";
816 ok = true;
817 }
818
819 return ok;
820}
821
822bool OpenSSLAdapter::SSLPostConnectionCheck(SSL* ssl, const char* host) {
823 bool ok = VerifyServerName(ssl, host, ignore_bad_cert());
824
825 if (ok) {
826 ok = (SSL_get_verify_result(ssl) == X509_V_OK ||
827 custom_verification_succeeded_);
828 }
829
830 if (!ok && ignore_bad_cert()) {
831 LOG(LS_INFO) << "Other TLS post connection checks failed.";
832 ok = true;
833 }
834
835 return ok;
836}
837
tfarinaa41ab932015-10-30 16:08:48 -0700838#if !defined(NDEBUG)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000839
840// We only use this for tracing and so it is only needed in debug mode
841
842void
843OpenSSLAdapter::SSLInfoCallback(const SSL* s, int where, int ret) {
844 const char* str = "undefined";
845 int w = where & ~SSL_ST_MASK;
846 if (w & SSL_ST_CONNECT) {
847 str = "SSL_connect";
848 } else if (w & SSL_ST_ACCEPT) {
849 str = "SSL_accept";
850 }
851 if (where & SSL_CB_LOOP) {
852 LOG(LS_INFO) << str << ":" << SSL_state_string_long(s);
853 } else if (where & SSL_CB_ALERT) {
854 str = (where & SSL_CB_READ) ? "read" : "write";
855 LOG(LS_INFO) << "SSL3 alert " << str
856 << ":" << SSL_alert_type_string_long(ret)
857 << ":" << SSL_alert_desc_string_long(ret);
858 } else if (where & SSL_CB_EXIT) {
859 if (ret == 0) {
860 LOG(LS_INFO) << str << ":failed in " << SSL_state_string_long(s);
861 } else if (ret < 0) {
862 LOG(LS_INFO) << str << ":error in " << SSL_state_string_long(s);
863 }
864 }
865}
866
tfarinaa41ab932015-10-30 16:08:48 -0700867#endif
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000868
869int
870OpenSSLAdapter::SSLVerifyCallback(int ok, X509_STORE_CTX* store) {
tfarinaa41ab932015-10-30 16:08:48 -0700871#if !defined(NDEBUG)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000872 if (!ok) {
873 char data[256];
874 X509* cert = X509_STORE_CTX_get_current_cert(store);
875 int depth = X509_STORE_CTX_get_error_depth(store);
876 int err = X509_STORE_CTX_get_error(store);
877
878 LOG(LS_INFO) << "Error with certificate at depth: " << depth;
879 X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof(data));
880 LOG(LS_INFO) << " issuer = " << data;
881 X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof(data));
882 LOG(LS_INFO) << " subject = " << data;
883 LOG(LS_INFO) << " err = " << err
884 << ":" << X509_verify_cert_error_string(err);
885 }
886#endif
887
888 // Get our stream pointer from the store
889 SSL* ssl = reinterpret_cast<SSL*>(
890 X509_STORE_CTX_get_ex_data(store,
891 SSL_get_ex_data_X509_STORE_CTX_idx()));
892
893 OpenSSLAdapter* stream =
894 reinterpret_cast<OpenSSLAdapter*>(SSL_get_app_data(ssl));
895
896 if (!ok && custom_verify_callback_) {
897 void* cert =
898 reinterpret_cast<void*>(X509_STORE_CTX_get_current_cert(store));
899 if (custom_verify_callback_(cert)) {
900 stream->custom_verification_succeeded_ = true;
901 LOG(LS_INFO) << "validated certificate using custom callback";
902 ok = true;
903 }
904 }
905
906 // Should only be used for debugging and development.
907 if (!ok && stream->ignore_bad_cert()) {
908 LOG(LS_WARNING) << "Ignoring cert error while verifying cert chain";
909 ok = 1;
910 }
911
912 return ok;
913}
914
915bool OpenSSLAdapter::ConfigureTrustedRootCertificates(SSL_CTX* ctx) {
916 // Add the root cert that we care about to the SSL context
917 int count_of_added_certs = 0;
tfarina5237aaf2015-11-10 23:44:30 -0800918 for (size_t i = 0; i < arraysize(kSSLCertCertificateList); i++) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000919 const unsigned char* cert_buffer = kSSLCertCertificateList[i];
920 size_t cert_buffer_len = kSSLCertCertificateSizeList[i];
henrike@webrtc.orgd89b69a2014-11-06 17:23:09 +0000921 X509* cert = d2i_X509(NULL, &cert_buffer,
922 checked_cast<long>(cert_buffer_len));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000923 if (cert) {
924 int return_value = X509_STORE_add_cert(SSL_CTX_get_cert_store(ctx), cert);
925 if (return_value == 0) {
926 LOG(LS_WARNING) << "Unable to add certificate.";
927 } else {
928 count_of_added_certs++;
929 }
930 X509_free(cert);
931 }
932 }
933 return count_of_added_certs > 0;
934}
935
936SSL_CTX*
937OpenSSLAdapter::SetupSSLContext() {
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000938 SSL_CTX* ctx = SSL_CTX_new(ssl_mode_ == SSL_MODE_DTLS ?
939 DTLSv1_client_method() : TLSv1_client_method());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000940 if (ctx == NULL) {
941 unsigned long error = ERR_get_error(); // NOLINT: type used by OpenSSL.
942 LOG(LS_WARNING) << "SSL_CTX creation failed: "
943 << '"' << ERR_reason_error_string(error) << "\" "
944 << "(error=" << error << ')';
945 return NULL;
946 }
947 if (!ConfigureTrustedRootCertificates(ctx)) {
948 SSL_CTX_free(ctx);
949 return NULL;
950 }
951
tfarinaa41ab932015-10-30 16:08:48 -0700952#if !defined(NDEBUG)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000953 SSL_CTX_set_info_callback(ctx, SSLInfoCallback);
954#endif
955
956 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, SSLVerifyCallback);
957 SSL_CTX_set_verify_depth(ctx, 4);
958 SSL_CTX_set_cipher_list(ctx, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
959
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000960 if (ssl_mode_ == SSL_MODE_DTLS) {
961 SSL_CTX_set_read_ahead(ctx, 1);
962 }
963
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000964 return ctx;
965}
966
967} // namespace rtc
968
969#endif // HAVE_OPENSSL_SSL_H