1f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if HAVE_CONFIG_H
2f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "config.h"
3f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif  // HAVE_CONFIG_H
4f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
5f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if HAVE_OPENSSL_SSL_H
6f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
7f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <openssl/bio.h>
8f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <openssl/crypto.h>
9f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <openssl/err.h>
103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include <openssl/opensslv.h>
11f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <openssl/rand.h>
12f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <openssl/ssl.h>
13f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <openssl/x509v3.h>
14f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
15f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/common.h"
16f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/logging.h"
17f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/openssladapter.h"
18f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/stringutils.h"
19f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/Equifax_Secure_Global_eBusiness_CA-1.h"
20f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
21f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// TODO: Use a nicer abstraction for mutex.
22f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
23f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if defined(WIN32)
24f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  #define MUTEX_TYPE HANDLE
25f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  #define MUTEX_SETUP(x) (x) = CreateMutex(NULL, FALSE, NULL)
26f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  #define MUTEX_CLEANUP(x) CloseHandle(x)
27f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  #define MUTEX_LOCK(x) WaitForSingleObject((x), INFINITE)
28f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  #define MUTEX_UNLOCK(x) ReleaseMutex(x)
29f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  #define THREAD_ID GetCurrentThreadId()
30f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#elif defined(_POSIX_THREADS)
31f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // _POSIX_THREADS is normally defined in unistd.h if pthreads are available
32f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // on your platform.
33f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  #define MUTEX_TYPE pthread_mutex_t
34f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  #define MUTEX_SETUP(x) pthread_mutex_init(&(x), NULL)
35f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  #define MUTEX_CLEANUP(x) pthread_mutex_destroy(&(x))
36f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  #define MUTEX_LOCK(x) pthread_mutex_lock(&(x))
37f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  #define MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x))
38f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  #define THREAD_ID pthread_self()
39f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#else
40f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  #error You must define mutex operations appropriate for your platform!
41f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
42f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
43f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstruct CRYPTO_dynlock_value {
44f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  MUTEX_TYPE mutex;
45f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch};
46f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
47f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//////////////////////////////////////////////////////////////////////
48f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// SocketBIO
49f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//////////////////////////////////////////////////////////////////////
50f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
51f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic int socket_write(BIO* h, const char* buf, int num);
52f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic int socket_read(BIO* h, char* buf, int size);
53f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic int socket_puts(BIO* h, const char* str);
54f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic long socket_ctrl(BIO* h, int cmd, long arg1, void* arg2);
55f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic int socket_new(BIO* h);
56f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic int socket_free(BIO* data);
57f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
58f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic BIO_METHOD methods_socket = {
59f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	BIO_TYPE_BIO,
60f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	"socket",
61f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	socket_write,
62f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	socket_read,
63f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	socket_puts,
64f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	0,
65f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	socket_ctrl,
66f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	socket_new,
67f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	socket_free,
68f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	NULL,
69f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch};
70f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
71f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochBIO_METHOD* BIO_s_socket2() { return(&methods_socket); }
72f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
73f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochBIO* BIO_new_socket(talk_base::AsyncSocket* socket) {
74f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	BIO* ret = BIO_new(BIO_s_socket2());
75f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	if (ret == NULL) {
76f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          return NULL;
77f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	}
78f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	ret->ptr = socket;
79f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	return ret;
80f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
81f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
82f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic int socket_new(BIO* b) {
83f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	b->shutdown = 0;
84f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	b->init = 1;
85f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	b->num = 0; // 1 means socket closed
86f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	b->ptr = 0;
87f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	return 1;
88f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
89f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
90f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic int socket_free(BIO* b) {
91f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	if (b == NULL)
92f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch		return 0;
93f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	return 1;
94f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
95f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
96f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic int socket_read(BIO* b, char* out, int outl) {
97f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	if (!out)
98f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch		return -1;
99f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	talk_base::AsyncSocket* socket = static_cast<talk_base::AsyncSocket*>(b->ptr);
100f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	BIO_clear_retry_flags(b);
101f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int result = socket->Recv(out, outl);
102f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (result > 0) {
103f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return result;
104f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else if (result == 0) {
105f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch		b->num = 1;
106f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else if (socket->IsBlocking()) {
107f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch		BIO_set_retry_read(b);
108f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	}
109f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	return -1;
110f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
111f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
112f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic int socket_write(BIO* b, const char* in, int inl) {
113f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	if (!in)
114f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch		return -1;
115f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	talk_base::AsyncSocket* socket = static_cast<talk_base::AsyncSocket*>(b->ptr);
116f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	BIO_clear_retry_flags(b);
117f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int result = socket->Send(in, inl);
118f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (result > 0) {
119f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return result;
120f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else if (socket->IsBlocking()) {
121f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch		BIO_set_retry_write(b);
122f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	}
123f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	return -1;
124f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
125f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
126f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic int socket_puts(BIO* b, const char* str) {
127f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	return socket_write(b, str, strlen(str));
128f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
129f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
130f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic long socket_ctrl(BIO* b, int cmd, long num, void* ptr) {
131f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  UNUSED(num);
132f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  UNUSED(ptr);
133f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
134f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	switch (cmd) {
135f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	case BIO_CTRL_RESET:
136f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch		return 0;
137f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	case BIO_CTRL_EOF:
138f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch		return b->num;
139f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	case BIO_CTRL_WPENDING:
140f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	case BIO_CTRL_PENDING:
141f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch		return 0;
142f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	case BIO_CTRL_FLUSH:
143f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch		return 1;
144f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	default:
145f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch		return 0;
146f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch	}
147f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
148f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
149f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/////////////////////////////////////////////////////////////////////////////
150f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// OpenSSLAdapter
151f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/////////////////////////////////////////////////////////////////////////////
152f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
153f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochnamespace talk_base {
154f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
155f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// This array will store all of the mutexes available to OpenSSL.
156f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic MUTEX_TYPE* mutex_buf = NULL;
157f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
158f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic void locking_function(int mode, int n, const char * file, int line) {
159f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (mode & CRYPTO_LOCK) {
160f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    MUTEX_LOCK(mutex_buf[n]);
161f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else {
162f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    MUTEX_UNLOCK(mutex_buf[n]);
163f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
164f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
165f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
166f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic pthread_t id_function() {
167f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return THREAD_ID;
168f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
169f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
170f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic CRYPTO_dynlock_value* dyn_create_function(const char* file, int line) {
171f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  CRYPTO_dynlock_value* value = new CRYPTO_dynlock_value;
172f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!value)
173f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return NULL;
174f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  MUTEX_SETUP(value->mutex);
175f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return value;
176f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
177f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
178f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic void dyn_lock_function(int mode, CRYPTO_dynlock_value* l,
179f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                              const char* file, int line) {
180f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (mode & CRYPTO_LOCK) {
181f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    MUTEX_LOCK(l->mutex);
182f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else {
183f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    MUTEX_UNLOCK(l->mutex);
184f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
185f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
186f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
187f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstatic void dyn_destroy_function(CRYPTO_dynlock_value* l,
188f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                 const char* file, int line) {
189f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  MUTEX_CLEANUP(l->mutex);
190f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  delete l;
191f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
192f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
193f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochVerificationCallback OpenSSLAdapter::custom_verify_callback_ = NULL;
194f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
195f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool OpenSSLAdapter::InitializeSSL(VerificationCallback callback) {
196f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!InitializeSSLThread() || !SSL_library_init())
197f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  	  return false;
198f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SSL_load_error_strings();
199f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ERR_load_BIO_strings();
200f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  OpenSSL_add_all_algorithms();
201f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  RAND_poll();
202f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  custom_verify_callback_ = callback;
203f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
204f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
205f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
206f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool OpenSSLAdapter::InitializeSSLThread() {
207f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  mutex_buf = new MUTEX_TYPE[CRYPTO_num_locks()];
208f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!mutex_buf)
209f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
210f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  for (int i = 0; i < CRYPTO_num_locks(); ++i)
211f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    MUTEX_SETUP(mutex_buf[i]);
212f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
213f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // we need to cast our id_function to return an unsigned long -- pthread_t is a pointer
214f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  CRYPTO_set_id_callback((unsigned long (*)())id_function);
215f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  CRYPTO_set_locking_callback(locking_function);
216f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  CRYPTO_set_dynlock_create_callback(dyn_create_function);
217f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  CRYPTO_set_dynlock_lock_callback(dyn_lock_function);
218f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function);
219f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
220f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
221f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
222f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool OpenSSLAdapter::CleanupSSL() {
223f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!mutex_buf)
224f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
225f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  CRYPTO_set_id_callback(NULL);
226f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  CRYPTO_set_locking_callback(NULL);
227f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  CRYPTO_set_dynlock_create_callback(NULL);
228f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  CRYPTO_set_dynlock_lock_callback(NULL);
229f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  CRYPTO_set_dynlock_destroy_callback(NULL);
230f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  for (int i = 0; i < CRYPTO_num_locks(); ++i)
231f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    MUTEX_CLEANUP(mutex_buf[i]);
232f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  delete [] mutex_buf;
233f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  mutex_buf = NULL;
234f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
235f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
236f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
237f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochOpenSSLAdapter::OpenSSLAdapter(AsyncSocket* socket)
238f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  : SSLAdapter(socket),
239f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    state_(SSL_NONE),
240f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ssl_read_needs_write_(false),
241f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ssl_write_needs_read_(false),
242f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    restartable_(false),
243f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ssl_(NULL), ssl_ctx_(NULL),
244f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    custom_verification_succeeded_(false) {
245f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
246f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
247f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochOpenSSLAdapter::~OpenSSLAdapter() {
248f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  Cleanup();
249f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
250f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
251f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint
252f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochOpenSSLAdapter::StartSSL(const char* hostname, bool restartable) {
253f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (state_ != SSL_NONE)
254f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return -1;
255f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
256f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ssl_host_name_ = hostname;
257f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  restartable_ = restartable;
258f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
259f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (socket_->GetState() != Socket::CS_CONNECTED) {
260f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    state_ = SSL_WAIT;
261f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return 0;
262f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
263f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
264f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  state_ = SSL_CONNECTING;
265f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (int err = BeginSSL()) {
266f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    Error("BeginSSL", err, false);
267f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return err;
268f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
269f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
270f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return 0;
271f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
272f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
273f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint
274f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochOpenSSLAdapter::BeginSSL() {
275f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG(LS_INFO) << "BeginSSL: " << ssl_host_name_;
276f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(state_ == SSL_CONNECTING);
277f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
278f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int err = 0;
279f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  BIO* bio = NULL;
280f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
281f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // First set up the context
282f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!ssl_ctx_)
283f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ssl_ctx_ = SetupSSLContext();
284f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
285f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!ssl_ctx_) {
286f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    err = -1;
287f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    goto ssl_error;
288f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
289f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
290f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bio = BIO_new_socket(static_cast<AsyncSocketAdapter*>(socket_));
291f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!bio) {
292f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    err = -1;
293f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    goto ssl_error;
294f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
295f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
296f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ssl_ = SSL_new(ssl_ctx_);
297f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!ssl_) {
298f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    err = -1;
299f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    goto ssl_error;
300f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
301f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
302f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SSL_set_app_data(ssl_, this);
303f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
304f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SSL_set_bio(ssl_, bio, bio);
305f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SSL_set_mode(ssl_, SSL_MODE_ENABLE_PARTIAL_WRITE |
306f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                     SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
307f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
308f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // the SSL object owns the bio now
309f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bio = NULL;
310f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
311f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Do the connect
312f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  err = ContinueSSL();
313f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (err != 0)
314f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    goto ssl_error;
315f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
316f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return err;
317f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
318f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochssl_error:
319f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  Cleanup();
320f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (bio)
321f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    BIO_free(bio);
322f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
323f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return err;
324f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
325f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
326f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint
327f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochOpenSSLAdapter::ContinueSSL() {
328f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG(LS_INFO) << "ContinueSSL";
329f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(state_ == SSL_CONNECTING);
330f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
331f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int code = SSL_connect(ssl_);
332f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  switch (SSL_get_error(ssl_, code)) {
333f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case SSL_ERROR_NONE:
334f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_INFO) << " -- success";
335f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
336f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (!SSLPostConnectionCheck(ssl_, ssl_host_name_.c_str())) {
337f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      LOG(LS_ERROR) << "TLS post connection check failed";
338f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // make sure we close the socket
339f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      Cleanup();
340f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // The connect failed so return -1 to shut down the socket
341f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return -1;
342f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
343f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
344f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    state_ = SSL_CONNECTED;
345f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    AsyncSocketAdapter::OnConnectEvent(this);
346f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if 0  // TODO: worry about this
347f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // Don't let ourselves go away during the callbacks
348f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    PRefPtr<OpenSSLAdapter> lock(this);
349f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_INFO) << " -- onStreamReadable";
350f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    AsyncSocketAdapter::OnReadEvent(this);
351f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_INFO) << " -- onStreamWriteable";
352f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    AsyncSocketAdapter::OnWriteEvent(this);
353f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
354f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    break;
355f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
356f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case SSL_ERROR_WANT_READ:
357f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_INFO) << " -- error want read";
358f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    break;
359f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
360f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case SSL_ERROR_WANT_WRITE:
361f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_INFO) << " -- error want write";
362f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    break;
363f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
364f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case SSL_ERROR_ZERO_RETURN:
365f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  default:
366f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_INFO) << " -- error " << code;
367f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return (code != 0) ? code : -1;
368f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
369f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
370f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return 0;
371f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
372f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
373f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid
374f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochOpenSSLAdapter::Error(const char* context, int err, bool signal) {
375f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG(LS_WARNING) << "SChannelAdapter::Error("
376f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                  << context << ", " << err << ")";
377f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  state_ = SSL_ERROR;
378f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SetError(err);
379f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (signal)
380f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    AsyncSocketAdapter::OnCloseEvent(this, err);
381f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
382f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
383f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid
384f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochOpenSSLAdapter::Cleanup() {
385f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG(LS_INFO) << "Cleanup";
386f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
387f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  state_ = SSL_NONE;
388f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ssl_read_needs_write_ = false;
389f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ssl_write_needs_read_ = false;
390f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  custom_verification_succeeded_ = false;
391f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
392f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (ssl_) {
393f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SSL_free(ssl_);
394f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ssl_ = NULL;
395f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
396f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
397f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (ssl_ctx_) {
398f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SSL_CTX_free(ssl_ctx_);
399f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ssl_ctx_ = NULL;
400f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
401f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
402f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
403f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
404f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// AsyncSocket Implementation
405f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
406f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
407f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint
408f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochOpenSSLAdapter::Send(const void* pv, size_t cb) {
409f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  //LOG(LS_INFO) << "OpenSSLAdapter::Send(" << cb << ")";
410f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
411f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  switch (state_) {
412f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case SSL_NONE:
413f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return AsyncSocketAdapter::Send(pv, cb);
414f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
415f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case SSL_WAIT:
416f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case SSL_CONNECTING:
417f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SetError(EWOULDBLOCK);
418f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return SOCKET_ERROR;
419f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
420f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case SSL_CONNECTED:
421f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    break;
422f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
423f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case SSL_ERROR:
424f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  default:
425f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return SOCKET_ERROR;
426f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
427f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
428f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // OpenSSL will return an error if we try to write zero bytes
429f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (cb == 0)
430f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return 0;
431f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
432f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ssl_write_needs_read_ = false;
433f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
434f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int code = SSL_write(ssl_, pv, cb);
435f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  switch (SSL_get_error(ssl_, code)) {
436f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case SSL_ERROR_NONE:
437f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    //LOG(LS_INFO) << " -- success";
438f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return code;
439f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case SSL_ERROR_WANT_READ:
440f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    //LOG(LS_INFO) << " -- error want read";
441f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ssl_write_needs_read_ = true;
442f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SetError(EWOULDBLOCK);
443f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    break;
444f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case SSL_ERROR_WANT_WRITE:
445f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    //LOG(LS_INFO) << " -- error want write";
446f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SetError(EWOULDBLOCK);
447f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    break;
448f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case SSL_ERROR_ZERO_RETURN:
449f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    //LOG(LS_INFO) << " -- remote side closed";
450f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SetError(EWOULDBLOCK);
451f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // do we need to signal closure?
452f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    break;
453f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  default:
454f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    //LOG(LS_INFO) << " -- error " << code;
455f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    Error("SSL_write", (code ? code : -1), false);
456f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    break;
457f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
458f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
459f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return SOCKET_ERROR;
460f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
461f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
462f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint
463f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochOpenSSLAdapter::Recv(void* pv, size_t cb) {
464f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  //LOG(LS_INFO) << "OpenSSLAdapter::Recv(" << cb << ")";
465f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  switch (state_) {
466f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
467f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case SSL_NONE:
468f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return AsyncSocketAdapter::Recv(pv, cb);
469f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
470f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case SSL_WAIT:
471f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case SSL_CONNECTING:
472f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SetError(EWOULDBLOCK);
473f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return SOCKET_ERROR;
474f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
475f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case SSL_CONNECTED:
476f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    break;
477f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
478f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case SSL_ERROR:
479f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  default:
480f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return SOCKET_ERROR;
481f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
482f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
483f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Don't trust OpenSSL with zero byte reads
484f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (cb == 0)
485f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return 0;
486f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
487f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ssl_read_needs_write_ = false;
488f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
489f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int code = SSL_read(ssl_, pv, cb);
490f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  switch (SSL_get_error(ssl_, code)) {
491f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case SSL_ERROR_NONE:
492f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    //LOG(LS_INFO) << " -- success";
493f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return code;
494f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case SSL_ERROR_WANT_READ:
495f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    //LOG(LS_INFO) << " -- error want read";
496f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SetError(EWOULDBLOCK);
497f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    break;
498f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case SSL_ERROR_WANT_WRITE:
499f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    //LOG(LS_INFO) << " -- error want write";
500f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ssl_read_needs_write_ = true;
501f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SetError(EWOULDBLOCK);
502f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    break;
503f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  case SSL_ERROR_ZERO_RETURN:
504f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    //LOG(LS_INFO) << " -- remote side closed";
505f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SetError(EWOULDBLOCK);
506f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // do we need to signal closure?
507f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    break;
508f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  default:
509f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    //LOG(LS_INFO) << " -- error " << code;
510f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    Error("SSL_read", (code ? code : -1), false);
511f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    break;
512f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
513f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
514f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return SOCKET_ERROR;
515f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
516f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
517f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint
518f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochOpenSSLAdapter::Close() {
519f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  Cleanup();
520f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  state_ = restartable_ ? SSL_WAIT : SSL_NONE;
521f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return AsyncSocketAdapter::Close();
522f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
523f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
524f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochSocket::ConnState
525f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochOpenSSLAdapter::GetState() const {
526f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  //if (signal_close_)
527f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  //  return CS_CONNECTED;
528f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ConnState state = socket_->GetState();
529f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if ((state == CS_CONNECTED)
530f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      && ((state_ == SSL_WAIT) || (state_ == SSL_CONNECTING)))
531f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    state = CS_CONNECTING;
532f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return state;
533f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
534f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
535f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid
536f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochOpenSSLAdapter::OnConnectEvent(AsyncSocket* socket) {
537f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG(LS_INFO) << "OpenSSLAdapter::OnConnectEvent";
538f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (state_ != SSL_WAIT) {
539f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ASSERT(state_ == SSL_NONE);
540f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    AsyncSocketAdapter::OnConnectEvent(socket);
541f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return;
542f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
543f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
544f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  state_ = SSL_CONNECTING;
545f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (int err = BeginSSL()) {
546f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    AsyncSocketAdapter::OnCloseEvent(socket, err);
547f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
548f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
549f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
550f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid
551f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochOpenSSLAdapter::OnReadEvent(AsyncSocket* socket) {
552f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  //LOG(LS_INFO) << "OpenSSLAdapter::OnReadEvent";
553f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
554f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (state_ == SSL_NONE) {
555f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    AsyncSocketAdapter::OnReadEvent(socket);
556f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return;
557f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
558f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
559f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (state_ == SSL_CONNECTING) {
560f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (int err = ContinueSSL()) {
561f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      Error("ContinueSSL", err);
562f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
563f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return;
564f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
565f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
566f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (state_ != SSL_CONNECTED)
567f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return;
568f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
569f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Don't let ourselves go away during the callbacks
570f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  //PRefPtr<OpenSSLAdapter> lock(this); // TODO: fix this
571f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (ssl_write_needs_read_)  {
572f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    //LOG(LS_INFO) << " -- onStreamWriteable";
573f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    AsyncSocketAdapter::OnWriteEvent(socket);
574f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
575f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
576f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  //LOG(LS_INFO) << " -- onStreamReadable";
577f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  AsyncSocketAdapter::OnReadEvent(socket);
578f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
579f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
580f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid
581f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochOpenSSLAdapter::OnWriteEvent(AsyncSocket* socket) {
582f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  //LOG(LS_INFO) << "OpenSSLAdapter::OnWriteEvent";
583f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
584f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (state_ == SSL_NONE) {
585f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    AsyncSocketAdapter::OnWriteEvent(socket);
586f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return;
587f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
588f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
589f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (state_ == SSL_CONNECTING) {
590f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (int err = ContinueSSL()) {
591f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      Error("ContinueSSL", err);
592f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
593f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return;
594f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
595f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
596f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (state_ != SSL_CONNECTED)
597f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return;
598f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
599f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Don't let ourselves go away during the callbacks
600f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  //PRefPtr<OpenSSLAdapter> lock(this); // TODO: fix this
601f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
602f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (ssl_read_needs_write_)  {
603f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    //LOG(LS_INFO) << " -- onStreamReadable";
604f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    AsyncSocketAdapter::OnReadEvent(socket);
605f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
606f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
607f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  //LOG(LS_INFO) << " -- onStreamWriteable";
608f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  AsyncSocketAdapter::OnWriteEvent(socket);
609f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
610f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
611f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid
612f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochOpenSSLAdapter::OnCloseEvent(AsyncSocket* socket, int err) {
613f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG(LS_INFO) << "OpenSSLAdapter::OnCloseEvent(" << err << ")";
614f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  AsyncSocketAdapter::OnCloseEvent(socket, err);
615f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
616f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
617f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// This code is taken from the "Network Security with OpenSSL"
618f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// sample in chapter 5
619f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
620f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool OpenSSLAdapter::VerifyServerName(SSL* ssl, const char* host,
621f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                      bool ignore_bad_cert) {
622f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!host)
623f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
624f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
625f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Checking the return from SSL_get_peer_certificate here is not strictly
626f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // necessary.  With our setup, it is not possible for it to return
627f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // NULL.  However, it is good form to check the return.
628f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  X509* certificate = SSL_get_peer_certificate(ssl);
629f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!certificate)
630f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
631f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
632f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef _DEBUG
633f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  {
634f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_INFO) << "Certificate from server:";
635f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    BIO* mem = BIO_new(BIO_s_mem());
636f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    X509_print_ex(mem, certificate, XN_FLAG_SEP_CPLUS_SPC, X509_FLAG_NO_HEADER);
637f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    BIO_write(mem, "\0", 1);
638f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    char* buffer;
639f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    BIO_get_mem_data(mem, &buffer);
640f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_INFO) << buffer;
641f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    BIO_free(mem);
642f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
643f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    char* cipher_description =
644f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      SSL_CIPHER_description(SSL_get_current_cipher(ssl), NULL, 128);
645f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_INFO) << "Cipher: " << cipher_description;
646f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    OPENSSL_free(cipher_description);
647f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
648f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
649f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
650f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool ok = false;
651f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int extension_count = X509_get_ext_count(certificate);
652f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  for (int i = 0; i < extension_count; ++i) {
653f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    X509_EXTENSION* extension = X509_get_ext(certificate, i);
654f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    int extension_nid = OBJ_obj2nid(X509_EXTENSION_get_object(extension));
655f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
656f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (extension_nid == NID_subject_alt_name) {
6573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#if OPENSSL_VERSION_NUMBER >= 0x10000000L
6583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      const X509V3_EXT_METHOD* meth = X509V3_EXT_get(extension);
6593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#else
660f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      X509V3_EXT_METHOD* meth = X509V3_EXT_get(extension);
6613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#endif
662f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      if (!meth)
663f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        break;
664f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
665f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      void* ext_str = NULL;
666f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
667f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // We assign this to a local variable, instead of passing the address
668f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // directly to ASN1_item_d2i.
669f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // See http://readlist.com/lists/openssl.org/openssl-users/0/4761.html.
670f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      unsigned char* ext_value_data = extension->value->data;
671f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
672f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
673f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      const unsigned char **ext_value_data_ptr =
674f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          (const_cast<const unsigned char **>(&ext_value_data));
675f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#else
676f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      unsigned char **ext_value_data_ptr = &ext_value_data;
677f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
678f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
679f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      if (meth->it) {
680f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        ext_str = ASN1_item_d2i(NULL, ext_value_data_ptr,
681f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                extension->value->length,
682f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                ASN1_ITEM_ptr(meth->it));
683f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      } else {
684f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        ext_str = meth->d2i(NULL, ext_value_data_ptr, extension->value->length);
685f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
686f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
687f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      STACK_OF(CONF_VALUE)* value = meth->i2v(meth, ext_str, NULL);
688f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      for (int j = 0; j < sk_CONF_VALUE_num(value); ++j) {
689f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        CONF_VALUE* nval = sk_CONF_VALUE_value(value, j);
690f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        // The value for nval can contain wildcards
691f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        if (!strcmp(nval->name, "DNS") && string_match(host, nval->value)) {
692f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          ok = true;
693f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          break;
694f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        }
695f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
696f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      sk_CONF_VALUE_pop_free(value, X509V3_conf_free);
697f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      value = NULL;
698f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
699f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      if (meth->it) {
700f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        ASN1_item_free(reinterpret_cast<ASN1_VALUE*>(ext_str), meth->it);
701f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      } else {
702f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        meth->ext_free(ext_str);
703f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
704f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      ext_str = NULL;
705f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
706f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (ok)
707f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      break;
708f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
709f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
710f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  char data[256];
711f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  X509_name_st* subject;
712f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!ok
713f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      && (subject = X509_get_subject_name(certificate))
714f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      && (X509_NAME_get_text_by_NID(subject, NID_commonName,
715f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                    data, sizeof(data)) > 0)) {
716f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    data[sizeof(data)-1] = 0;
717f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (_stricmp(data, host) == 0)
718f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      ok = true;
719f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
720f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
721f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  X509_free(certificate);
722f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
723f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!ok && ignore_bad_cert) {
724f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_WARNING) << "TLS certificate check FAILED.  "
725f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      << "Allowing connection anyway.";
726f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ok = true;
727f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
728f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
729f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return ok;
730f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
731f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
732f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool OpenSSLAdapter::SSLPostConnectionCheck(SSL* ssl, const char* host) {
733f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool ok = VerifyServerName(ssl, host, ignore_bad_cert());
734f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
735f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (ok) {
736f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ok = (SSL_get_verify_result(ssl) == X509_V_OK ||
737f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          custom_verification_succeeded_);
738f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
739f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
740f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!ok && ignore_bad_cert()) {
741f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_INFO) << "Other TLS post connection checks failed.";
742f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ok = true;
743f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
744f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
745f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return ok;
746f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
747f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
748f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if _DEBUG
749f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
750f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// We only use this for tracing and so it is only needed in debug mode
751f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
752f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid
753f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochOpenSSLAdapter::SSLInfoCallback(const SSL* s, int where, int ret) {
754f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  const char* str = "undefined";
755f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int w = where & ~SSL_ST_MASK;
756f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (w & SSL_ST_CONNECT) {
757f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    str = "SSL_connect";
758f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else if (w & SSL_ST_ACCEPT) {
759f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    str = "SSL_accept";
760f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
761f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (where & SSL_CB_LOOP) {
762f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_INFO) <<  str << ":" << SSL_state_string_long(s);
763f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else if (where & SSL_CB_ALERT) {
764f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    str = (where & SSL_CB_READ) ? "read" : "write";
765f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_INFO) <<  "SSL3 alert " << str
766f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      << ":" << SSL_alert_type_string_long(ret)
767f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      << ":" << SSL_alert_desc_string_long(ret);
768f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else if (where & SSL_CB_EXIT) {
769f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (ret == 0) {
770f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      LOG(LS_INFO) << str << ":failed in " << SSL_state_string_long(s);
771f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    } else if (ret < 0) {
772f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      LOG(LS_INFO) << str << ":error in " << SSL_state_string_long(s);
773f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
774f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
775f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
776f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
777f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif  // _DEBUG
778f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
779f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint
780f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochOpenSSLAdapter::SSLVerifyCallback(int ok, X509_STORE_CTX* store) {
781f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if _DEBUG
782f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!ok) {
783f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    char data[256];
784f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    X509* cert = X509_STORE_CTX_get_current_cert(store);
785f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    int depth = X509_STORE_CTX_get_error_depth(store);
786f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    int err = X509_STORE_CTX_get_error(store);
787f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
788f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_INFO) << "Error with certificate at depth: " << depth;
789f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof(data));
790f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_INFO) << "  issuer  = " << data;
791f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof(data));
792f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_INFO) << "  subject = " << data;
793f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_INFO) << "  err     = " << err
794f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      << ":" << X509_verify_cert_error_string(err);
795f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
796f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
797f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
798f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Get our stream pointer from the store
799f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SSL* ssl = reinterpret_cast<SSL*>(
800f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                X509_STORE_CTX_get_ex_data(store,
801f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                  SSL_get_ex_data_X509_STORE_CTX_idx()));
802f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
803f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  OpenSSLAdapter* stream =
804f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    reinterpret_cast<OpenSSLAdapter*>(SSL_get_app_data(ssl));
805f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
806f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!ok && custom_verify_callback_) {
807f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    void* cert =
808f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        reinterpret_cast<void*>(X509_STORE_CTX_get_current_cert(store));
809f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (custom_verify_callback_(cert)) {
810f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      stream->custom_verification_succeeded_ = true;
811f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      LOG(LS_INFO) << "validated certificate using custom callback";
812f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      ok = true;
813f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
814f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
815f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
816f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!ok && stream->ignore_bad_cert()) {
817f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_WARNING) << "Ignoring cert error while verifying cert chain";
818f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ok = 1;
819f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
820f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
821f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return ok;
822f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
823f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
824f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool OpenSSLAdapter::ConfigureTrustedRootCertificates(SSL_CTX* ctx) {
825f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Add the root cert to the SSL context
826731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // TODO: this cert appears to be the wrong one.
827f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
828f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch   const unsigned char* cert_buffer
829f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#else
830f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch   unsigned char* cert_buffer
831f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
832f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    = EquifaxSecureGlobalEBusinessCA1_certificate;
833f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  size_t cert_buffer_len = sizeof(EquifaxSecureGlobalEBusinessCA1_certificate);
834f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  X509* cert = d2i_X509(NULL, &cert_buffer, cert_buffer_len);
835f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (cert == NULL)
836f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
837f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool success = X509_STORE_add_cert(SSL_CTX_get_cert_store(ctx), cert);
838f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  X509_free(cert);
839f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return success;
840f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
841f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
842f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochSSL_CTX*
843f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochOpenSSLAdapter::SetupSSLContext() {
844f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SSL_CTX* ctx = SSL_CTX_new(TLSv1_client_method());
845f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (ctx == NULL)
846f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return NULL;
847f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
848f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!ConfigureTrustedRootCertificates(ctx)) {
849f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SSL_CTX_free(ctx);
850f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return NULL;
851f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
852f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
853f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef _DEBUG
854f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SSL_CTX_set_info_callback(ctx, SSLInfoCallback);
855f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
856f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
857f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, SSLVerifyCallback);
858f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SSL_CTX_set_verify_depth(ctx, 4);
859f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SSL_CTX_set_cipher_list(ctx, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
860f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
861f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return ctx;
862f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
863f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
864f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} // namespace talk_base
865f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
866f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif  // HAVE_OPENSSL_SSL_H
867