From 8a40573369e4e23d86435a8347b2d4186b5228f0 Mon Sep 17 00:00:00 2001 From: Aaron Jones Date: Thu, 15 Sep 2016 15:30:12 +0000 Subject: [PATCH] OpenSSL: Remove context duplication OpenSSL is perfectly capable of having a single context that is shared by both client and server sessions alike; one simply needs to call SSL_set_accept_state (for server) or SSL_set_connect_state (for client) before attempting handshaking. --- libratbox/src/openssl.c | 85 ++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 53 deletions(-) diff --git a/libratbox/src/openssl.c b/libratbox/src/openssl.c index 07017a10..944800de 100644 --- a/libratbox/src/openssl.c +++ b/libratbox/src/openssl.c @@ -33,8 +33,7 @@ #include "openssl_ratbox.h" -static SSL_CTX *ssl_server_ctx = NULL; -static SSL_CTX *ssl_client_ctx = NULL; +static SSL_CTX *ssl_ctx = NULL; static unsigned long get_last_err(void) @@ -169,7 +168,7 @@ void rb_ssl_start_accepted(rb_fde_t *new_F, ACCB * cb, void *data, int timeout) { new_F->type |= RB_FD_SSL; - new_F->ssl = SSL_new(ssl_server_ctx); + new_F->ssl = SSL_new(ssl_ctx); new_F->accept = rb_malloc(sizeof(struct acceptdata)); new_F->accept->callback = cb; @@ -178,6 +177,7 @@ rb_ssl_start_accepted(rb_fde_t *new_F, ACCB * cb, void *data, int timeout) new_F->accept->addrlen = 0; SSL_set_fd((SSL *) new_F->ssl, rb_get_fd(new_F)); + SSL_set_accept_state((SSL *) new_F->ssl); rb_ssl_accept_common(new_F); } @@ -188,7 +188,7 @@ void rb_ssl_accept_setup(rb_fde_t *F, rb_fde_t *new_F, struct sockaddr *st, int addrlen) { new_F->type |= RB_FD_SSL; - new_F->ssl = SSL_new(ssl_server_ctx); + new_F->ssl = SSL_new(ssl_ctx); new_F->accept = rb_malloc(sizeof(struct acceptdata)); new_F->accept->callback = F->accept->callback; @@ -198,6 +198,7 @@ rb_ssl_accept_setup(rb_fde_t *F, rb_fde_t *new_F, struct sockaddr *st, int addrl new_F->accept->addrlen = addrlen; SSL_set_fd((SSL *) new_F->ssl, rb_get_fd(new_F)); + SSL_set_accept_state((SSL *) new_F->ssl); rb_ssl_accept_common(new_F); } @@ -294,9 +295,6 @@ rb_init_ssl(void) int rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, const char *cipher_list) { - SSL_CTX *ssl_server_ctx_new; - SSL_CTX *ssl_client_ctx_new; - if(cert == NULL) { rb_lib_log("rb_setup_ssl_server: No certificate file"); @@ -313,62 +311,48 @@ rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, c cipher_list = rb_default_ciphers; #ifdef LRB_HAVE_TLS_METHOD_API - if((ssl_server_ctx_new = SSL_CTX_new(TLS_server_method())) == NULL) + SSL_CTX *const ssl_ctx_new = SSL_CTX_new(TLS_method()); #else - if((ssl_server_ctx_new = SSL_CTX_new(SSLv23_server_method())) == NULL) + SSL_CTX *const ssl_ctx_new = SSL_CTX_new(SSLv23_method()); #endif - { - rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL server context: %s", - get_ssl_error(ERR_get_error())); - return 0; - } - #ifdef LRB_HAVE_TLS_METHOD_API - if((ssl_client_ctx_new = SSL_CTX_new(TLS_client_method())) == NULL) - #else - if((ssl_client_ctx_new = SSL_CTX_new(SSLv23_client_method())) == NULL) - #endif + if(ssl_ctx_new == NULL) { - rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL client context: %s", + rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL context: %s", get_ssl_error(ERR_get_error())); - - SSL_CTX_free(ssl_server_ctx_new); return 0; } #ifndef LRB_HAVE_TLS_METHOD_API - SSL_CTX_set_options(ssl_server_ctx_new, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); - SSL_CTX_set_options(ssl_client_ctx_new, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); + SSL_CTX_set_options(ssl_ctx_new, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); #endif #ifdef SSL_OP_SINGLE_DH_USE - SSL_CTX_set_options(ssl_server_ctx_new, SSL_OP_SINGLE_DH_USE); + SSL_CTX_set_options(ssl_ctx_new, SSL_OP_SINGLE_DH_USE); #endif #ifdef SSL_OP_SINGLE_ECDH_USE - SSL_CTX_set_options(ssl_server_ctx_new, SSL_OP_SINGLE_ECDH_USE); + SSL_CTX_set_options(ssl_ctx_new, SSL_OP_SINGLE_ECDH_USE); #endif #ifdef SSL_OP_NO_TICKET - SSL_CTX_set_options(ssl_server_ctx_new, SSL_OP_NO_TICKET); - SSL_CTX_set_options(ssl_client_ctx_new, SSL_OP_NO_TICKET); + SSL_CTX_set_options(ssl_ctx_new, SSL_OP_NO_TICKET); #endif #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE - SSL_CTX_set_options(ssl_server_ctx_new, SSL_OP_CIPHER_SERVER_PREFERENCE); + SSL_CTX_set_options(ssl_ctx_new, SSL_OP_CIPHER_SERVER_PREFERENCE); #endif #ifdef LRB_HAVE_TLS_ECDH_AUTO - SSL_CTX_set_ecdh_auto(ssl_server_ctx_new, 1); + SSL_CTX_set_ecdh_auto(ssl_ctx_new, 1); #endif #ifdef LRB_HAVE_TLS_SET_CURVES - SSL_CTX_set1_curves_list(ssl_server_ctx_new, rb_default_curves); - SSL_CTX_set1_curves_list(ssl_client_ctx_new, rb_default_curves); + SSL_CTX_set1_curves_list(ssl_ctx_new, rb_default_curves); #endif - SSL_CTX_set_verify(ssl_server_ctx_new, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, verify_accept_all_cb); - SSL_CTX_set_session_cache_mode(ssl_server_ctx_new, SSL_SESS_CACHE_OFF); + SSL_CTX_set_verify(ssl_ctx_new, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, verify_accept_all_cb); + SSL_CTX_set_session_cache_mode(ssl_ctx_new, SSL_SESS_CACHE_OFF); /* * Set manual ECDHE curve on OpenSSL 1.0.0 & 1.0.1, but make sure it's actually available @@ -376,31 +360,28 @@ rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, c #if (OPENSSL_VERSION_NUMBER >= 0x10000000L) && (OPENSSL_VERSION_NUMBER < 0x10002000L) && !defined(OPENSSL_NO_ECDH) EC_KEY *key = EC_KEY_new_by_curve_name(NID_secp384r1); if(key) { - SSL_CTX_set_tmp_ecdh(ssl_server_ctx_new, key); + SSL_CTX_set_tmp_ecdh(ssl_ctx_new, key); EC_KEY_free(key); } #endif - SSL_CTX_set_cipher_list(ssl_server_ctx_new, cipher_list); - SSL_CTX_set_cipher_list(ssl_client_ctx_new, cipher_list); + SSL_CTX_set_cipher_list(ssl_ctx_new, cipher_list); - if(!SSL_CTX_use_certificate_chain_file(ssl_server_ctx_new, cert) || !SSL_CTX_use_certificate_chain_file(ssl_client_ctx_new, cert)) + if(! SSL_CTX_use_certificate_chain_file(ssl_ctx_new, cert)) { rb_lib_log("rb_setup_ssl_server: Error loading certificate file [%s]: %s", cert, get_ssl_error(ERR_get_error())); - SSL_CTX_free(ssl_server_ctx_new); - SSL_CTX_free(ssl_client_ctx_new); + SSL_CTX_free(ssl_ctx_new); return 0; } - if(!SSL_CTX_use_PrivateKey_file(ssl_server_ctx_new, keyfile, SSL_FILETYPE_PEM) || !SSL_CTX_use_PrivateKey_file(ssl_client_ctx_new, keyfile, SSL_FILETYPE_PEM)) + if(! SSL_CTX_use_PrivateKey_file(ssl_ctx_new, keyfile, SSL_FILETYPE_PEM)) { rb_lib_log("rb_setup_ssl_server: Error loading keyfile [%s]: %s", keyfile, get_ssl_error(ERR_get_error())); - SSL_CTX_free(ssl_server_ctx_new); - SSL_CTX_free(ssl_client_ctx_new); + SSL_CTX_free(ssl_ctx_new); return 0; } @@ -423,20 +404,16 @@ rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, c } else { - SSL_CTX_set_tmp_dh(ssl_server_ctx_new, dh); + SSL_CTX_set_tmp_dh(ssl_ctx_new, dh); DH_free(dh); fclose(fp); } } - if(ssl_server_ctx) - SSL_CTX_free(ssl_server_ctx); + if(ssl_ctx) + SSL_CTX_free(ssl_ctx); - if(ssl_client_ctx) - SSL_CTX_free(ssl_client_ctx); - - ssl_server_ctx = ssl_server_ctx_new; - ssl_client_ctx = ssl_client_ctx_new; + ssl_ctx = ssl_ctx_new; return 1; } @@ -521,8 +498,9 @@ rb_ssl_tryconn(rb_fde_t *F, int status, void *data) } F->type |= RB_FD_SSL; - F->ssl = SSL_new(ssl_client_ctx); + F->ssl = SSL_new(ssl_ctx); SSL_set_fd((SSL *) F->ssl, F->fd); + SSL_set_connect_state((SSL *) F->ssl); rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn); if((ssl_err = SSL_connect((SSL *) F->ssl)) <= 0) { @@ -583,9 +561,10 @@ rb_ssl_start_connected(rb_fde_t *F, CNCB * callback, void *data, int timeout) F->connect->callback = callback; F->connect->data = data; F->type |= RB_FD_SSL; - F->ssl = SSL_new(ssl_client_ctx); + F->ssl = SSL_new(ssl_ctx); SSL_set_fd((SSL *) F->ssl, F->fd); + SSL_set_connect_state((SSL *) F->ssl); rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn); if((ssl_err = SSL_connect((SSL *) F->ssl)) <= 0) {