147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/*
247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  Copyright 2008 The WebRTC Project Authors. All rights reserved.
347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *
447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  Use of this source code is governed by a BSD-style license
547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  that can be found in the LICENSE file in the root of the source
647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  tree. An additional intellectual property rights grant can be found
747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  in the file PATENTS.  All contributing project authors may
847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org */
1047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if HAVE_OPENSSL_SSL_H
1247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/openssladapter.h"
1447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_POSIX)
1647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <unistd.h>
1747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
1847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Must be included first before openssl headers.
2047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/win32.h"  // NOLINT
2147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
2247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <openssl/bio.h>
2347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <openssl/crypto.h>
2447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <openssl/err.h>
2547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <openssl/opensslv.h>
2647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <openssl/rand.h>
27222d84ad848886a7123d3ad47c4daf188ecac574henrike@webrtc.org#include <openssl/x509.h>
2847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <openssl/x509v3.h>
2947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
3047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if HAVE_CONFIG_H
3147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "config.h"
3247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif  // HAVE_CONFIG_H
3347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
3447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/common.h"
3547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/logging.h"
3647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/openssl.h"
3747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/sslroots.h"
3847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/stringutils.h"
3947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
4047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// TODO: Use a nicer abstraction for mutex.
4147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
4247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
4347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  #define MUTEX_TYPE HANDLE
4447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  #define MUTEX_SETUP(x) (x) = CreateMutex(NULL, FALSE, NULL)
4547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  #define MUTEX_CLEANUP(x) CloseHandle(x)
4647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  #define MUTEX_LOCK(x) WaitForSingleObject((x), INFINITE)
4747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  #define MUTEX_UNLOCK(x) ReleaseMutex(x)
4847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  #define THREAD_ID GetCurrentThreadId()
4947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(WEBRTC_POSIX)
5047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  #define MUTEX_TYPE pthread_mutex_t
5147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  #define MUTEX_SETUP(x) pthread_mutex_init(&(x), NULL)
5247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  #define MUTEX_CLEANUP(x) pthread_mutex_destroy(&(x))
5347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  #define MUTEX_LOCK(x) pthread_mutex_lock(&(x))
5447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  #define MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x))
5547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  #define THREAD_ID pthread_self()
5647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#else
5747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  #error You must define mutex operations appropriate for your platform!
5847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
5947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
6047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstruct CRYPTO_dynlock_value {
6147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  MUTEX_TYPE mutex;
6247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org};
6347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
6447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//////////////////////////////////////////////////////////////////////
6547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// SocketBIO
6647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//////////////////////////////////////////////////////////////////////
6747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
6847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic int socket_write(BIO* h, const char* buf, int num);
6947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic int socket_read(BIO* h, char* buf, int size);
7047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic int socket_puts(BIO* h, const char* str);
7147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic long socket_ctrl(BIO* h, int cmd, long arg1, void* arg2);
7247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic int socket_new(BIO* h);
7347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic int socket_free(BIO* data);
7447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
7547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic BIO_METHOD methods_socket = {
7647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  BIO_TYPE_BIO,
7747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  "socket",
7847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  socket_write,
7947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  socket_read,
8047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  socket_puts,
8147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  0,
8247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  socket_ctrl,
8347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  socket_new,
8447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  socket_free,
8547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  NULL,
8647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org};
8747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
88b2eea5cf51211d6d4fd735380705f9626a1ebff9henrike@webrtc.orgstatic BIO_METHOD* BIO_s_socket2() { return(&methods_socket); }
8947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
90b2eea5cf51211d6d4fd735380705f9626a1ebff9henrike@webrtc.orgstatic BIO* BIO_new_socket(rtc::AsyncSocket* socket) {
9147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  BIO* ret = BIO_new(BIO_s_socket2());
9247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (ret == NULL) {
9347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          return NULL;
9447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
9547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ret->ptr = socket;
9647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return ret;
9747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
9847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
9947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic int socket_new(BIO* b) {
10047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  b->shutdown = 0;
10147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  b->init = 1;
10247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  b->num = 0; // 1 means socket closed
10347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  b->ptr = 0;
10447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return 1;
10547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
10647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
10747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic int socket_free(BIO* b) {
10847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (b == NULL)
10947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 0;
11047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return 1;
11147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
11247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
11347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic int socket_read(BIO* b, char* out, int outl) {
11447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!out)
11547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return -1;
11647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  rtc::AsyncSocket* socket = static_cast<rtc::AsyncSocket*>(b->ptr);
11747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  BIO_clear_retry_flags(b);
11847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int result = socket->Recv(out, outl);
11947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (result > 0) {
12047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return result;
12147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else if (result == 0) {
12247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    b->num = 1;
12347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else if (socket->IsBlocking()) {
12447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    BIO_set_retry_read(b);
12547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
12647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return -1;
12747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
12847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
12947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic int socket_write(BIO* b, const char* in, int inl) {
13047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!in)
13147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return -1;
13247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  rtc::AsyncSocket* socket = static_cast<rtc::AsyncSocket*>(b->ptr);
13347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  BIO_clear_retry_flags(b);
13447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int result = socket->Send(in, inl);
13547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (result > 0) {
13647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return result;
13747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else if (socket->IsBlocking()) {
13847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    BIO_set_retry_write(b);
13947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
14047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return -1;
14147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
14247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
14347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic int socket_puts(BIO* b, const char* str) {
14447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return socket_write(b, str, strlen(str));
14547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
14647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
14747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic long socket_ctrl(BIO* b, int cmd, long num, void* ptr) {
1485199d1ddc1a2d8bb9feeadc5bc684f8a1fd6b76bhenrike@webrtc.org  RTC_UNUSED(num);
1495199d1ddc1a2d8bb9feeadc5bc684f8a1fd6b76bhenrike@webrtc.org  RTC_UNUSED(ptr);
15047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
15147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  switch (cmd) {
15247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  case BIO_CTRL_RESET:
15347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 0;
15447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  case BIO_CTRL_EOF:
15547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return b->num;
15647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  case BIO_CTRL_WPENDING:
15747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  case BIO_CTRL_PENDING:
15847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 0;
15947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  case BIO_CTRL_FLUSH:
16047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 1;
16147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  default:
16247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 0;
16347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
16447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
16547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
16647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/////////////////////////////////////////////////////////////////////////////
16747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// OpenSSLAdapter
16847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/////////////////////////////////////////////////////////////////////////////
16947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
17047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgnamespace rtc {
17147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
17247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// This array will store all of the mutexes available to OpenSSL.
17347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic MUTEX_TYPE* mutex_buf = NULL;
17447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
17547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic void locking_function(int mode, int n, const char * file, int line) {
17647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (mode & CRYPTO_LOCK) {
17747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    MUTEX_LOCK(mutex_buf[n]);
17847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else {
17947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    MUTEX_UNLOCK(mutex_buf[n]);
18047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
18147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
18247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
18347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic unsigned long id_function() {  // NOLINT
18447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Use old-style C cast because THREAD_ID's type varies with the platform,
18547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // in some cases requiring static_cast, and in others requiring
18647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // reinterpret_cast.
18747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return (unsigned long)THREAD_ID; // NOLINT
18847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
18947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
19047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic CRYPTO_dynlock_value* dyn_create_function(const char* file, int line) {
19147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  CRYPTO_dynlock_value* value = new CRYPTO_dynlock_value;
19247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!value)
19347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return NULL;
19447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  MUTEX_SETUP(value->mutex);
19547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return value;
19647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
19747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
19847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic void dyn_lock_function(int mode, CRYPTO_dynlock_value* l,
19947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                              const char* file, int line) {
20047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (mode & CRYPTO_LOCK) {
20147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    MUTEX_LOCK(l->mutex);
20247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else {
20347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    MUTEX_UNLOCK(l->mutex);
20447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
20547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
20647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
20747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic void dyn_destroy_function(CRYPTO_dynlock_value* l,
20847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                 const char* file, int line) {
20947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  MUTEX_CLEANUP(l->mutex);
21047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  delete l;
21147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
21247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
21347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgVerificationCallback OpenSSLAdapter::custom_verify_callback_ = NULL;
21447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
21547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool OpenSSLAdapter::InitializeSSL(VerificationCallback callback) {
21647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!InitializeSSLThread() || !SSL_library_init())
21747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return false;
21847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if !defined(ADDRESS_SANITIZER) || !defined(WEBRTC_MAC) || defined(WEBRTC_IOS)
21947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Loading the error strings crashes mac_asan.  Omit this debugging aid there.
22047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SSL_load_error_strings();
22147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
22247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ERR_load_BIO_strings();
22347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  OpenSSL_add_all_algorithms();
22447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  RAND_poll();
22547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  custom_verify_callback_ = callback;
22647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
22747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
22847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
22947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool OpenSSLAdapter::InitializeSSLThread() {
23047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  mutex_buf = new MUTEX_TYPE[CRYPTO_num_locks()];
23147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!mutex_buf)
23247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
23347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  for (int i = 0; i < CRYPTO_num_locks(); ++i)
23447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    MUTEX_SETUP(mutex_buf[i]);
23547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
23647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // we need to cast our id_function to return an unsigned long -- pthread_t is
23747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // a pointer
23847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  CRYPTO_set_id_callback(id_function);
23947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  CRYPTO_set_locking_callback(locking_function);
24047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  CRYPTO_set_dynlock_create_callback(dyn_create_function);
24147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  CRYPTO_set_dynlock_lock_callback(dyn_lock_function);
24247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function);
24347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
24447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
24547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
24647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool OpenSSLAdapter::CleanupSSL() {
24747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!mutex_buf)
24847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
24947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  CRYPTO_set_id_callback(NULL);
25047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  CRYPTO_set_locking_callback(NULL);
25147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  CRYPTO_set_dynlock_create_callback(NULL);
25247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  CRYPTO_set_dynlock_lock_callback(NULL);
25347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  CRYPTO_set_dynlock_destroy_callback(NULL);
25447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  for (int i = 0; i < CRYPTO_num_locks(); ++i)
25547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    MUTEX_CLEANUP(mutex_buf[i]);
25647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  delete [] mutex_buf;
25747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  mutex_buf = NULL;
25847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
25947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
26047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
26147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgOpenSSLAdapter::OpenSSLAdapter(AsyncSocket* socket)
26247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  : SSLAdapter(socket),
26347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    state_(SSL_NONE),
26447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ssl_read_needs_write_(false),
26547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ssl_write_needs_read_(false),
26647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    restartable_(false),
26747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ssl_(NULL), ssl_ctx_(NULL),
26847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    custom_verification_succeeded_(false) {
26947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
27047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
27147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgOpenSSLAdapter::~OpenSSLAdapter() {
27247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  Cleanup();
27347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
27447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
27547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint
27647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgOpenSSLAdapter::StartSSL(const char* hostname, bool restartable) {
27747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (state_ != SSL_NONE)
27847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return -1;
27947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
28047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ssl_host_name_ = hostname;
28147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  restartable_ = restartable;
28247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
28347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (socket_->GetState() != Socket::CS_CONNECTED) {
28447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    state_ = SSL_WAIT;
28547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 0;
28647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
28747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
28847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  state_ = SSL_CONNECTING;
28947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (int err = BeginSSL()) {
29047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    Error("BeginSSL", err, false);
29147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return err;
29247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
29347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
29447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return 0;
29547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
29647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
29747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint
29847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgOpenSSLAdapter::BeginSSL() {
29947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  LOG(LS_INFO) << "BeginSSL: " << ssl_host_name_;
30047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ASSERT(state_ == SSL_CONNECTING);
30147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
30247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int err = 0;
30347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  BIO* bio = NULL;
30447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
30547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // First set up the context
30647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!ssl_ctx_)
30747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ssl_ctx_ = SetupSSLContext();
30847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
30947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!ssl_ctx_) {
31047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    err = -1;
31147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    goto ssl_error;
31247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
31347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
31447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  bio = BIO_new_socket(static_cast<AsyncSocketAdapter*>(socket_));
31547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!bio) {
31647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    err = -1;
31747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    goto ssl_error;
31847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
31947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
32047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ssl_ = SSL_new(ssl_ctx_);
32147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!ssl_) {
32247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    err = -1;
32347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    goto ssl_error;
32447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
32547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
32647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SSL_set_app_data(ssl_, this);
32747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
32847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SSL_set_bio(ssl_, bio, bio);
32947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SSL_set_mode(ssl_, SSL_MODE_ENABLE_PARTIAL_WRITE |
33047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                     SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
33147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
33247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // the SSL object owns the bio now
33347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  bio = NULL;
33447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
33547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Do the connect
33647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  err = ContinueSSL();
33747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (err != 0)
33847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    goto ssl_error;
33947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
34047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return err;
34147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
34247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgssl_error:
34347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  Cleanup();
34447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (bio)
34547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    BIO_free(bio);
34647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
34747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return err;
34847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
34947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
35047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint
35147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgOpenSSLAdapter::ContinueSSL() {
35247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ASSERT(state_ == SSL_CONNECTING);
35347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
35447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int code = SSL_connect(ssl_);
35547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  switch (SSL_get_error(ssl_, code)) {
35647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  case SSL_ERROR_NONE:
35747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (!SSLPostConnectionCheck(ssl_, ssl_host_name_.c_str())) {
35847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      LOG(LS_ERROR) << "TLS post connection check failed";
35947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // make sure we close the socket
36047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      Cleanup();
36147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // The connect failed so return -1 to shut down the socket
36247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return -1;
36347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
36447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
36547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    state_ = SSL_CONNECTED;
36647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    AsyncSocketAdapter::OnConnectEvent(this);
36747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if 0  // TODO: worry about this
36847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // Don't let ourselves go away during the callbacks
36947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    PRefPtr<OpenSSLAdapter> lock(this);
37047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG(LS_INFO) << " -- onStreamReadable";
37147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    AsyncSocketAdapter::OnReadEvent(this);
37247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG(LS_INFO) << " -- onStreamWriteable";
37347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    AsyncSocketAdapter::OnWriteEvent(this);
37447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
37547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    break;
37647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
37747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  case SSL_ERROR_WANT_READ:
37847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  case SSL_ERROR_WANT_WRITE:
37947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    break;
38047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
38147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  case SSL_ERROR_ZERO_RETURN:
38247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  default:
38347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG(LS_WARNING) << "ContinueSSL -- error " << code;
38447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return (code != 0) ? code : -1;
38547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
38647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
38747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return 0;
38847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
38947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
39047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid
39147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgOpenSSLAdapter::Error(const char* context, int err, bool signal) {
39247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  LOG(LS_WARNING) << "OpenSSLAdapter::Error("
39347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                  << context << ", " << err << ")";
39447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  state_ = SSL_ERROR;
39547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SetError(err);
39647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (signal)
39747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    AsyncSocketAdapter::OnCloseEvent(this, err);
39847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
39947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
40047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid
40147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgOpenSSLAdapter::Cleanup() {
40247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  LOG(LS_INFO) << "Cleanup";
40347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
40447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  state_ = SSL_NONE;
40547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ssl_read_needs_write_ = false;
40647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ssl_write_needs_read_ = false;
40747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  custom_verification_succeeded_ = false;
40847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
40947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (ssl_) {
41047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    SSL_free(ssl_);
41147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ssl_ = NULL;
41247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
41347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
41447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (ssl_ctx_) {
41547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    SSL_CTX_free(ssl_ctx_);
41647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ssl_ctx_ = NULL;
41747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
41847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
41947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
42047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//
42147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// AsyncSocket Implementation
42247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org//
42347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
42447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint
42547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgOpenSSLAdapter::Send(const void* pv, size_t cb) {
42647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  //LOG(LS_INFO) << "OpenSSLAdapter::Send(" << cb << ")";
42747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
42847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  switch (state_) {
42947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  case SSL_NONE:
43047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return AsyncSocketAdapter::Send(pv, cb);
43147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
43247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  case SSL_WAIT:
43347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  case SSL_CONNECTING:
43447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    SetError(EWOULDBLOCK);
43547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return SOCKET_ERROR;
43647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
43747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  case SSL_CONNECTED:
43847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    break;
43947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
44047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  case SSL_ERROR:
44147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  default:
44247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return SOCKET_ERROR;
44347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
44447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
44547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // OpenSSL will return an error if we try to write zero bytes
44647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (cb == 0)
44747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 0;
44847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
44947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ssl_write_needs_read_ = false;
45047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
45147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int code = SSL_write(ssl_, pv, cb);
45247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  switch (SSL_get_error(ssl_, code)) {
45347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  case SSL_ERROR_NONE:
45447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    //LOG(LS_INFO) << " -- success";
45547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return code;
45647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  case SSL_ERROR_WANT_READ:
45747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    //LOG(LS_INFO) << " -- error want read";
45847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ssl_write_needs_read_ = true;
45947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    SetError(EWOULDBLOCK);
46047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    break;
46147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  case SSL_ERROR_WANT_WRITE:
46247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    //LOG(LS_INFO) << " -- error want write";
46347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    SetError(EWOULDBLOCK);
46447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    break;
46547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  case SSL_ERROR_ZERO_RETURN:
46647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    //LOG(LS_INFO) << " -- remote side closed";
46747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    SetError(EWOULDBLOCK);
46847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // do we need to signal closure?
46947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    break;
47047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  default:
47147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    //LOG(LS_INFO) << " -- error " << code;
47247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    Error("SSL_write", (code ? code : -1), false);
47347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    break;
47447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
47547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
47647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return SOCKET_ERROR;
47747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
47847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
47947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint
48047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgOpenSSLAdapter::Recv(void* pv, size_t cb) {
48147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  //LOG(LS_INFO) << "OpenSSLAdapter::Recv(" << cb << ")";
48247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  switch (state_) {
48347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
48447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  case SSL_NONE:
48547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return AsyncSocketAdapter::Recv(pv, cb);
48647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
48747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  case SSL_WAIT:
48847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  case SSL_CONNECTING:
48947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    SetError(EWOULDBLOCK);
49047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return SOCKET_ERROR;
49147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
49247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  case SSL_CONNECTED:
49347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    break;
49447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
49547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  case SSL_ERROR:
49647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  default:
49747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return SOCKET_ERROR;
49847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
49947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
50047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Don't trust OpenSSL with zero byte reads
50147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (cb == 0)
50247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return 0;
50347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
50447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ssl_read_needs_write_ = false;
50547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
50647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int code = SSL_read(ssl_, pv, cb);
50747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  switch (SSL_get_error(ssl_, code)) {
50847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  case SSL_ERROR_NONE:
50947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    //LOG(LS_INFO) << " -- success";
51047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return code;
51147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  case SSL_ERROR_WANT_READ:
51247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    //LOG(LS_INFO) << " -- error want read";
51347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    SetError(EWOULDBLOCK);
51447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    break;
51547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  case SSL_ERROR_WANT_WRITE:
51647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    //LOG(LS_INFO) << " -- error want write";
51747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ssl_read_needs_write_ = true;
51847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    SetError(EWOULDBLOCK);
51947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    break;
52047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  case SSL_ERROR_ZERO_RETURN:
52147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    //LOG(LS_INFO) << " -- remote side closed";
52247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    SetError(EWOULDBLOCK);
52347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // do we need to signal closure?
52447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    break;
52547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  default:
52647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    //LOG(LS_INFO) << " -- error " << code;
52747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    Error("SSL_read", (code ? code : -1), false);
52847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    break;
52947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
53047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
53147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return SOCKET_ERROR;
53247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
53347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
53447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint
53547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgOpenSSLAdapter::Close() {
53647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  Cleanup();
53747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  state_ = restartable_ ? SSL_WAIT : SSL_NONE;
53847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return AsyncSocketAdapter::Close();
53947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
54047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
54147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSocket::ConnState
54247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgOpenSSLAdapter::GetState() const {
54347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  //if (signal_close_)
54447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  //  return CS_CONNECTED;
54547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ConnState state = socket_->GetState();
54647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if ((state == CS_CONNECTED)
54747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      && ((state_ == SSL_WAIT) || (state_ == SSL_CONNECTING)))
54847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    state = CS_CONNECTING;
54947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return state;
55047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
55147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
55247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid
55347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgOpenSSLAdapter::OnConnectEvent(AsyncSocket* socket) {
55447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  LOG(LS_INFO) << "OpenSSLAdapter::OnConnectEvent";
55547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (state_ != SSL_WAIT) {
55647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ASSERT(state_ == SSL_NONE);
55747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    AsyncSocketAdapter::OnConnectEvent(socket);
55847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return;
55947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
56047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
56147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  state_ = SSL_CONNECTING;
56247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (int err = BeginSSL()) {
56347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    AsyncSocketAdapter::OnCloseEvent(socket, err);
56447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
56547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
56647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
56747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid
56847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgOpenSSLAdapter::OnReadEvent(AsyncSocket* socket) {
56947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  //LOG(LS_INFO) << "OpenSSLAdapter::OnReadEvent";
57047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
57147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (state_ == SSL_NONE) {
57247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    AsyncSocketAdapter::OnReadEvent(socket);
57347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return;
57447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
57547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
57647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (state_ == SSL_CONNECTING) {
57747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (int err = ContinueSSL()) {
57847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      Error("ContinueSSL", err);
57947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
58047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return;
58147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
58247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
58347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (state_ != SSL_CONNECTED)
58447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return;
58547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
58647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Don't let ourselves go away during the callbacks
58747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  //PRefPtr<OpenSSLAdapter> lock(this); // TODO: fix this
58847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (ssl_write_needs_read_)  {
58947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    //LOG(LS_INFO) << " -- onStreamWriteable";
59047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    AsyncSocketAdapter::OnWriteEvent(socket);
59147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
59247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
59347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  //LOG(LS_INFO) << " -- onStreamReadable";
59447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  AsyncSocketAdapter::OnReadEvent(socket);
59547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
59647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
59747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid
59847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgOpenSSLAdapter::OnWriteEvent(AsyncSocket* socket) {
59947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  //LOG(LS_INFO) << "OpenSSLAdapter::OnWriteEvent";
60047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
60147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (state_ == SSL_NONE) {
60247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    AsyncSocketAdapter::OnWriteEvent(socket);
60347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return;
60447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
60547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
60647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (state_ == SSL_CONNECTING) {
60747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (int err = ContinueSSL()) {
60847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      Error("ContinueSSL", err);
60947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
61047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return;
61147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
61247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
61347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (state_ != SSL_CONNECTED)
61447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return;
61547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
61647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Don't let ourselves go away during the callbacks
61747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  //PRefPtr<OpenSSLAdapter> lock(this); // TODO: fix this
61847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
61947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (ssl_read_needs_write_)  {
62047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    //LOG(LS_INFO) << " -- onStreamReadable";
62147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    AsyncSocketAdapter::OnReadEvent(socket);
62247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
62347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
62447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  //LOG(LS_INFO) << " -- onStreamWriteable";
62547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  AsyncSocketAdapter::OnWriteEvent(socket);
62647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
62747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
62847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid
62947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgOpenSSLAdapter::OnCloseEvent(AsyncSocket* socket, int err) {
63047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  LOG(LS_INFO) << "OpenSSLAdapter::OnCloseEvent(" << err << ")";
63147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  AsyncSocketAdapter::OnCloseEvent(socket, err);
63247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
63347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
63447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// This code is taken from the "Network Security with OpenSSL"
63547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// sample in chapter 5
63647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
63747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool OpenSSLAdapter::VerifyServerName(SSL* ssl, const char* host,
63847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                      bool ignore_bad_cert) {
63947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!host)
64047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
64147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
64247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Checking the return from SSL_get_peer_certificate here is not strictly
64347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // necessary.  With our setup, it is not possible for it to return
64447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // NULL.  However, it is good form to check the return.
64547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  X509* certificate = SSL_get_peer_certificate(ssl);
64647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!certificate)
64747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
64847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
64947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Logging certificates is extremely verbose. So it is disabled by default.
65047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#ifdef LOG_CERTIFICATES
65147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  {
65247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG(LS_INFO) << "Certificate from server:";
65347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    BIO* mem = BIO_new(BIO_s_mem());
65447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    X509_print_ex(mem, certificate, XN_FLAG_SEP_CPLUS_SPC, X509_FLAG_NO_HEADER);
65547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    BIO_write(mem, "\0", 1);
65647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    char* buffer;
65747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    BIO_get_mem_data(mem, &buffer);
65847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG(LS_INFO) << buffer;
65947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    BIO_free(mem);
66047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
66147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    char* cipher_description =
66247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      SSL_CIPHER_description(SSL_get_current_cipher(ssl), NULL, 128);
66347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG(LS_INFO) << "Cipher: " << cipher_description;
66447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    OPENSSL_free(cipher_description);
66547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
66647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
66747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
66847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  bool ok = false;
66947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int extension_count = X509_get_ext_count(certificate);
67047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  for (int i = 0; i < extension_count; ++i) {
67147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    X509_EXTENSION* extension = X509_get_ext(certificate, i);
67247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int extension_nid = OBJ_obj2nid(X509_EXTENSION_get_object(extension));
67347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
67447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (extension_nid == NID_subject_alt_name) {
67547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      const X509V3_EXT_METHOD* meth = X509V3_EXT_get(extension);
67647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (!meth)
67747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        break;
67847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
67947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      void* ext_str = NULL;
68047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
68147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // We assign this to a local variable, instead of passing the address
68247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // directly to ASN1_item_d2i.
68347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // See http://readlist.com/lists/openssl.org/openssl-users/0/4761.html.
68447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      unsigned char* ext_value_data = extension->value->data;
68547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
68647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      const unsigned char **ext_value_data_ptr =
68747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          (const_cast<const unsigned char **>(&ext_value_data));
68847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
68947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (meth->it) {
69047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        ext_str = ASN1_item_d2i(NULL, ext_value_data_ptr,
69147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                extension->value->length,
69247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                ASN1_ITEM_ptr(meth->it));
69347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      } else {
69447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        ext_str = meth->d2i(NULL, ext_value_data_ptr, extension->value->length);
69547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
69647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
69747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      STACK_OF(CONF_VALUE)* value = meth->i2v(meth, ext_str, NULL);
698d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.org
699d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.org      // Cast to size_t to be compilable for both OpenSSL and BoringSSL.
700d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.org      for (size_t j = 0; j < static_cast<size_t>(sk_CONF_VALUE_num(value));
701d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.org           ++j) {
70247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        CONF_VALUE* nval = sk_CONF_VALUE_value(value, j);
70347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        // The value for nval can contain wildcards
70447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        if (!strcmp(nval->name, "DNS") && string_match(host, nval->value)) {
70547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          ok = true;
70647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          break;
70747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        }
70847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
70947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      sk_CONF_VALUE_pop_free(value, X509V3_conf_free);
71047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      value = NULL;
71147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
71247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (meth->it) {
71347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        ASN1_item_free(reinterpret_cast<ASN1_VALUE*>(ext_str),
71447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                       ASN1_ITEM_ptr(meth->it));
71547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      } else {
71647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        meth->ext_free(ext_str);
71747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
71847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      ext_str = NULL;
71947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
72047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (ok)
72147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      break;
72247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
72347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
72447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  char data[256];
725222d84ad848886a7123d3ad47c4daf188ecac574henrike@webrtc.org  X509_NAME* subject;
72647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!ok
72747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      && ((subject = X509_get_subject_name(certificate)) != NULL)
72847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      && (X509_NAME_get_text_by_NID(subject, NID_commonName,
72947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                    data, sizeof(data)) > 0)) {
73047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    data[sizeof(data)-1] = 0;
73147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (_stricmp(data, host) == 0)
73247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      ok = true;
73347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
73447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
73547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  X509_free(certificate);
73647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
73747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // This should only ever be turned on for debugging and development.
73847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!ok && ignore_bad_cert) {
73947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG(LS_WARNING) << "TLS certificate check FAILED.  "
74047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      << "Allowing connection anyway.";
74147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ok = true;
74247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
74347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
74447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return ok;
74547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
74647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
74747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool OpenSSLAdapter::SSLPostConnectionCheck(SSL* ssl, const char* host) {
74847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  bool ok = VerifyServerName(ssl, host, ignore_bad_cert());
74947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
75047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (ok) {
75147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ok = (SSL_get_verify_result(ssl) == X509_V_OK ||
75247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          custom_verification_succeeded_);
75347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
75447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
75547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!ok && ignore_bad_cert()) {
75647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG(LS_INFO) << "Other TLS post connection checks failed.";
75747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ok = true;
75847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
75947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
76047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return ok;
76147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
76247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
76347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if _DEBUG
76447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
76547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// We only use this for tracing and so it is only needed in debug mode
76647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
76747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid
76847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgOpenSSLAdapter::SSLInfoCallback(const SSL* s, int where, int ret) {
76947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  const char* str = "undefined";
77047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int w = where & ~SSL_ST_MASK;
77147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (w & SSL_ST_CONNECT) {
77247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    str = "SSL_connect";
77347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else if (w & SSL_ST_ACCEPT) {
77447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    str = "SSL_accept";
77547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
77647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (where & SSL_CB_LOOP) {
77747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG(LS_INFO) <<  str << ":" << SSL_state_string_long(s);
77847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else if (where & SSL_CB_ALERT) {
77947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    str = (where & SSL_CB_READ) ? "read" : "write";
78047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG(LS_INFO) <<  "SSL3 alert " << str
78147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      << ":" << SSL_alert_type_string_long(ret)
78247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      << ":" << SSL_alert_desc_string_long(ret);
78347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else if (where & SSL_CB_EXIT) {
78447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (ret == 0) {
78547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      LOG(LS_INFO) << str << ":failed in " << SSL_state_string_long(s);
78647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else if (ret < 0) {
78747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      LOG(LS_INFO) << str << ":error in " << SSL_state_string_long(s);
78847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
78947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
79047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
79147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
79247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif  // _DEBUG
79347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
79447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint
79547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgOpenSSLAdapter::SSLVerifyCallback(int ok, X509_STORE_CTX* store) {
79647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if _DEBUG
79747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!ok) {
79847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    char data[256];
79947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    X509* cert = X509_STORE_CTX_get_current_cert(store);
80047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int depth = X509_STORE_CTX_get_error_depth(store);
80147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int err = X509_STORE_CTX_get_error(store);
80247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
80347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG(LS_INFO) << "Error with certificate at depth: " << depth;
80447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof(data));
80547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG(LS_INFO) << "  issuer  = " << data;
80647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof(data));
80747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG(LS_INFO) << "  subject = " << data;
80847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG(LS_INFO) << "  err     = " << err
80947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      << ":" << X509_verify_cert_error_string(err);
81047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
81147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
81247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
81347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Get our stream pointer from the store
81447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SSL* ssl = reinterpret_cast<SSL*>(
81547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                X509_STORE_CTX_get_ex_data(store,
81647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                  SSL_get_ex_data_X509_STORE_CTX_idx()));
81747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
81847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  OpenSSLAdapter* stream =
81947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    reinterpret_cast<OpenSSLAdapter*>(SSL_get_app_data(ssl));
82047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
82147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!ok && custom_verify_callback_) {
82247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    void* cert =
82347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        reinterpret_cast<void*>(X509_STORE_CTX_get_current_cert(store));
82447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (custom_verify_callback_(cert)) {
82547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      stream->custom_verification_succeeded_ = true;
82647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      LOG(LS_INFO) << "validated certificate using custom callback";
82747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      ok = true;
82847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
82947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
83047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
83147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Should only be used for debugging and development.
83247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!ok && stream->ignore_bad_cert()) {
83347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG(LS_WARNING) << "Ignoring cert error while verifying cert chain";
83447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ok = 1;
83547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
83647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
83747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return ok;
83847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
83947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
84047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool OpenSSLAdapter::ConfigureTrustedRootCertificates(SSL_CTX* ctx) {
84147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Add the root cert that we care about to the SSL context
84247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int count_of_added_certs = 0;
84347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  for (int i = 0; i < ARRAY_SIZE(kSSLCertCertificateList); i++) {
84447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    const unsigned char* cert_buffer = kSSLCertCertificateList[i];
84547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    size_t cert_buffer_len = kSSLCertCertificateSizeList[i];
84647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    X509* cert = d2i_X509(NULL, &cert_buffer, cert_buffer_len);
84747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (cert) {
84847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      int return_value = X509_STORE_add_cert(SSL_CTX_get_cert_store(ctx), cert);
84947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (return_value == 0) {
85047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        LOG(LS_WARNING) << "Unable to add certificate.";
85147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      } else {
85247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        count_of_added_certs++;
85347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
85447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      X509_free(cert);
85547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
85647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
85747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return count_of_added_certs > 0;
85847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
85947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
86047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSSL_CTX*
86147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgOpenSSLAdapter::SetupSSLContext() {
86247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SSL_CTX* ctx = SSL_CTX_new(TLSv1_client_method());
86347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (ctx == NULL) {
86447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    unsigned long error = ERR_get_error();  // NOLINT: type used by OpenSSL.
86547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG(LS_WARNING) << "SSL_CTX creation failed: "
86647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                    << '"' << ERR_reason_error_string(error) << "\" "
86747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                    << "(error=" << error << ')';
86847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return NULL;
86947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
87047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!ConfigureTrustedRootCertificates(ctx)) {
87147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    SSL_CTX_free(ctx);
87247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return NULL;
87347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
87447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
87547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#ifdef _DEBUG
87647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SSL_CTX_set_info_callback(ctx, SSLInfoCallback);
87747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
87847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
87947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, SSLVerifyCallback);
88047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SSL_CTX_set_verify_depth(ctx, 4);
88147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SSL_CTX_set_cipher_list(ctx, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
88247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
88347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return ctx;
88447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
88547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
88647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} // namespace rtc
88747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
88847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif  // HAVE_OPENSSL_SSL_H
889