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.
This commit is contained in:
Aaron Jones 2016-09-15 15:30:12 +00:00
parent 2aec9b6d68
commit 8a40573369
No known key found for this signature in database
GPG key ID: EC6F86EE9CD840B5

View file

@ -33,8 +33,7 @@
#include "openssl_ratbox.h" #include "openssl_ratbox.h"
static SSL_CTX *ssl_server_ctx = NULL; static SSL_CTX *ssl_ctx = NULL;
static SSL_CTX *ssl_client_ctx = NULL;
static unsigned long static unsigned long
get_last_err(void) get_last_err(void)
@ -169,7 +168,7 @@ void
rb_ssl_start_accepted(rb_fde_t *new_F, ACCB * cb, void *data, int timeout) rb_ssl_start_accepted(rb_fde_t *new_F, ACCB * cb, void *data, int timeout)
{ {
new_F->type |= RB_FD_SSL; 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 = rb_malloc(sizeof(struct acceptdata));
new_F->accept->callback = cb; 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; new_F->accept->addrlen = 0;
SSL_set_fd((SSL *) new_F->ssl, rb_get_fd(new_F)); 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); 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) 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->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 = rb_malloc(sizeof(struct acceptdata));
new_F->accept->callback = F->accept->callback; 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; new_F->accept->addrlen = addrlen;
SSL_set_fd((SSL *) new_F->ssl, rb_get_fd(new_F)); 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); rb_ssl_accept_common(new_F);
} }
@ -294,9 +295,6 @@ rb_init_ssl(void)
int int
rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, const char *cipher_list) 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) if(cert == NULL)
{ {
rb_lib_log("rb_setup_ssl_server: No certificate file"); 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; cipher_list = rb_default_ciphers;
#ifdef LRB_HAVE_TLS_METHOD_API #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 #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 #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_ctx_new == NULL)
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
{ {
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())); get_ssl_error(ERR_get_error()));
SSL_CTX_free(ssl_server_ctx_new);
return 0; return 0;
} }
#ifndef LRB_HAVE_TLS_METHOD_API #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_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);
#endif #endif
#ifdef SSL_OP_SINGLE_DH_USE #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 #endif
#ifdef SSL_OP_SINGLE_ECDH_USE #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 #endif
#ifdef SSL_OP_NO_TICKET #ifdef SSL_OP_NO_TICKET
SSL_CTX_set_options(ssl_server_ctx_new, SSL_OP_NO_TICKET); SSL_CTX_set_options(ssl_ctx_new, SSL_OP_NO_TICKET);
SSL_CTX_set_options(ssl_client_ctx_new, SSL_OP_NO_TICKET);
#endif #endif
#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE #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 #endif
#ifdef LRB_HAVE_TLS_ECDH_AUTO #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 #endif
#ifdef LRB_HAVE_TLS_SET_CURVES #ifdef LRB_HAVE_TLS_SET_CURVES
SSL_CTX_set1_curves_list(ssl_server_ctx_new, rb_default_curves); SSL_CTX_set1_curves_list(ssl_ctx_new, rb_default_curves);
SSL_CTX_set1_curves_list(ssl_client_ctx_new, rb_default_curves);
#endif #endif
SSL_CTX_set_verify(ssl_server_ctx_new, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, verify_accept_all_cb); 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_server_ctx_new, SSL_SESS_CACHE_OFF); 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 * 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) #if (OPENSSL_VERSION_NUMBER >= 0x10000000L) && (OPENSSL_VERSION_NUMBER < 0x10002000L) && !defined(OPENSSL_NO_ECDH)
EC_KEY *key = EC_KEY_new_by_curve_name(NID_secp384r1); EC_KEY *key = EC_KEY_new_by_curve_name(NID_secp384r1);
if(key) { 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); EC_KEY_free(key);
} }
#endif #endif
SSL_CTX_set_cipher_list(ssl_server_ctx_new, cipher_list); SSL_CTX_set_cipher_list(ssl_ctx_new, cipher_list);
SSL_CTX_set_cipher_list(ssl_client_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, rb_lib_log("rb_setup_ssl_server: Error loading certificate file [%s]: %s", cert,
get_ssl_error(ERR_get_error())); get_ssl_error(ERR_get_error()));
SSL_CTX_free(ssl_server_ctx_new); SSL_CTX_free(ssl_ctx_new);
SSL_CTX_free(ssl_client_ctx_new);
return 0; 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, rb_lib_log("rb_setup_ssl_server: Error loading keyfile [%s]: %s", keyfile,
get_ssl_error(ERR_get_error())); get_ssl_error(ERR_get_error()));
SSL_CTX_free(ssl_server_ctx_new); SSL_CTX_free(ssl_ctx_new);
SSL_CTX_free(ssl_client_ctx_new);
return 0; return 0;
} }
@ -423,20 +404,16 @@ rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, c
} }
else else
{ {
SSL_CTX_set_tmp_dh(ssl_server_ctx_new, dh); SSL_CTX_set_tmp_dh(ssl_ctx_new, dh);
DH_free(dh); DH_free(dh);
fclose(fp); fclose(fp);
} }
} }
if(ssl_server_ctx) if(ssl_ctx)
SSL_CTX_free(ssl_server_ctx); SSL_CTX_free(ssl_ctx);
if(ssl_client_ctx) ssl_ctx = ssl_ctx_new;
SSL_CTX_free(ssl_client_ctx);
ssl_server_ctx = ssl_server_ctx_new;
ssl_client_ctx = ssl_client_ctx_new;
return 1; return 1;
} }
@ -521,8 +498,9 @@ rb_ssl_tryconn(rb_fde_t *F, int status, void *data)
} }
F->type |= RB_FD_SSL; 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_fd((SSL *) F->ssl, F->fd);
SSL_set_connect_state((SSL *) F->ssl);
rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn); rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn);
if((ssl_err = SSL_connect((SSL *) F->ssl)) <= 0) 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->callback = callback;
F->connect->data = data; F->connect->data = data;
F->type |= RB_FD_SSL; 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_fd((SSL *) F->ssl, F->fd);
SSL_set_connect_state((SSL *) F->ssl);
rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn); rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn);
if((ssl_err = SSL_connect((SSL *) F->ssl)) <= 0) if((ssl_err = SSL_connect((SSL *) F->ssl)) <= 0)
{ {