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