From 1f30c8943bf2ca3a26c362fa7b2487860f86521b Mon Sep 17 00:00:00 2001 From: Aaron Jones Date: Thu, 15 Sep 2016 14:08:19 +0000 Subject: [PATCH 01/25] OpenSSL: Tidy up headers Move all the header includes to a single header file, rename said file. --- libratbox/src/openssl.c | 77 ++----------------------- libratbox/src/openssl_ratbox.h | 102 +++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 71 deletions(-) create mode 100644 libratbox/src/openssl_ratbox.h diff --git a/libratbox/src/openssl.c b/libratbox/src/openssl.c index 64a446b0..0871c671 100644 --- a/libratbox/src/openssl.c +++ b/libratbox/src/openssl.c @@ -1,9 +1,10 @@ /* * libratbox: a library used by ircd-ratbox and other things - * openssl.c: openssl related code + * openssl.c: OpenSSL backend * * Copyright (C) 2007-2008 ircd-ratbox development team * Copyright (C) 2007-2008 Aaron Sethman + * Copyright (C) 2015-2016 Aaron Jones * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,7 +21,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA * - * $Id: commio.c 24808 2008-01-02 08:17:05Z androsyn $ */ #include @@ -30,67 +30,8 @@ #include #include -#include -#include -#include -#include -#include -#include -/* - * This is a mess but what can you do when the library authors - * refuse to play ball with established conventions? - */ -#if defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER >= 0x20020002L) -# define LRB_HAVE_TLS_METHOD_API 1 -#else -# if !defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x10100000L) -# define LRB_HAVE_TLS_METHOD_API 1 -# endif -#endif - -/* - * Use SSL_CTX_set_ecdh_auto() in OpenSSL 1.0.2 only - * Use SSL_CTX_set1_curves_list() in OpenSSL 1.0.2 and above - * TODO: Merge this into the block above if LibreSSL implements them - */ -#if !defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x10002000L) -# define LRB_HAVE_TLS_SET_CURVES 1 -# if (OPENSSL_VERSION_NUMBER < 0x10100000L) -# define LRB_HAVE_TLS_ECDH_AUTO 1 -# endif -#endif - -/* - * More LibreSSL compatibility mess - * Used in rb_get_ssl_info() below. - */ -#if !defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x10100000L) - /* OpenSSL 1.1.0+ */ -# define LRB_SSL_VTEXT_COMPILETIME OPENSSL_VERSION_TEXT -# define LRB_SSL_VTEXT_RUNTIME OpenSSL_version(OPENSSL_VERSION) -# define LRB_SSL_VNUM_COMPILETIME OPENSSL_VERSION_NUMBER -# define LRB_SSL_VNUM_RUNTIME OpenSSL_version_num() -# define LRB_SSL_FULL_VERSION_INFO 1 -#else -/* - * "Full version info" above means we have access to all 4 pieces of information. - * - * For the below, this is not the case; LibreSSL version number at runtime returns - * the wrong version number, and OpenSSL version text at compile time does not exist. - * Thus, we only reliably have version text at runtime, and version number at compile - * time. - */ -# if defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER >= 0x20200000L) - /* LibreSSL 2.2.0+ */ -# define LRB_SSL_VTEXT_RUNTIME SSLeay_version(SSLEAY_VERSION) -# define LRB_SSL_VNUM_COMPILETIME LIBRESSL_VERSION_NUMBER -# else - /* OpenSSL < 1.1.0 or LibreSSL < 2.2.0 */ -# define LRB_SSL_VTEXT_RUNTIME SSLeay_version(SSLEAY_VERSION) -# define LRB_SSL_VNUM_COMPILETIME SSLEAY_VERSION_NUMBER -# endif -#endif +#include "openssl_ratbox.h" static SSL_CTX *ssl_server_ctx = NULL; static SSL_CTX *ssl_client_ctx = NULL; @@ -374,15 +315,9 @@ rb_init_ssl(void) int rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, const char *cipher_list) { - const char libratbox_ciphers[] = "kEECDH+HIGH:kEDH+HIGH:HIGH:!aNULL"; - SSL_CTX *ssl_server_ctx_new; SSL_CTX *ssl_client_ctx_new; - #ifdef LRB_HAVE_TLS_SET_CURVES - const char libratbox_curves[] = "P-521:P-384:P-256"; - #endif - if(cert == NULL) { rb_lib_log("rb_setup_ssl_server: No certificate file"); @@ -396,7 +331,7 @@ rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, c } if(cipher_list == NULL) - cipher_list = libratbox_ciphers; + cipher_list = rb_default_ciphers; #ifdef LRB_HAVE_TLS_METHOD_API if((ssl_server_ctx_new = SSL_CTX_new(TLS_server_method())) == NULL) @@ -449,8 +384,8 @@ rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, c #endif #ifdef LRB_HAVE_TLS_SET_CURVES - SSL_CTX_set1_curves_list(ssl_server_ctx_new, libratbox_curves); - SSL_CTX_set1_curves_list(ssl_client_ctx_new, libratbox_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); #endif SSL_CTX_set_verify(ssl_server_ctx_new, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, verify_accept_all_cb); diff --git a/libratbox/src/openssl_ratbox.h b/libratbox/src/openssl_ratbox.h new file mode 100644 index 00000000..b2d033c9 --- /dev/null +++ b/libratbox/src/openssl_ratbox.h @@ -0,0 +1,102 @@ +/* + * libratbox: a library used by ircd-ratbox and other things + * openssl_ratbox.h: OpenSSL backend data + * + * Copyright (C) 2015-2016 Aaron Jones + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + */ + +#ifndef LRB_OPENSSL_H_INC +#define LRB_OPENSSL_H_INC 1 + +#include +#include +#include +#include +#include +#include + +#include + +/* + * A long time ago, in a world far away, OpenSSL had a well-established mechanism for ensuring compatibility with + * regards to added, changed, and removed functions, by having an SSLEAY_VERSION_NUMBER macro. This was then + * renamed to OPENSSL_VERSION_NUMBER, but the old macro was kept around for compatibility until OpenSSL version + * 1.1.0. + * + * Then the OpenBSD developers decided that having OpenSSL in their codebase was a bad idea. They forked it to + * create LibreSSL, gutted all of the functionality they didn't want or need, and generally improved the library + * a lot. Then, as the OpenBSD developers are want to do, they packaged up LibreSSL for release to other + * operating systems, as LibreSSL Portable. Think along the lines of OpenSSH where they have also done this. + * + * The fun part of this story ends there. LibreSSL has an OPENSSL_VERSION_NUMBER macro, but they have set it to a + * stupidly high value, version 2.0. OpenSSL version 2.0 does not exist, and LibreSSL 2.2 does not implement + * everything OpenSSL 1.0.2 or 1.1.0 do. This completely breaks the entire purpose of the macro. + * + * The ifdef soup below is for LibreSSL compatibility. Please find whoever thought setting OPENSSL_VERSION_NUMBER + * to a version that does not exist was a good idea. Encourage them to realise that it is not. -- amdj + */ + +#if !defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x10100000L) +# define LRB_SSL_NO_EXPLICIT_INIT 1 +#endif + +#if !defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x10002000L) +# define LRB_HAVE_TLS_SET_CURVES 1 +# if (OPENSSL_VERSION_NUMBER < 0x10100000L) +# define LRB_HAVE_TLS_ECDH_AUTO 1 +# endif +#endif + +#if defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER >= 0x20020002L) +# define LRB_HAVE_TLS_METHOD_API 1 +#else +# if !defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x10100000L) +# define LRB_HAVE_TLS_METHOD_API 1 +# endif +#endif + +#if !defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x10100000L) +# define LRB_SSL_VTEXT_COMPILETIME OPENSSL_VERSION_TEXT +# define LRB_SSL_VTEXT_RUNTIME OpenSSL_version(OPENSSL_VERSION) +# define LRB_SSL_VNUM_COMPILETIME OPENSSL_VERSION_NUMBER +# define LRB_SSL_VNUM_RUNTIME OpenSSL_version_num() +# define LRB_SSL_FULL_VERSION_INFO 1 +#else +# if defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER >= 0x20200000L) +# define LRB_SSL_VTEXT_RUNTIME SSLeay_version(SSLEAY_VERSION) +# define LRB_SSL_VNUM_COMPILETIME LIBRESSL_VERSION_NUMBER +# else +# define LRB_SSL_VTEXT_RUNTIME SSLeay_version(SSLEAY_VERSION) +# define LRB_SSL_VNUM_COMPILETIME SSLEAY_VERSION_NUMBER +# endif +#endif + + + +/* + * Default supported ciphersuites (if the user does not provide any) and curves (OpenSSL 1.0.2+) + * Hardcoded secp384r1 (P-384) is used on OpenSSL 1.0.0 and 1.0.1 (if available). + */ + +static const char rb_default_ciphers[] = "kEECDH+HIGH:kEDH+HIGH:HIGH:!aNULL"; +#ifdef LRB_HAVE_TLS_SET_CURVES +static const char rb_default_curves[] = "P-521:P-384:P-256"; +#endif + +#endif /* LRB_OPENSSL_H_INC */ From 2aec9b6d6851e4df79473a2802868f586fa0c2ff Mon Sep 17 00:00:00 2001 From: Aaron Jones Date: Thu, 15 Sep 2016 15:28:44 +0000 Subject: [PATCH 02/25] OpenSSL: Remove unnecessary handshake info callback --- libratbox/src/openssl.c | 31 +++++-------------------------- 1 file changed, 5 insertions(+), 26 deletions(-) diff --git a/libratbox/src/openssl.c b/libratbox/src/openssl.c index 0871c671..07017a10 100644 --- a/libratbox/src/openssl.c +++ b/libratbox/src/openssl.c @@ -35,7 +35,6 @@ static SSL_CTX *ssl_server_ctx = NULL; static SSL_CTX *ssl_client_ctx = NULL; -static int libratbox_index = -1; static unsigned long get_last_err(void) @@ -88,25 +87,6 @@ rb_ssl_timeout(rb_fde_t *F, void *notused) } -static void -rb_ssl_info_callback(SSL * ssl, int where, int ret) -{ - if(where & SSL_CB_HANDSHAKE_START) - { - rb_fde_t *F = SSL_get_ex_data(ssl, libratbox_index); - if(F == NULL) - return; - F->handshake_count++; - } -} - -static void -rb_setup_ssl_cb(rb_fde_t *F) -{ - SSL_set_ex_data(F->ssl, libratbox_index, (char *)F); - SSL_set_info_callback((SSL *) F->ssl, (void (*)(const SSL *,int,int))rb_ssl_info_callback); -} - static void rb_ssl_tryaccept(rb_fde_t *F, void *data) { @@ -140,6 +120,8 @@ rb_ssl_tryaccept(rb_fde_t *F, void *data) } return; } + else + F->handshake_count++; } rb_settimeout(F, 0, NULL, NULL); rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, NULL, NULL); @@ -178,6 +160,7 @@ rb_ssl_accept_common(rb_fde_t *new_F) } else { + new_F->handshake_count++; rb_ssl_tryaccept(new_F, NULL); } } @@ -195,7 +178,6 @@ 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)); - rb_setup_ssl_cb(new_F); rb_ssl_accept_common(new_F); } @@ -216,7 +198,6 @@ 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)); - rb_setup_ssl_cb(new_F); rb_ssl_accept_common(new_F); } @@ -307,8 +288,6 @@ rb_init_ssl(void) SSL_load_error_strings(); #endif - libratbox_index = SSL_get_ex_new_index(0, libratbox_data, NULL, NULL, NULL); - return 1; } @@ -524,6 +503,7 @@ rb_ssl_tryconn_cb(rb_fde_t *F, void *data) } else { + F->handshake_count++; rb_ssl_connect_realcb(F, RB_OK, sconn); } } @@ -543,7 +523,6 @@ rb_ssl_tryconn(rb_fde_t *F, int status, void *data) F->type |= RB_FD_SSL; F->ssl = SSL_new(ssl_client_ctx); SSL_set_fd((SSL *) F->ssl, F->fd); - rb_setup_ssl_cb(F); rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn); if((ssl_err = SSL_connect((SSL *) F->ssl)) <= 0) { @@ -567,6 +546,7 @@ rb_ssl_tryconn(rb_fde_t *F, int status, void *data) } else { + F->handshake_count++; rb_ssl_connect_realcb(F, RB_OK, sconn); } } @@ -606,7 +586,6 @@ rb_ssl_start_connected(rb_fde_t *F, CNCB * callback, void *data, int timeout) F->ssl = SSL_new(ssl_client_ctx); SSL_set_fd((SSL *) F->ssl, F->fd); - rb_setup_ssl_cb(F); rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn); if((ssl_err = SSL_connect((SSL *) F->ssl)) <= 0) { From 8a40573369e4e23d86435a8347b2d4186b5228f0 Mon Sep 17 00:00:00 2001 From: Aaron Jones Date: Thu, 15 Sep 2016 15:30:12 +0000 Subject: [PATCH 03/25] 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) { From 1c7d29532071b893c44137da650a731df968c792 Mon Sep 17 00:00:00 2001 From: Aaron Jones Date: Thu, 15 Sep 2016 15:51:33 +0000 Subject: [PATCH 04/25] OpenSSL: Move connect structure declaration to top of file --- libratbox/src/openssl.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/libratbox/src/openssl.c b/libratbox/src/openssl.c index 944800de..49625bb7 100644 --- a/libratbox/src/openssl.c +++ b/libratbox/src/openssl.c @@ -35,6 +35,15 @@ static SSL_CTX *ssl_ctx = NULL; +struct ssl_connect +{ + CNCB *callback; + void *data; + int timeout; +}; + +static void rb_ssl_connect_realcb(rb_fde_t *, int, struct ssl_connect *); + static unsigned long get_last_err(void) { @@ -429,13 +438,6 @@ rb_ssl_listen(rb_fde_t *F, int backlog, int defer_accept) return result; } -struct ssl_connect -{ - CNCB *callback; - void *data; - int timeout; -}; - static void rb_ssl_connect_realcb(rb_fde_t *F, int status, struct ssl_connect *sconn) { From 1c39c519fe1e1cfdfa96fd69219fd3b3088b0515 Mon Sep 17 00:00:00 2001 From: Aaron Jones Date: Thu, 15 Sep 2016 16:26:01 +0000 Subject: [PATCH 05/25] OpenSSL: Reorder functions in line with the MbedTLS backend. The diff for this commit will look like I have changed a lot of code; in reality, nothing was changed, just whole functions moved up or down. --- libratbox/src/openssl.c | 556 +++++++++++++++++++++------------------- 1 file changed, 289 insertions(+), 267 deletions(-) diff --git a/libratbox/src/openssl.c b/libratbox/src/openssl.c index 49625bb7..f2c4429d 100644 --- a/libratbox/src/openssl.c +++ b/libratbox/src/openssl.c @@ -43,6 +43,15 @@ struct ssl_connect }; static void rb_ssl_connect_realcb(rb_fde_t *, int, struct ssl_connect *); +static void rb_ssl_tryconn_timeout_cb(rb_fde_t *, void *); +static void rb_ssl_timeout(rb_fde_t *, void *); +static void rb_ssl_tryaccept(rb_fde_t *, void *); + + + +/* + * Internal OpenSSL-specific code + */ static unsigned long get_last_err(void) @@ -58,43 +67,37 @@ get_last_err(void) return err; } -void -rb_ssl_shutdown(rb_fde_t *F) -{ - int i; - if(F == NULL || F->ssl == NULL) - return; - SSL_set_shutdown((SSL *) F->ssl, SSL_RECEIVED_SHUTDOWN); - - for(i = 0; i < 4; i++) - { - if(SSL_shutdown((SSL *) F->ssl)) - break; - } - get_last_err(); - SSL_free((SSL *) F->ssl); -} - -unsigned int -rb_ssl_handshake_count(rb_fde_t *F) -{ - return F->handshake_count; -} - -void -rb_ssl_clear_handshake_count(rb_fde_t *F) -{ - F->handshake_count = 0; -} - static void -rb_ssl_timeout(rb_fde_t *F, void *notused) +rb_ssl_accept_common(rb_fde_t *new_F) { - lrb_assert(F->accept != NULL); - F->accept->callback(F, RB_ERR_TIMEOUT, NULL, 0, F->accept->data); + int ssl_err; + if((ssl_err = SSL_accept((SSL *) new_F->ssl)) <= 0) + { + switch (ssl_err = SSL_get_error((SSL *) new_F->ssl, ssl_err)) + { + case SSL_ERROR_SYSCALL: + if(rb_ignore_errno(errno)) + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + { + new_F->ssl_errno = get_last_err(); + rb_setselect(new_F, RB_SELECT_READ | RB_SELECT_WRITE, + rb_ssl_tryaccept, NULL); + return; + } + default: + new_F->ssl_errno = get_last_err(); + new_F->accept->callback(new_F, RB_ERROR_SSL, NULL, 0, new_F->accept->data); + return; + } + } + else + { + new_F->handshake_count++; + rb_ssl_tryaccept(new_F, NULL); + } } - static void rb_ssl_tryaccept(rb_fde_t *F, void *data) { @@ -141,74 +144,97 @@ rb_ssl_tryaccept(rb_fde_t *F, void *data) } +static void +rb_ssl_tryconn_cb(rb_fde_t *F, void *data) +{ + struct ssl_connect *sconn = data; + int ssl_err; + if(!SSL_is_init_finished((SSL *) F->ssl)) + { + if((ssl_err = SSL_connect((SSL *) F->ssl)) <= 0) + { + switch (ssl_err = SSL_get_error((SSL *) F->ssl, ssl_err)) + { + case SSL_ERROR_SYSCALL: + if(rb_ignore_errno(errno)) + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + { + F->ssl_errno = get_last_err(); + rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, + rb_ssl_tryconn_cb, sconn); + return; + } + default: + F->ssl_errno = get_last_err(); + rb_ssl_connect_realcb(F, RB_ERROR_SSL, sconn); + return; + } + } + else + { + F->handshake_count++; + rb_ssl_connect_realcb(F, RB_OK, sconn); + } + } +} static void -rb_ssl_accept_common(rb_fde_t *new_F) +rb_ssl_tryconn(rb_fde_t *F, int status, void *data) { + struct ssl_connect *sconn = data; int ssl_err; - if((ssl_err = SSL_accept((SSL *) new_F->ssl)) <= 0) + if(status != RB_OK) { - switch (ssl_err = SSL_get_error((SSL *) new_F->ssl, ssl_err)) + rb_ssl_connect_realcb(F, status, sconn); + return; + } + + F->type |= RB_FD_SSL; + 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) + { + switch (ssl_err = SSL_get_error((SSL *) F->ssl, ssl_err)) { case SSL_ERROR_SYSCALL: if(rb_ignore_errno(errno)) case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: { - new_F->ssl_errno = get_last_err(); - rb_setselect(new_F, RB_SELECT_READ | RB_SELECT_WRITE, - rb_ssl_tryaccept, NULL); + F->ssl_errno = get_last_err(); + rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, + rb_ssl_tryconn_cb, sconn); return; } default: - new_F->ssl_errno = get_last_err(); - new_F->accept->callback(new_F, RB_ERROR_SSL, NULL, 0, new_F->accept->data); + F->ssl_errno = get_last_err(); + rb_ssl_connect_realcb(F, RB_ERROR_SSL, sconn); return; } } else { - new_F->handshake_count++; - rb_ssl_tryaccept(new_F, NULL); + F->handshake_count++; + rb_ssl_connect_realcb(F, RB_OK, sconn); } } -void -rb_ssl_start_accepted(rb_fde_t *new_F, ACCB * cb, void *data, int timeout) +static const char * +get_ssl_error(unsigned long err) { - new_F->type |= RB_FD_SSL; - new_F->ssl = SSL_new(ssl_ctx); - new_F->accept = rb_malloc(sizeof(struct acceptdata)); + static char buf[512]; - new_F->accept->callback = cb; - new_F->accept->data = data; - rb_settimeout(new_F, timeout, rb_ssl_timeout, NULL); - - 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); + ERR_error_string_n(err, buf, sizeof buf); + return buf; } - - - -void -rb_ssl_accept_setup(rb_fde_t *F, rb_fde_t *new_F, struct sockaddr *st, int addrlen) +static int +verify_accept_all_cb(int preverify_ok, X509_STORE_CTX *x509_ctx) { - new_F->type |= RB_FD_SSL; - new_F->ssl = SSL_new(ssl_ctx); - new_F->accept = rb_malloc(sizeof(struct acceptdata)); - - new_F->accept->callback = F->accept->callback; - new_F->accept->data = F->accept->data; - rb_settimeout(new_F, 10, rb_ssl_timeout, NULL); - memcpy(&new_F->accept->S, st, addrlen); - 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); + return 1; } static ssize_t @@ -258,31 +284,27 @@ rb_ssl_read_or_write(int r_or_w, rb_fde_t *F, void *rbuf, const void *wbuf, size return ret; } -ssize_t -rb_ssl_read(rb_fde_t *F, void *buf, size_t count) -{ - return rb_ssl_read_or_write(0, F, buf, NULL, count); -} -ssize_t -rb_ssl_write(rb_fde_t *F, const void *buf, size_t count) -{ - return rb_ssl_read_or_write(1, F, NULL, buf, count); -} -static int -verify_accept_all_cb(int preverify_ok, X509_STORE_CTX *x509_ctx) -{ - return 1; -} +/* + * External OpenSSL-specific code + */ -static const char * -get_ssl_error(unsigned long err) +void +rb_ssl_shutdown(rb_fde_t *F) { - static char buf[512]; + int i; + if(F == NULL || F->ssl == NULL) + return; + SSL_set_shutdown((SSL *) F->ssl, SSL_RECEIVED_SHUTDOWN); - ERR_error_string_n(err, buf, sizeof buf); - return buf; + for(i = 0; i < 4; i++) + { + if(SSL_shutdown((SSL *) F->ssl)) + break; + } + get_last_err(); + SSL_free((SSL *) F->ssl); } int @@ -427,173 +449,6 @@ rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, c return 1; } -int -rb_ssl_listen(rb_fde_t *F, int backlog, int defer_accept) -{ - int result; - - result = rb_listen(F, backlog, defer_accept); - F->type = RB_FD_SOCKET | RB_FD_LISTEN | RB_FD_SSL; - - return result; -} - -static void -rb_ssl_connect_realcb(rb_fde_t *F, int status, struct ssl_connect *sconn) -{ - F->connect->callback = sconn->callback; - F->connect->data = sconn->data; - rb_free(sconn); - rb_connect_callback(F, status); -} - -static void -rb_ssl_tryconn_timeout_cb(rb_fde_t *F, void *data) -{ - rb_ssl_connect_realcb(F, RB_ERR_TIMEOUT, data); -} - -static void -rb_ssl_tryconn_cb(rb_fde_t *F, void *data) -{ - struct ssl_connect *sconn = data; - int ssl_err; - if(!SSL_is_init_finished((SSL *) F->ssl)) - { - if((ssl_err = SSL_connect((SSL *) F->ssl)) <= 0) - { - switch (ssl_err = SSL_get_error((SSL *) F->ssl, ssl_err)) - { - case SSL_ERROR_SYSCALL: - if(rb_ignore_errno(errno)) - case SSL_ERROR_WANT_READ: - case SSL_ERROR_WANT_WRITE: - { - F->ssl_errno = get_last_err(); - rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, - rb_ssl_tryconn_cb, sconn); - return; - } - default: - F->ssl_errno = get_last_err(); - rb_ssl_connect_realcb(F, RB_ERROR_SSL, sconn); - return; - } - } - else - { - F->handshake_count++; - rb_ssl_connect_realcb(F, RB_OK, sconn); - } - } -} - -static void -rb_ssl_tryconn(rb_fde_t *F, int status, void *data) -{ - struct ssl_connect *sconn = data; - int ssl_err; - if(status != RB_OK) - { - rb_ssl_connect_realcb(F, status, sconn); - return; - } - - F->type |= RB_FD_SSL; - 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) - { - switch (ssl_err = SSL_get_error((SSL *) F->ssl, ssl_err)) - { - case SSL_ERROR_SYSCALL: - if(rb_ignore_errno(errno)) - case SSL_ERROR_WANT_READ: - case SSL_ERROR_WANT_WRITE: - { - F->ssl_errno = get_last_err(); - rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, - rb_ssl_tryconn_cb, sconn); - return; - } - default: - F->ssl_errno = get_last_err(); - rb_ssl_connect_realcb(F, RB_ERROR_SSL, sconn); - return; - } - } - else - { - F->handshake_count++; - rb_ssl_connect_realcb(F, RB_OK, sconn); - } -} - -void -rb_connect_tcp_ssl(rb_fde_t *F, struct sockaddr *dest, - struct sockaddr *clocal, int socklen, CNCB * callback, void *data, int timeout) -{ - struct ssl_connect *sconn; - if(F == NULL) - return; - - sconn = rb_malloc(sizeof(struct ssl_connect)); - sconn->data = data; - sconn->callback = callback; - sconn->timeout = timeout; - rb_connect_tcp(F, dest, clocal, socklen, rb_ssl_tryconn, sconn, timeout); - -} - -void -rb_ssl_start_connected(rb_fde_t *F, CNCB * callback, void *data, int timeout) -{ - struct ssl_connect *sconn; - int ssl_err; - if(F == NULL) - return; - - sconn = rb_malloc(sizeof(struct ssl_connect)); - sconn->data = data; - sconn->callback = callback; - sconn->timeout = timeout; - F->connect = rb_malloc(sizeof(struct conndata)); - F->connect->callback = callback; - F->connect->data = data; - F->type |= RB_FD_SSL; - 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) - { - switch (ssl_err = SSL_get_error((SSL *) F->ssl, ssl_err)) - { - case SSL_ERROR_SYSCALL: - if(rb_ignore_errno(errno)) - case SSL_ERROR_WANT_READ: - case SSL_ERROR_WANT_WRITE: - { - F->ssl_errno = get_last_err(); - rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, - rb_ssl_tryconn_cb, sconn); - return; - } - default: - F->ssl_errno = get_last_err(); - rb_ssl_connect_realcb(F, RB_ERROR_SSL, sconn); - return; - } - } - else - { - rb_ssl_connect_realcb(F, RB_OK, sconn); - } -} - int rb_init_prng(const char *path, prng_seed_t seed_type) { @@ -698,12 +553,6 @@ rb_get_ssl_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN], int method) return (int) len; } -int -rb_supports_ssl(void) -{ - return 1; -} - void rb_get_ssl_info(char *buf, size_t len) { @@ -737,4 +586,177 @@ rb_ssl_get_cipher(rb_fde_t *F) return buf; } +ssize_t +rb_ssl_read(rb_fde_t *F, void *buf, size_t count) +{ + return rb_ssl_read_or_write(0, F, buf, NULL, count); +} + +ssize_t +rb_ssl_write(rb_fde_t *F, const void *buf, size_t count) +{ + return rb_ssl_read_or_write(1, F, NULL, buf, count); +} + +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_ctx); + new_F->accept = rb_malloc(sizeof(struct acceptdata)); + + new_F->accept->callback = cb; + new_F->accept->data = data; + rb_settimeout(new_F, timeout, rb_ssl_timeout, NULL); + + 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); +} + +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_ctx); + new_F->accept = rb_malloc(sizeof(struct acceptdata)); + + new_F->accept->callback = F->accept->callback; + new_F->accept->data = F->accept->data; + rb_settimeout(new_F, 10, rb_ssl_timeout, NULL); + memcpy(&new_F->accept->S, st, addrlen); + 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); +} + +void +rb_ssl_start_connected(rb_fde_t *F, CNCB * callback, void *data, int timeout) +{ + struct ssl_connect *sconn; + int ssl_err; + if(F == NULL) + return; + + sconn = rb_malloc(sizeof(struct ssl_connect)); + sconn->data = data; + sconn->callback = callback; + sconn->timeout = timeout; + F->connect = rb_malloc(sizeof(struct conndata)); + F->connect->callback = callback; + F->connect->data = data; + F->type |= RB_FD_SSL; + 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) + { + switch (ssl_err = SSL_get_error((SSL *) F->ssl, ssl_err)) + { + case SSL_ERROR_SYSCALL: + if(rb_ignore_errno(errno)) + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + { + F->ssl_errno = get_last_err(); + rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, + rb_ssl_tryconn_cb, sconn); + return; + } + default: + F->ssl_errno = get_last_err(); + rb_ssl_connect_realcb(F, RB_ERROR_SSL, sconn); + return; + } + } + else + { + rb_ssl_connect_realcb(F, RB_OK, sconn); + } +} + + + +/* + * Internal library-agnostic code + */ + +static void +rb_ssl_connect_realcb(rb_fde_t *F, int status, struct ssl_connect *sconn) +{ + F->connect->callback = sconn->callback; + F->connect->data = sconn->data; + rb_free(sconn); + rb_connect_callback(F, status); +} + +static void +rb_ssl_timeout(rb_fde_t *F, void *notused) +{ + lrb_assert(F->accept != NULL); + F->accept->callback(F, RB_ERR_TIMEOUT, NULL, 0, F->accept->data); +} + +static void +rb_ssl_tryconn_timeout_cb(rb_fde_t *F, void *data) +{ + rb_ssl_connect_realcb(F, RB_ERR_TIMEOUT, data); +} + + + +/* + * External library-agnostic code + */ + +int +rb_supports_ssl(void) +{ + return 1; +} + +unsigned int +rb_ssl_handshake_count(rb_fde_t *F) +{ + return F->handshake_count; +} + +void +rb_ssl_clear_handshake_count(rb_fde_t *F) +{ + F->handshake_count = 0; +} + +int +rb_ssl_listen(rb_fde_t *F, int backlog, int defer_accept) +{ + int result; + + result = rb_listen(F, backlog, defer_accept); + F->type = RB_FD_SOCKET | RB_FD_LISTEN | RB_FD_SSL; + + return result; +} + +void +rb_connect_tcp_ssl(rb_fde_t *F, struct sockaddr *dest, + struct sockaddr *clocal, int socklen, CNCB * callback, void *data, int timeout) +{ + struct ssl_connect *sconn; + if(F == NULL) + return; + + sconn = rb_malloc(sizeof(struct ssl_connect)); + sconn->data = data; + sconn->callback = callback; + sconn->timeout = timeout; + rb_connect_tcp(F, dest, clocal, socklen, rb_ssl_tryconn, sconn, timeout); + +} + #endif /* HAVE_OPESSL */ From a61e06e1d12dc78920bae5d72b71c4dc3cf8f1ed Mon Sep 17 00:00:00 2001 From: Aaron Jones Date: Thu, 15 Sep 2016 16:35:47 +0000 Subject: [PATCH 06/25] OpenSSL: Add const-correctness to function and variable declarations. --- libratbox/src/openssl.c | 87 ++++++++++++++++++++--------------------- 1 file changed, 42 insertions(+), 45 deletions(-) diff --git a/libratbox/src/openssl.c b/libratbox/src/openssl.c index f2c4429d..0e88949e 100644 --- a/libratbox/src/openssl.c +++ b/libratbox/src/openssl.c @@ -68,7 +68,7 @@ get_last_err(void) } static void -rb_ssl_accept_common(rb_fde_t *new_F) +rb_ssl_accept_common(rb_fde_t *const new_F) { int ssl_err; if((ssl_err = SSL_accept((SSL *) new_F->ssl)) <= 0) @@ -99,12 +99,11 @@ rb_ssl_accept_common(rb_fde_t *new_F) } static void -rb_ssl_tryaccept(rb_fde_t *F, void *data) +rb_ssl_tryaccept(rb_fde_t *const F, void *const data) { int ssl_err; lrb_assert(F->accept != NULL); int flags; - struct acceptdata *ad; if(!SSL_is_init_finished((SSL *) F->ssl)) { @@ -137,17 +136,16 @@ rb_ssl_tryaccept(rb_fde_t *F, void *data) rb_settimeout(F, 0, NULL, NULL); rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, NULL, NULL); - ad = F->accept; + struct acceptdata *const ad = F->accept; F->accept = NULL; ad->callback(F, RB_OK, (struct sockaddr *)&ad->S, ad->addrlen, ad->data); rb_free(ad); - } static void -rb_ssl_tryconn_cb(rb_fde_t *F, void *data) +rb_ssl_tryconn_cb(rb_fde_t *const F, void *const data) { - struct ssl_connect *sconn = data; + struct ssl_connect *const sconn = data; int ssl_err; if(!SSL_is_init_finished((SSL *) F->ssl)) { @@ -180,9 +178,9 @@ rb_ssl_tryconn_cb(rb_fde_t *F, void *data) } static void -rb_ssl_tryconn(rb_fde_t *F, int status, void *data) +rb_ssl_tryconn(rb_fde_t *const F, const int status, void *const data) { - struct ssl_connect *sconn = data; + struct ssl_connect *const sconn = data; int ssl_err; if(status != RB_OK) { @@ -232,17 +230,17 @@ get_ssl_error(unsigned long err) } static int -verify_accept_all_cb(int preverify_ok, X509_STORE_CTX *x509_ctx) +verify_accept_all_cb(const int preverify_ok, X509_STORE_CTX *const x509_ctx) { return 1; } static ssize_t -rb_ssl_read_or_write(int r_or_w, rb_fde_t *F, void *rbuf, const void *wbuf, size_t count) +rb_ssl_read_or_write(const int r_or_w, rb_fde_t *const F, void *const rbuf, const void *const wbuf, const size_t count) { ssize_t ret; unsigned long err; - SSL *ssl = F->ssl; + SSL *const ssl = F->ssl; if(r_or_w == 0) ret = (ssize_t) SSL_read(ssl, rbuf, (int)count); @@ -291,7 +289,7 @@ rb_ssl_read_or_write(int r_or_w, rb_fde_t *F, void *rbuf, const void *wbuf, size */ void -rb_ssl_shutdown(rb_fde_t *F) +rb_ssl_shutdown(rb_fde_t *const F) { int i; if(F == NULL || F->ssl == NULL) @@ -324,7 +322,7 @@ rb_init_ssl(void) } int -rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, const char *cipher_list) +rb_setup_ssl_server(const char *const cert, const char *keyfile, const char *const dhfile, const char *cipher_list) { if(cert == NULL) { @@ -389,7 +387,7 @@ rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, c * Set manual ECDHE curve on OpenSSL 1.0.0 & 1.0.1, but make sure it's actually available */ #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 *const key = EC_KEY_new_by_curve_name(NID_secp384r1); if(key) { SSL_CTX_set_tmp_ecdh(ssl_ctx_new, key); EC_KEY_free(key); @@ -419,7 +417,7 @@ rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, c if(dhfile != NULL) { /* DH parameters aren't necessary, but they are nice..if they didn't pass one..that is their problem */ - FILE *fp = fopen(dhfile, "r"); + FILE *const fp = fopen(dhfile, "r"); DH *dh = NULL; if(fp == NULL) @@ -450,7 +448,7 @@ rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, c } int -rb_init_prng(const char *path, prng_seed_t seed_type) +rb_init_prng(const char *const path, prng_seed_t seed_type) { if(seed_type == RB_PRNG_DEFAULT) { @@ -481,7 +479,7 @@ rb_init_prng(const char *path, prng_seed_t seed_type) } int -rb_get_random(void *buf, size_t length) +rb_get_random(void *const buf, const size_t length) { int ret; @@ -494,17 +492,16 @@ rb_get_random(void *buf, size_t length) } const char * -rb_get_ssl_strerror(rb_fde_t *F) +rb_get_ssl_strerror(rb_fde_t *const F) { return get_ssl_error(F->ssl_errno); } int -rb_get_ssl_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN], int method) +rb_get_ssl_certfp(rb_fde_t *const F, uint8_t certfp[const RB_SSL_CERTFP_LEN], const int method) { const EVP_MD *evp; unsigned int len; - X509 *cert; int res; if(F->ssl == NULL) @@ -528,7 +525,7 @@ rb_get_ssl_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN], int method) return 0; } - cert = SSL_get_peer_certificate((SSL *) F->ssl); + X509 *const cert = SSL_get_peer_certificate((SSL *) F->ssl); if(cert == NULL) return 0; @@ -554,7 +551,7 @@ rb_get_ssl_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN], int method) } void -rb_get_ssl_info(char *buf, size_t len) +rb_get_ssl_info(char *const buf, const size_t len) { #ifdef LRB_SSL_FULL_VERSION_INFO if (LRB_SSL_VNUM_RUNTIME == LRB_SSL_VNUM_COMPILETIME) @@ -571,15 +568,15 @@ rb_get_ssl_info(char *buf, size_t len) } const char * -rb_ssl_get_cipher(rb_fde_t *F) +rb_ssl_get_cipher(rb_fde_t *const F) { if(F == NULL || F->ssl == NULL) return NULL; static char buf[512]; - const char *version = SSL_get_version(F->ssl); - const char *cipher = SSL_get_cipher_name(F->ssl); + const char *const version = SSL_get_version(F->ssl); + const char *const cipher = SSL_get_cipher_name(F->ssl); (void) rb_snprintf(buf, sizeof buf, "%s, %s", version, cipher); @@ -587,19 +584,19 @@ rb_ssl_get_cipher(rb_fde_t *F) } ssize_t -rb_ssl_read(rb_fde_t *F, void *buf, size_t count) +rb_ssl_read(rb_fde_t *const F, void *const buf, const size_t count) { return rb_ssl_read_or_write(0, F, buf, NULL, count); } ssize_t -rb_ssl_write(rb_fde_t *F, const void *buf, size_t count) +rb_ssl_write(rb_fde_t *const F, const void *const buf, const size_t count) { return rb_ssl_read_or_write(1, F, NULL, buf, count); } void -rb_ssl_start_accepted(rb_fde_t *new_F, ACCB * cb, void *data, int timeout) +rb_ssl_start_accepted(rb_fde_t *const new_F, ACCB *const cb, void *const data, const int timeout) { new_F->type |= RB_FD_SSL; new_F->ssl = SSL_new(ssl_ctx); @@ -616,7 +613,7 @@ rb_ssl_start_accepted(rb_fde_t *new_F, ACCB * cb, void *data, int timeout) } 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 *const F, rb_fde_t *const new_F, struct sockaddr *const st, const int addrlen) { new_F->type |= RB_FD_SSL; new_F->ssl = SSL_new(ssl_ctx); @@ -634,17 +631,18 @@ rb_ssl_accept_setup(rb_fde_t *F, rb_fde_t *new_F, struct sockaddr *st, int addrl } void -rb_ssl_start_connected(rb_fde_t *F, CNCB * callback, void *data, int timeout) +rb_ssl_start_connected(rb_fde_t *const F, CNCB *const callback, void *const data, const int timeout) { - struct ssl_connect *sconn; - int ssl_err; if(F == NULL) return; - sconn = rb_malloc(sizeof(struct ssl_connect)); + int ssl_err; + + struct ssl_connect *const sconn = rb_malloc(sizeof *sconn); sconn->data = data; sconn->callback = callback; sconn->timeout = timeout; + F->connect = rb_malloc(sizeof(struct conndata)); F->connect->callback = callback; F->connect->data = data; @@ -687,7 +685,7 @@ rb_ssl_start_connected(rb_fde_t *F, CNCB * callback, void *data, int timeout) */ static void -rb_ssl_connect_realcb(rb_fde_t *F, int status, struct ssl_connect *sconn) +rb_ssl_connect_realcb(rb_fde_t *const F, const int status, struct ssl_connect *const sconn) { F->connect->callback = sconn->callback; F->connect->data = sconn->data; @@ -696,14 +694,14 @@ rb_ssl_connect_realcb(rb_fde_t *F, int status, struct ssl_connect *sconn) } static void -rb_ssl_timeout(rb_fde_t *F, void *notused) +rb_ssl_timeout(rb_fde_t *const F, void *const notused) { lrb_assert(F->accept != NULL); F->accept->callback(F, RB_ERR_TIMEOUT, NULL, 0, F->accept->data); } static void -rb_ssl_tryconn_timeout_cb(rb_fde_t *F, void *data) +rb_ssl_tryconn_timeout_cb(rb_fde_t *const F, void *const data) { rb_ssl_connect_realcb(F, RB_ERR_TIMEOUT, data); } @@ -721,19 +719,19 @@ rb_supports_ssl(void) } unsigned int -rb_ssl_handshake_count(rb_fde_t *F) +rb_ssl_handshake_count(rb_fde_t *const F) { return F->handshake_count; } void -rb_ssl_clear_handshake_count(rb_fde_t *F) +rb_ssl_clear_handshake_count(rb_fde_t *const F) { F->handshake_count = 0; } int -rb_ssl_listen(rb_fde_t *F, int backlog, int defer_accept) +rb_ssl_listen(rb_fde_t *const F, const int backlog, const int defer_accept) { int result; @@ -744,19 +742,18 @@ rb_ssl_listen(rb_fde_t *F, int backlog, int defer_accept) } void -rb_connect_tcp_ssl(rb_fde_t *F, struct sockaddr *dest, - struct sockaddr *clocal, int socklen, CNCB * callback, void *data, int timeout) +rb_connect_tcp_ssl(rb_fde_t *const F, struct sockaddr *const dest, struct sockaddr *const clocal, + const int socklen, CNCB *const callback, void *const data, const int timeout) { - struct ssl_connect *sconn; if(F == NULL) return; - sconn = rb_malloc(sizeof(struct ssl_connect)); + struct ssl_connect *const sconn = rb_malloc(sizeof *sconn); sconn->data = data; sconn->callback = callback; sconn->timeout = timeout; - rb_connect_tcp(F, dest, clocal, socklen, rb_ssl_tryconn, sconn, timeout); + rb_connect_tcp(F, dest, clocal, socklen, rb_ssl_tryconn, sconn, timeout); } #endif /* HAVE_OPESSL */ From e569720fe1666843596cbc7f48d86bb6295e8355 Mon Sep 17 00:00:00 2001 From: Aaron Jones Date: Thu, 15 Sep 2016 16:54:06 +0000 Subject: [PATCH 07/25] OpenSSL: Misc code cleanups Make use of C99 for loop initialisers, declarations with immediate rvalues, etc. --- libratbox/src/openssl.c | 152 +++++++++++++++++++++------------------- 1 file changed, 80 insertions(+), 72 deletions(-) diff --git a/libratbox/src/openssl.c b/libratbox/src/openssl.c index 0e88949e..3ae97108 100644 --- a/libratbox/src/openssl.c +++ b/libratbox/src/openssl.c @@ -56,13 +56,10 @@ static void rb_ssl_tryaccept(rb_fde_t *, void *); static unsigned long get_last_err(void) { - unsigned long t_err, err = 0; - err = ERR_get_error(); - if(err == 0) - return 0; + unsigned long err_saved, err = 0; - while((t_err = ERR_get_error()) > 0) - err = t_err; + while((err_saved = ERR_get_error()) != 0) + err = err_saved; return err; } @@ -70,10 +67,11 @@ get_last_err(void) static void rb_ssl_accept_common(rb_fde_t *const new_F) { - int ssl_err; - if((ssl_err = SSL_accept((SSL *) new_F->ssl)) <= 0) + int ssl_err = SSL_accept((SSL *) new_F->ssl); + + if(ssl_err <= 0) { - switch (ssl_err = SSL_get_error((SSL *) new_F->ssl, ssl_err)) + switch((ssl_err = SSL_get_error((SSL *) new_F->ssl, ssl_err))) { case SSL_ERROR_SYSCALL: if(rb_ignore_errno(errno)) @@ -101,15 +99,16 @@ rb_ssl_accept_common(rb_fde_t *const new_F) static void rb_ssl_tryaccept(rb_fde_t *const F, void *const data) { - int ssl_err; lrb_assert(F->accept != NULL); - int flags; - if(!SSL_is_init_finished((SSL *) F->ssl)) + if(! SSL_is_init_finished((SSL *) F->ssl)) { - if((ssl_err = SSL_accept((SSL *) F->ssl)) <= 0) + int flags; + int ssl_err = SSL_accept((SSL *) F->ssl); + + if(ssl_err <= 0) { - switch (ssl_err = SSL_get_error((SSL *) F->ssl, ssl_err)) + switch(ssl_err = SSL_get_error((SSL *) F->ssl, ssl_err)) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: @@ -133,6 +132,7 @@ rb_ssl_tryaccept(rb_fde_t *const F, void *const data) else F->handshake_count++; } + rb_settimeout(F, 0, NULL, NULL); rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, NULL, NULL); @@ -145,13 +145,14 @@ rb_ssl_tryaccept(rb_fde_t *const F, void *const data) static void rb_ssl_tryconn_cb(rb_fde_t *const F, void *const data) { - struct ssl_connect *const sconn = data; - int ssl_err; - if(!SSL_is_init_finished((SSL *) F->ssl)) + if(! SSL_is_init_finished((SSL *) F->ssl)) { - if((ssl_err = SSL_connect((SSL *) F->ssl)) <= 0) + struct ssl_connect *const sconn = data; + int ssl_err = SSL_connect((SSL *) F->ssl); + + if(ssl_err <= 0) { - switch (ssl_err = SSL_get_error((SSL *) F->ssl, ssl_err)) + switch(ssl_err = SSL_get_error((SSL *) F->ssl, ssl_err)) { case SSL_ERROR_SYSCALL: if(rb_ignore_errno(errno)) @@ -181,7 +182,7 @@ static void rb_ssl_tryconn(rb_fde_t *const F, const int status, void *const data) { struct ssl_connect *const sconn = data; - int ssl_err; + if(status != RB_OK) { rb_ssl_connect_realcb(F, status, sconn); @@ -189,13 +190,18 @@ rb_ssl_tryconn(rb_fde_t *const F, const int status, void *const data) } F->type |= RB_FD_SSL; + 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) + + int ssl_err = SSL_connect((SSL *) F->ssl); + + if(ssl_err <= 0) { - switch (ssl_err = SSL_get_error((SSL *) F->ssl, ssl_err)) + switch(ssl_err = SSL_get_error((SSL *) F->ssl, ssl_err)) { case SSL_ERROR_SYSCALL: if(rb_ignore_errno(errno)) @@ -226,6 +232,7 @@ get_ssl_error(unsigned long err) static char buf[512]; ERR_error_string_n(err, buf, sizeof buf); + return buf; } @@ -249,7 +256,7 @@ rb_ssl_read_or_write(const int r_or_w, rb_fde_t *const F, void *const rbuf, cons if(ret < 0) { - switch (SSL_get_error(ssl, ret)) + switch(SSL_get_error(ssl, ret)) { case SSL_ERROR_WANT_READ: errno = EAGAIN; @@ -271,6 +278,7 @@ rb_ssl_read_or_write(const int r_or_w, rb_fde_t *const F, void *const rbuf, cons err = get_last_err(); break; } + F->ssl_errno = err; if(err > 0) { @@ -291,16 +299,17 @@ rb_ssl_read_or_write(const int r_or_w, rb_fde_t *const F, void *const rbuf, cons void rb_ssl_shutdown(rb_fde_t *const F) { - int i; if(F == NULL || F->ssl == NULL) return; + SSL_set_shutdown((SSL *) F->ssl, SSL_RECEIVED_SHUTDOWN); - for(i = 0; i < 4; i++) + for(int i = 0; i < 4; i++) { if(SSL_shutdown((SSL *) F->ssl)) break; } + get_last_err(); SSL_free((SSL *) F->ssl); } @@ -308,8 +317,6 @@ rb_ssl_shutdown(rb_fde_t *const F) int rb_init_ssl(void) { - char libratbox_data[] = "libratbox data"; - /* * OpenSSL 1.1.0 and above automatically initialises itself with sane defaults */ @@ -460,7 +467,7 @@ rb_init_prng(const char *const path, prng_seed_t seed_type) if(path == NULL) return RAND_status(); - switch (seed_type) + switch(seed_type) { case RB_PRNG_FILE: if(RAND_load_file(path, -1) == -1) @@ -500,13 +507,12 @@ rb_get_ssl_strerror(rb_fde_t *const F) int rb_get_ssl_certfp(rb_fde_t *const F, uint8_t certfp[const RB_SSL_CERTFP_LEN], const int method) { - const EVP_MD *evp; - unsigned int len; - int res; - if(F->ssl == NULL) return 0; + const EVP_MD *evp; + unsigned int len; + switch(method) { case RB_SSL_CERTFP_METH_SHA1: @@ -529,7 +535,7 @@ rb_get_ssl_certfp(rb_fde_t *const F, uint8_t certfp[const RB_SSL_CERTFP_LEN], co if(cert == NULL) return 0; - res = SSL_get_verify_result((SSL *) F->ssl); + int res = SSL_get_verify_result((SSL *) F->ssl); switch(res) { case X509_V_OK: @@ -554,16 +560,16 @@ void rb_get_ssl_info(char *const buf, const size_t len) { #ifdef LRB_SSL_FULL_VERSION_INFO - if (LRB_SSL_VNUM_RUNTIME == LRB_SSL_VNUM_COMPILETIME) - rb_snprintf(buf, len, "OpenSSL: compiled 0x%lx, library %s", - LRB_SSL_VNUM_COMPILETIME, LRB_SSL_VTEXT_COMPILETIME); + if(LRB_SSL_VNUM_RUNTIME == LRB_SSL_VNUM_COMPILETIME) + (void) rb_snprintf(buf, len, "OpenSSL: compiled 0x%lx, library %s", + LRB_SSL_VNUM_COMPILETIME, LRB_SSL_VTEXT_COMPILETIME); else - rb_snprintf(buf, len, "OpenSSL: compiled (0x%lx, %s), library (0x%lx, %s)", - LRB_SSL_VNUM_COMPILETIME, LRB_SSL_VTEXT_COMPILETIME, - LRB_SSL_VNUM_RUNTIME, LRB_SSL_VTEXT_RUNTIME); + (void) rb_snprintf(buf, len, "OpenSSL: compiled (0x%lx, %s), library (0x%lx, %s)", + LRB_SSL_VNUM_COMPILETIME, LRB_SSL_VTEXT_COMPILETIME, + LRB_SSL_VNUM_RUNTIME, LRB_SSL_VTEXT_RUNTIME); #else - rb_snprintf(buf, len, "OpenSSL: compiled 0x%lx, library %s", - LRB_SSL_VNUM_COMPILETIME, LRB_SSL_VTEXT_RUNTIME); + (void) rb_snprintf(buf, len, "OpenSSL: compiled 0x%lx, library %s", + LRB_SSL_VNUM_COMPILETIME, LRB_SSL_VTEXT_RUNTIME); #endif } @@ -596,38 +602,40 @@ rb_ssl_write(rb_fde_t *const F, const void *const buf, const size_t count) } void -rb_ssl_start_accepted(rb_fde_t *const new_F, ACCB *const cb, void *const data, const int timeout) +rb_ssl_start_accepted(rb_fde_t *const F, ACCB *const cb, void *const data, const int timeout) { - new_F->type |= RB_FD_SSL; - new_F->ssl = SSL_new(ssl_ctx); - new_F->accept = rb_malloc(sizeof(struct acceptdata)); + F->type |= RB_FD_SSL; - new_F->accept->callback = cb; - new_F->accept->data = data; - rb_settimeout(new_F, timeout, rb_ssl_timeout, NULL); + F->accept = rb_malloc(sizeof(struct acceptdata)); + F->accept->callback = cb; + F->accept->data = data; + F->accept->addrlen = 0; + (void) memset(&F->accept->S, 0x00, sizeof F->accept->S); - 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); + rb_settimeout(F, timeout, rb_ssl_timeout, NULL); + F->ssl = SSL_new(ssl_ctx); + SSL_set_fd((SSL *) F->ssl, rb_get_fd(F)); + SSL_set_accept_state((SSL *) F->ssl); + rb_ssl_accept_common(F); } void -rb_ssl_accept_setup(rb_fde_t *const F, rb_fde_t *const new_F, struct sockaddr *const st, const int addrlen) +rb_ssl_accept_setup(rb_fde_t *const srv_F, rb_fde_t *const cli_F, struct sockaddr *const st, const int addrlen) { - new_F->type |= RB_FD_SSL; - new_F->ssl = SSL_new(ssl_ctx); - new_F->accept = rb_malloc(sizeof(struct acceptdata)); + cli_F->type |= RB_FD_SSL; - new_F->accept->callback = F->accept->callback; - new_F->accept->data = F->accept->data; - rb_settimeout(new_F, 10, rb_ssl_timeout, NULL); - memcpy(&new_F->accept->S, st, addrlen); - new_F->accept->addrlen = addrlen; + cli_F->accept = rb_malloc(sizeof(struct acceptdata)); + cli_F->accept->callback = srv_F->accept->callback; + cli_F->accept->data = srv_F->accept->data; + cli_F->accept->addrlen = addrlen; + (void) memset(&cli_F->accept->S, 0x00, sizeof cli_F->accept->S); + (void) memcpy(&cli_F->accept->S, st, 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); + rb_settimeout(cli_F, 10, rb_ssl_timeout, NULL); + cli_F->ssl = SSL_new(ssl_ctx); + SSL_set_fd((SSL *) cli_F->ssl, rb_get_fd(cli_F)); + SSL_set_accept_state((SSL *) cli_F->ssl); + rb_ssl_accept_common(cli_F); } void @@ -636,8 +644,6 @@ rb_ssl_start_connected(rb_fde_t *const F, CNCB *const callback, void *const data if(F == NULL) return; - int ssl_err; - struct ssl_connect *const sconn = rb_malloc(sizeof *sconn); sconn->data = data; sconn->callback = callback; @@ -647,14 +653,17 @@ rb_ssl_start_connected(rb_fde_t *const F, CNCB *const callback, void *const data F->connect->callback = callback; F->connect->data = data; F->type |= RB_FD_SSL; - F->ssl = SSL_new(ssl_ctx); + rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn); + 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) + + int ssl_err = SSL_connect((SSL *) F->ssl); + + if(ssl_err <= 0) { - switch (ssl_err = SSL_get_error((SSL *) F->ssl, ssl_err)) + switch(ssl_err = SSL_get_error((SSL *) F->ssl, ssl_err)) { case SSL_ERROR_SYSCALL: if(rb_ignore_errno(errno)) @@ -733,9 +742,8 @@ rb_ssl_clear_handshake_count(rb_fde_t *const F) int rb_ssl_listen(rb_fde_t *const F, const int backlog, const int defer_accept) { - int result; + int result = rb_listen(F, backlog, defer_accept); - result = rb_listen(F, backlog, defer_accept); F->type = RB_FD_SOCKET | RB_FD_LISTEN | RB_FD_SSL; return result; From 4e9441a1cbff37f22d4cb1b3cc71a49d4dc1a77e Mon Sep 17 00:00:00 2001 From: Aaron Jones Date: Thu, 15 Sep 2016 17:06:05 +0000 Subject: [PATCH 08/25] OpenSSL: Add generic direction enum for negotiation setup. Also define an SSL_P(x) macro as in other backends and use that to refer to the client session context. --- libratbox/src/openssl.c | 103 ++++++++++++++++++++++++++-------------- 1 file changed, 67 insertions(+), 36 deletions(-) diff --git a/libratbox/src/openssl.c b/libratbox/src/openssl.c index 3ae97108..e3f199d8 100644 --- a/libratbox/src/openssl.c +++ b/libratbox/src/openssl.c @@ -33,6 +33,16 @@ #include "openssl_ratbox.h" +typedef enum +{ + RB_FD_TLS_DIRECTION_IN = 0, + RB_FD_TLS_DIRECTION_OUT = 1 +} rb_fd_tls_direction; + +#define SSL_P(x) ((SSL *)((x)->ssl)) + + + static SSL_CTX *ssl_ctx = NULL; struct ssl_connect @@ -46,6 +56,7 @@ static void rb_ssl_connect_realcb(rb_fde_t *, int, struct ssl_connect *); static void rb_ssl_tryconn_timeout_cb(rb_fde_t *, void *); static void rb_ssl_timeout(rb_fde_t *, void *); static void rb_ssl_tryaccept(rb_fde_t *, void *); +static const char *get_ssl_error(unsigned long); @@ -64,14 +75,41 @@ get_last_err(void) return err; } +static void +rb_ssl_init_fd(rb_fde_t *const F, const rb_fd_tls_direction dir) +{ + (void) get_last_err(); + + F->ssl = SSL_new(ssl_ctx); + + if(F->ssl == NULL) + { + rb_lib_log("%s: SSL_new: %s", __func__, get_ssl_error(get_last_err())); + rb_close(F); + return; + } + + switch(dir) + { + case RB_FD_TLS_DIRECTION_IN: + SSL_set_accept_state(SSL_P(F)); + break; + case RB_FD_TLS_DIRECTION_OUT: + SSL_set_connect_state(SSL_P(F)); + break; + } + + SSL_set_fd(SSL_P(F), rb_get_fd(F)); +} + static void rb_ssl_accept_common(rb_fde_t *const new_F) { - int ssl_err = SSL_accept((SSL *) new_F->ssl); + int ssl_err = SSL_accept(SSL_P(new_F)); if(ssl_err <= 0) { - switch((ssl_err = SSL_get_error((SSL *) new_F->ssl, ssl_err))) + switch((ssl_err = SSL_get_error(SSL_P(new_F), ssl_err))) { case SSL_ERROR_SYSCALL: if(rb_ignore_errno(errno)) @@ -101,14 +139,14 @@ rb_ssl_tryaccept(rb_fde_t *const F, void *const data) { lrb_assert(F->accept != NULL); - if(! SSL_is_init_finished((SSL *) F->ssl)) + if(! SSL_is_init_finished(SSL_P(F))) { int flags; - int ssl_err = SSL_accept((SSL *) F->ssl); + int ssl_err = SSL_accept(SSL_P(F)); if(ssl_err <= 0) { - switch(ssl_err = SSL_get_error((SSL *) F->ssl, ssl_err)) + switch(ssl_err = SSL_get_error(SSL_P(F), ssl_err)) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: @@ -145,14 +183,14 @@ rb_ssl_tryaccept(rb_fde_t *const F, void *const data) static void rb_ssl_tryconn_cb(rb_fde_t *const F, void *const data) { - if(! SSL_is_init_finished((SSL *) F->ssl)) + if(! SSL_is_init_finished(SSL_P(F))) { struct ssl_connect *const sconn = data; - int ssl_err = SSL_connect((SSL *) F->ssl); + int ssl_err = SSL_connect(SSL_P(F)); if(ssl_err <= 0) { - switch(ssl_err = SSL_get_error((SSL *) F->ssl, ssl_err)) + switch(ssl_err = SSL_get_error(SSL_P(F), ssl_err)) { case SSL_ERROR_SYSCALL: if(rb_ignore_errno(errno)) @@ -181,6 +219,8 @@ rb_ssl_tryconn_cb(rb_fde_t *const F, void *const data) static void rb_ssl_tryconn(rb_fde_t *const F, const int status, void *const data) { + lrb_assert(F != NULL); + struct ssl_connect *const sconn = data; if(status != RB_OK) @@ -191,17 +231,14 @@ rb_ssl_tryconn(rb_fde_t *const F, const int status, void *const data) F->type |= RB_FD_SSL; - 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); + rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_OUT); - int ssl_err = SSL_connect((SSL *) F->ssl); + int ssl_err = SSL_connect(SSL_P(F)); if(ssl_err <= 0) { - switch(ssl_err = SSL_get_error((SSL *) F->ssl, ssl_err)) + switch(ssl_err = SSL_get_error(SSL_P(F), ssl_err)) { case SSL_ERROR_SYSCALL: if(rb_ignore_errno(errno)) @@ -247,16 +284,15 @@ rb_ssl_read_or_write(const int r_or_w, rb_fde_t *const F, void *const rbuf, cons { ssize_t ret; unsigned long err; - SSL *const ssl = F->ssl; if(r_or_w == 0) - ret = (ssize_t) SSL_read(ssl, rbuf, (int)count); + ret = (ssize_t) SSL_read(SSL_P(F), rbuf, (int)count); else - ret = (ssize_t) SSL_write(ssl, wbuf, (int)count); + ret = (ssize_t) SSL_write(SSL_P(F), wbuf, (int)count); if(ret < 0) { - switch(SSL_get_error(ssl, ret)) + switch(SSL_get_error(SSL_P(F), ret)) { case SSL_ERROR_WANT_READ: errno = EAGAIN; @@ -302,16 +338,17 @@ rb_ssl_shutdown(rb_fde_t *const F) if(F == NULL || F->ssl == NULL) return; - SSL_set_shutdown((SSL *) F->ssl, SSL_RECEIVED_SHUTDOWN); + SSL_set_shutdown(SSL_P(F), SSL_RECEIVED_SHUTDOWN); for(int i = 0; i < 4; i++) { - if(SSL_shutdown((SSL *) F->ssl)) + if(SSL_shutdown(SSL_P(F))) break; } get_last_err(); - SSL_free((SSL *) F->ssl); + SSL_free(SSL_P(F)); + F->ssl = NULL; } int @@ -531,11 +568,11 @@ rb_get_ssl_certfp(rb_fde_t *const F, uint8_t certfp[const RB_SSL_CERTFP_LEN], co return 0; } - X509 *const cert = SSL_get_peer_certificate((SSL *) F->ssl); + X509 *const cert = SSL_get_peer_certificate(SSL_P(F)); if(cert == NULL) return 0; - int res = SSL_get_verify_result((SSL *) F->ssl); + int res = SSL_get_verify_result(SSL_P(F)); switch(res) { case X509_V_OK: @@ -581,8 +618,8 @@ rb_ssl_get_cipher(rb_fde_t *const F) static char buf[512]; - const char *const version = SSL_get_version(F->ssl); - const char *const cipher = SSL_get_cipher_name(F->ssl); + const char *const version = SSL_get_version(SSL_P(F)); + const char *const cipher = SSL_get_cipher_name(SSL_P(F)); (void) rb_snprintf(buf, sizeof buf, "%s, %s", version, cipher); @@ -613,9 +650,7 @@ rb_ssl_start_accepted(rb_fde_t *const F, ACCB *const cb, void *const data, const (void) memset(&F->accept->S, 0x00, sizeof F->accept->S); rb_settimeout(F, timeout, rb_ssl_timeout, NULL); - F->ssl = SSL_new(ssl_ctx); - SSL_set_fd((SSL *) F->ssl, rb_get_fd(F)); - SSL_set_accept_state((SSL *) F->ssl); + rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_IN); rb_ssl_accept_common(F); } @@ -632,9 +667,7 @@ rb_ssl_accept_setup(rb_fde_t *const srv_F, rb_fde_t *const cli_F, struct sockadd (void) memcpy(&cli_F->accept->S, st, addrlen); rb_settimeout(cli_F, 10, rb_ssl_timeout, NULL); - cli_F->ssl = SSL_new(ssl_ctx); - SSL_set_fd((SSL *) cli_F->ssl, rb_get_fd(cli_F)); - SSL_set_accept_state((SSL *) cli_F->ssl); + rb_ssl_init_fd(cli_F, RB_FD_TLS_DIRECTION_IN); rb_ssl_accept_common(cli_F); } @@ -655,15 +688,13 @@ rb_ssl_start_connected(rb_fde_t *const F, CNCB *const callback, void *const data F->type |= RB_FD_SSL; rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn); - F->ssl = SSL_new(ssl_ctx); - SSL_set_fd((SSL *) F->ssl, F->fd); - SSL_set_connect_state((SSL *) F->ssl); + rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_OUT); - int ssl_err = SSL_connect((SSL *) F->ssl); + int ssl_err = SSL_connect(SSL_P(F)); if(ssl_err <= 0) { - switch(ssl_err = SSL_get_error((SSL *) F->ssl, ssl_err)) + switch((ssl_err = SSL_get_error(SSL_P(F), ssl_err))) { case SSL_ERROR_SYSCALL: if(rb_ignore_errno(errno)) From 62fc0eab037b39a6a768063c9b915201b5a2a18e Mon Sep 17 00:00:00 2001 From: Aaron Jones Date: Thu, 15 Sep 2016 17:13:27 +0000 Subject: [PATCH 09/25] OpenSSL: Rename error functions consistent with other backends. --- libratbox/src/openssl.c | 66 ++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 24 deletions(-) diff --git a/libratbox/src/openssl.c b/libratbox/src/openssl.c index e3f199d8..39ae5b77 100644 --- a/libratbox/src/openssl.c +++ b/libratbox/src/openssl.c @@ -56,7 +56,9 @@ static void rb_ssl_connect_realcb(rb_fde_t *, int, struct ssl_connect *); static void rb_ssl_tryconn_timeout_cb(rb_fde_t *, void *); static void rb_ssl_timeout(rb_fde_t *, void *); static void rb_ssl_tryaccept(rb_fde_t *, void *); -static const char *get_ssl_error(unsigned long); + +static unsigned long rb_ssl_last_err(void); +static const char *rb_ssl_strerror(unsigned long); @@ -65,7 +67,7 @@ static const char *get_ssl_error(unsigned long); */ static unsigned long -get_last_err(void) +rb_ssl_last_err(void) { unsigned long err_saved, err = 0; @@ -78,13 +80,13 @@ get_last_err(void) static void rb_ssl_init_fd(rb_fde_t *const F, const rb_fd_tls_direction dir) { - (void) get_last_err(); + (void) rb_ssl_last_err(); F->ssl = SSL_new(ssl_ctx); if(F->ssl == NULL) { - rb_lib_log("%s: SSL_new: %s", __func__, get_ssl_error(get_last_err())); + rb_lib_log("%s: SSL_new: %s", __func__, rb_ssl_strerror(rb_ssl_last_err())); rb_close(F); return; } @@ -105,6 +107,8 @@ rb_ssl_init_fd(rb_fde_t *const F, const rb_fd_tls_direction dir) static void rb_ssl_accept_common(rb_fde_t *const new_F) { + (void) rb_ssl_last_err(); + int ssl_err = SSL_accept(SSL_P(new_F)); if(ssl_err <= 0) @@ -116,13 +120,13 @@ rb_ssl_accept_common(rb_fde_t *const new_F) case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: { - new_F->ssl_errno = get_last_err(); + new_F->ssl_errno = rb_ssl_last_err(); rb_setselect(new_F, RB_SELECT_READ | RB_SELECT_WRITE, rb_ssl_tryaccept, NULL); return; } default: - new_F->ssl_errno = get_last_err(); + new_F->ssl_errno = rb_ssl_last_err(); new_F->accept->callback(new_F, RB_ERROR_SSL, NULL, 0, new_F->accept->data); return; } @@ -141,6 +145,8 @@ rb_ssl_tryaccept(rb_fde_t *const F, void *const data) if(! SSL_is_init_finished(SSL_P(F))) { + (void) rb_ssl_last_err(); + int flags; int ssl_err = SSL_accept(SSL_P(F)); @@ -154,14 +160,14 @@ rb_ssl_tryaccept(rb_fde_t *const F, void *const data) flags = RB_SELECT_WRITE; else flags = RB_SELECT_READ; - F->ssl_errno = get_last_err(); + F->ssl_errno = rb_ssl_last_err(); rb_setselect(F, flags, rb_ssl_tryaccept, NULL); break; case SSL_ERROR_SYSCALL: F->accept->callback(F, RB_ERROR, NULL, 0, F->accept->data); break; default: - F->ssl_errno = get_last_err(); + F->ssl_errno = rb_ssl_last_err(); F->accept->callback(F, RB_ERROR_SSL, NULL, 0, F->accept->data); break; } @@ -185,6 +191,8 @@ rb_ssl_tryconn_cb(rb_fde_t *const F, void *const data) { if(! SSL_is_init_finished(SSL_P(F))) { + (void) rb_ssl_last_err(); + struct ssl_connect *const sconn = data; int ssl_err = SSL_connect(SSL_P(F)); @@ -197,13 +205,13 @@ rb_ssl_tryconn_cb(rb_fde_t *const F, void *const data) case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: { - F->ssl_errno = get_last_err(); + F->ssl_errno = rb_ssl_last_err(); rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, rb_ssl_tryconn_cb, sconn); return; } default: - F->ssl_errno = get_last_err(); + F->ssl_errno = rb_ssl_last_err(); rb_ssl_connect_realcb(F, RB_ERROR_SSL, sconn); return; } @@ -234,6 +242,8 @@ rb_ssl_tryconn(rb_fde_t *const F, const int status, void *const data) rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn); rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_OUT); + (void) rb_ssl_last_err(); + int ssl_err = SSL_connect(SSL_P(F)); if(ssl_err <= 0) @@ -245,13 +255,13 @@ rb_ssl_tryconn(rb_fde_t *const F, const int status, void *const data) case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: { - F->ssl_errno = get_last_err(); + F->ssl_errno = rb_ssl_last_err(); rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, rb_ssl_tryconn_cb, sconn); return; } default: - F->ssl_errno = get_last_err(); + F->ssl_errno = rb_ssl_last_err(); rb_ssl_connect_realcb(F, RB_ERROR_SSL, sconn); return; } @@ -264,7 +274,7 @@ rb_ssl_tryconn(rb_fde_t *const F, const int status, void *const data) } static const char * -get_ssl_error(unsigned long err) +rb_ssl_strerror(unsigned long err) { static char buf[512]; @@ -285,6 +295,8 @@ rb_ssl_read_or_write(const int r_or_w, rb_fde_t *const F, void *const rbuf, cons ssize_t ret; unsigned long err; + (void) rb_ssl_last_err(); + if(r_or_w == 0) ret = (ssize_t) SSL_read(SSL_P(F), rbuf, (int)count); else @@ -303,7 +315,7 @@ rb_ssl_read_or_write(const int r_or_w, rb_fde_t *const F, void *const rbuf, cons case SSL_ERROR_ZERO_RETURN: return 0; case SSL_ERROR_SYSCALL: - err = get_last_err(); + err = rb_ssl_last_err(); if(err == 0) { F->ssl_errno = 0; @@ -311,7 +323,7 @@ rb_ssl_read_or_write(const int r_or_w, rb_fde_t *const F, void *const rbuf, cons } break; default: - err = get_last_err(); + err = rb_ssl_last_err(); break; } @@ -338,6 +350,8 @@ rb_ssl_shutdown(rb_fde_t *const F) if(F == NULL || F->ssl == NULL) return; + (void) rb_ssl_last_err(); + SSL_set_shutdown(SSL_P(F), SSL_RECEIVED_SHUTDOWN); for(int i = 0; i < 4; i++) @@ -346,7 +360,6 @@ rb_ssl_shutdown(rb_fde_t *const F) break; } - get_last_err(); SSL_free(SSL_P(F)); F->ssl = NULL; } @@ -383,6 +396,9 @@ rb_setup_ssl_server(const char *const cert, const char *keyfile, const char *con if(cipher_list == NULL) cipher_list = rb_default_ciphers; + + (void) rb_ssl_last_err(); + #ifdef LRB_HAVE_TLS_METHOD_API SSL_CTX *const ssl_ctx_new = SSL_CTX_new(TLS_method()); #else @@ -392,7 +408,7 @@ rb_setup_ssl_server(const char *const cert, const char *keyfile, const char *con if(ssl_ctx_new == NULL) { rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL context: %s", - get_ssl_error(ERR_get_error())); + rb_ssl_strerror(rb_ssl_last_err())); return 0; } @@ -443,7 +459,7 @@ rb_setup_ssl_server(const char *const cert, const char *keyfile, const char *con 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())); + rb_ssl_strerror(rb_ssl_last_err())); SSL_CTX_free(ssl_ctx_new); return 0; @@ -452,7 +468,7 @@ rb_setup_ssl_server(const char *const cert, const char *keyfile, const char *con 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())); + rb_ssl_strerror(rb_ssl_last_err())); SSL_CTX_free(ssl_ctx_new); return 0; @@ -472,7 +488,7 @@ rb_setup_ssl_server(const char *const cert, const char *keyfile, const char *con else if(PEM_read_DHparams(fp, &dh, NULL, NULL) == NULL) { rb_lib_log("rb_setup_ssl_server: Error loading DH params file [%s]: %s", - dhfile, get_ssl_error(ERR_get_error())); + dhfile, rb_ssl_strerror(rb_ssl_last_err())); fclose(fp); } else @@ -530,7 +546,7 @@ rb_get_random(void *const buf, const size_t length) if((ret = RAND_bytes(buf, length)) == 0) { /* remove the error from the queue */ - ERR_get_error(); + rb_ssl_last_err(); } return ret; } @@ -538,7 +554,7 @@ rb_get_random(void *const buf, const size_t length) const char * rb_get_ssl_strerror(rb_fde_t *const F) { - return get_ssl_error(F->ssl_errno); + return rb_ssl_strerror(F->ssl_errno); } int @@ -690,6 +706,8 @@ rb_ssl_start_connected(rb_fde_t *const F, CNCB *const callback, void *const data rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn); rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_OUT); + (void) rb_ssl_last_err(); + int ssl_err = SSL_connect(SSL_P(F)); if(ssl_err <= 0) @@ -701,13 +719,13 @@ rb_ssl_start_connected(rb_fde_t *const F, CNCB *const callback, void *const data case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: { - F->ssl_errno = get_last_err(); + F->ssl_errno = rb_ssl_last_err(); rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, rb_ssl_tryconn_cb, sconn); return; } default: - F->ssl_errno = get_last_err(); + F->ssl_errno = rb_ssl_last_err(); rb_ssl_connect_realcb(F, RB_ERROR_SSL, sconn); return; } From cc04fbe3f9303b75d60607a3f4a767039243aedc Mon Sep 17 00:00:00 2001 From: Aaron Jones Date: Thu, 15 Sep 2016 17:16:40 +0000 Subject: [PATCH 10/25] OpenSSL: Fix up rb_init_ssl() to use proper define from openssl_ratbox.h --- libratbox/src/openssl.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/libratbox/src/openssl.c b/libratbox/src/openssl.c index 39ae5b77..7a52ad09 100644 --- a/libratbox/src/openssl.c +++ b/libratbox/src/openssl.c @@ -367,14 +367,12 @@ rb_ssl_shutdown(rb_fde_t *const F) int rb_init_ssl(void) { - /* - * OpenSSL 1.1.0 and above automatically initialises itself with sane defaults - */ - #if defined(LIBRESSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x10100000L) - SSL_library_init(); +#ifndef LRB_SSL_NO_EXPLICIT_INIT + (void) SSL_library_init(); SSL_load_error_strings(); - #endif +#endif + rb_lib_log("%s: OpenSSL backend initialised", __func__); return 1; } From 47d51fe3acb2988878edd418157ea18926bbd219 Mon Sep 17 00:00:00 2001 From: Aaron Jones Date: Thu, 15 Sep 2016 17:20:14 +0000 Subject: [PATCH 11/25] OpenSSL: Use C99 __func__ declaration instead of writing function names --- libratbox/src/openssl.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libratbox/src/openssl.c b/libratbox/src/openssl.c index 7a52ad09..6df14766 100644 --- a/libratbox/src/openssl.c +++ b/libratbox/src/openssl.c @@ -381,13 +381,13 @@ rb_setup_ssl_server(const char *const cert, const char *keyfile, const char *con { if(cert == NULL) { - rb_lib_log("rb_setup_ssl_server: No certificate file"); + rb_lib_log("%s: no certificate file specified", __func__); return 0; } if(keyfile == NULL) { - rb_lib_log("rb_setup_ssl_server: No key file"); + rb_lib_log("%s: no key file specified", __func__); return 0; } @@ -405,7 +405,7 @@ rb_setup_ssl_server(const char *const cert, const char *keyfile, const char *con if(ssl_ctx_new == NULL) { - rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL context: %s", + rb_lib_log("%s: Unable to initialize OpenSSL context: %s", __func__, rb_ssl_strerror(rb_ssl_last_err())); return 0; } @@ -456,7 +456,7 @@ rb_setup_ssl_server(const char *const cert, const char *keyfile, const char *con 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("%s: Error loading certificate file [%s]: %s", __func__, cert, rb_ssl_strerror(rb_ssl_last_err())); SSL_CTX_free(ssl_ctx_new); @@ -465,7 +465,7 @@ rb_setup_ssl_server(const char *const cert, const char *keyfile, const char *con 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("%s: Error loading keyfile [%s]: %s", __func__, keyfile, rb_ssl_strerror(rb_ssl_last_err())); SSL_CTX_free(ssl_ctx_new); @@ -480,12 +480,12 @@ rb_setup_ssl_server(const char *const cert, const char *keyfile, const char *con if(fp == NULL) { - rb_lib_log("rb_setup_ssl_server: Error loading DH params file [%s]: %s", + rb_lib_log("%s: Error loading DH params file [%s]: %s", __func__, dhfile, strerror(errno)); } else if(PEM_read_DHparams(fp, &dh, NULL, NULL) == NULL) { - rb_lib_log("rb_setup_ssl_server: Error loading DH params file [%s]: %s", + rb_lib_log("%s: Error loading DH params file [%s]: %s", __func__, dhfile, rb_ssl_strerror(rb_ssl_last_err())); fclose(fp); } From 9114e3a2dc77dd434a9e0cf3073cf8a84512be20 Mon Sep 17 00:00:00 2001 From: Aaron Jones Date: Thu, 15 Sep 2016 17:34:14 +0000 Subject: [PATCH 12/25] OpenSSL: Improve rb_setup_ssl_server() * Move file/data assignments to the top of the function * Don't attempt to set a hardcoded P-384 ECDH key if we have the new SSL_CTX_set1_curves_list() function (OpenSSL 1.0.2+) * Rename variables consistent with other backends and wrap the function arguments. * Disable OpenSSL's disabling of TLS 1/n-1 record splitting. In other words, enable TLS 1/n-1 record splitting. * Other misc cleanups. --- libratbox/src/openssl.c | 154 ++++++++++++++++++++++------------------ 1 file changed, 84 insertions(+), 70 deletions(-) diff --git a/libratbox/src/openssl.c b/libratbox/src/openssl.c index 6df14766..62e40832 100644 --- a/libratbox/src/openssl.c +++ b/libratbox/src/openssl.c @@ -377,22 +377,20 @@ rb_init_ssl(void) } int -rb_setup_ssl_server(const char *const cert, const char *keyfile, const char *const dhfile, const char *cipher_list) +rb_setup_ssl_server(const char *const certfile, const char *keyfile, + const char *const dhfile, const char *cipherlist) { - if(cert == NULL) + if(certfile == NULL) { rb_lib_log("%s: no certificate file specified", __func__); return 0; } if(keyfile == NULL) - { - rb_lib_log("%s: no key file specified", __func__); - return 0; - } + keyfile = certfile; - if(cipher_list == NULL) - cipher_list = rb_default_ciphers; + if(cipherlist == NULL) + cipherlist = rb_default_ciphers; (void) rb_ssl_last_err(); @@ -410,98 +408,114 @@ rb_setup_ssl_server(const char *const cert, const char *keyfile, const char *con return 0; } - #ifndef LRB_HAVE_TLS_METHOD_API - 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_ctx_new, SSL_OP_SINGLE_DH_USE); - #endif - - #ifdef 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_ctx_new, SSL_OP_NO_TICKET); - #endif - - #ifdef 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_ctx_new, 1); - #endif - - #ifdef LRB_HAVE_TLS_SET_CURVES - SSL_CTX_set1_curves_list(ssl_ctx_new, rb_default_curves); - #endif - - 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 - */ - #if (OPENSSL_VERSION_NUMBER >= 0x10000000L) && (OPENSSL_VERSION_NUMBER < 0x10002000L) && !defined(OPENSSL_NO_ECDH) - EC_KEY *const key = EC_KEY_new_by_curve_name(NID_secp384r1); - if(key) { - SSL_CTX_set_tmp_ecdh(ssl_ctx_new, key); - EC_KEY_free(key); - } - #endif - - SSL_CTX_set_cipher_list(ssl_ctx_new, cipher_list); - - if(! SSL_CTX_use_certificate_chain_file(ssl_ctx_new, cert)) + if(SSL_CTX_use_certificate_chain_file(ssl_ctx_new, certfile) != 1) { - rb_lib_log("%s: Error loading certificate file [%s]: %s", __func__, cert, + rb_lib_log("%s: Error loading certificate file ('%s'): %s", __func__, certfile, rb_ssl_strerror(rb_ssl_last_err())); SSL_CTX_free(ssl_ctx_new); return 0; } - if(! SSL_CTX_use_PrivateKey_file(ssl_ctx_new, keyfile, SSL_FILETYPE_PEM)) + if(SSL_CTX_use_PrivateKey_file(ssl_ctx_new, keyfile, SSL_FILETYPE_PEM) != 1) { - rb_lib_log("%s: Error loading keyfile [%s]: %s", __func__, keyfile, + rb_lib_log("%s: Error loading keyfile ('%s'): %s", __func__, keyfile, rb_ssl_strerror(rb_ssl_last_err())); SSL_CTX_free(ssl_ctx_new); return 0; } - if(dhfile != NULL) + if(dhfile == NULL) { - /* DH parameters aren't necessary, but they are nice..if they didn't pass one..that is their problem */ - FILE *const fp = fopen(dhfile, "r"); - DH *dh = NULL; + rb_lib_log("%s: no DH parameters file specified", __func__); + } + else + { + FILE *const dhf = fopen(dhfile, "r"); + DH *dhp = NULL; - if(fp == NULL) + if(dhf == NULL) { - rb_lib_log("%s: Error loading DH params file [%s]: %s", __func__, - dhfile, strerror(errno)); + rb_lib_log("%s: Error loading DH params file ('%s'): %s", __func__, dhfile, strerror(errno)); } - else if(PEM_read_DHparams(fp, &dh, NULL, NULL) == NULL) + else if(PEM_read_DHparams(dhf, &dhp, NULL, NULL) == NULL) { - rb_lib_log("%s: Error loading DH params file [%s]: %s", __func__, - dhfile, rb_ssl_strerror(rb_ssl_last_err())); - fclose(fp); + rb_lib_log("%s: Error loading DH params file ('%s'): %s", __func__, dhfile, + rb_ssl_strerror(rb_ssl_last_err())); + fclose(dhf); } else { - SSL_CTX_set_tmp_dh(ssl_ctx_new, dh); - DH_free(dh); - fclose(fp); + SSL_CTX_set_tmp_dh(ssl_ctx_new, dhp); + DH_free(dhp); + fclose(dhf); } } + if (SSL_CTX_set_cipher_list(ssl_ctx_new, cipherlist) != 1) + { + rb_lib_log("%s: SSL_CTX_set_cipher_list: could not configure any ciphers", __func__); + SSL_CTX_free(ssl_ctx_new); + return 0; + } + + SSL_CTX_set_session_cache_mode(ssl_ctx_new, SSL_SESS_CACHE_OFF); + SSL_CTX_set_verify(ssl_ctx_new, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, verify_accept_all_cb); + + #ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS + (void) SSL_CTX_clear_options(ssl_ctx_new, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); + #endif + + #ifndef LRB_HAVE_TLS_METHOD_API + (void) SSL_CTX_set_options(ssl_ctx_new, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); + #endif + + #ifdef SSL_OP_NO_TICKET + (void) SSL_CTX_set_options(ssl_ctx_new, SSL_OP_NO_TICKET); + #endif + + #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE + (void) SSL_CTX_set_options(ssl_ctx_new, SSL_OP_CIPHER_SERVER_PREFERENCE); + #endif + + #ifdef SSL_OP_SINGLE_DH_USE + (void) SSL_CTX_set_options(ssl_ctx_new, SSL_OP_SINGLE_DH_USE); + #endif + + #ifdef SSL_OP_SINGLE_ECDH_USE + (void) SSL_CTX_set_options(ssl_ctx_new, SSL_OP_SINGLE_ECDH_USE); + #endif + + #ifdef LRB_HAVE_TLS_ECDH_AUTO + (void) SSL_CTX_set_ecdh_auto(ssl_ctx_new, 1); + #endif + + #ifdef LRB_HAVE_TLS_SET_CURVES + (void) SSL_CTX_set1_curves_list(ssl_ctx_new, rb_default_curves); + #else + # if (OPENSSL_VERSION_NUMBER >= 0x10000000L) && !defined(OPENSSL_NO_ECDH) && defined(NID_secp384r1) + EC_KEY *const ec_key = EC_KEY_new_by_curve_name(NID_secp384r1); + if(ec_key != NULL) + { + SSL_CTX_set_tmp_ecdh(ssl_ctx_new, ec_key); + EC_KEY_free(ec_key); + } + else + rb_lib_log("%s: EC_KEY_new_by_curve_name failed; will not enable ECDHE- ciphers", __func__); + # else + rb_lib_log("%s: OpenSSL built without ECDH support; will not enable ECDHE- ciphers", __func__); + # endif + #endif + + if(ssl_ctx) SSL_CTX_free(ssl_ctx); ssl_ctx = ssl_ctx_new; + + rb_lib_log("%s: TLS configuration successful", __func__); return 1; } From 485b5b80845630a601429c6650be19bb085a2e5d Mon Sep 17 00:00:00 2001 From: Aaron Jones Date: Thu, 15 Sep 2016 19:12:13 +0000 Subject: [PATCH 13/25] OpenSSL: Import the callback/handshake logic from the MbedTLS backend --- libratbox/src/openssl.c | 359 +++++++++++++++------------------------- 1 file changed, 129 insertions(+), 230 deletions(-) diff --git a/libratbox/src/openssl.c b/libratbox/src/openssl.c index 62e40832..7c7d989a 100644 --- a/libratbox/src/openssl.c +++ b/libratbox/src/openssl.c @@ -52,13 +52,8 @@ struct ssl_connect int timeout; }; -static void rb_ssl_connect_realcb(rb_fde_t *, int, struct ssl_connect *); -static void rb_ssl_tryconn_timeout_cb(rb_fde_t *, void *); -static void rb_ssl_timeout(rb_fde_t *, void *); -static void rb_ssl_tryaccept(rb_fde_t *, void *); - -static unsigned long rb_ssl_last_err(void); static const char *rb_ssl_strerror(unsigned long); +static void rb_ssl_connect_realcb(rb_fde_t *, int, struct ssl_connect *); @@ -105,172 +100,84 @@ rb_ssl_init_fd(rb_fde_t *const F, const rb_fd_tls_direction dir) } static void -rb_ssl_accept_common(rb_fde_t *const new_F) +rb_ssl_accept_common(rb_fde_t *const F, void *const data) { + lrb_assert(F != NULL); + lrb_assert(F->accept != NULL); + lrb_assert(F->accept->callback != NULL); + lrb_assert(F->ssl != NULL); + (void) rb_ssl_last_err(); - int ssl_err = SSL_accept(SSL_P(new_F)); + int ret = SSL_do_handshake(SSL_P(F)); + int err = SSL_get_error(SSL_P(F), ret); - if(ssl_err <= 0) + if(ret == 1) { - switch((ssl_err = SSL_get_error(SSL_P(new_F), ssl_err))) - { - case SSL_ERROR_SYSCALL: - if(rb_ignore_errno(errno)) - case SSL_ERROR_WANT_READ: - case SSL_ERROR_WANT_WRITE: - { - new_F->ssl_errno = rb_ssl_last_err(); - rb_setselect(new_F, RB_SELECT_READ | RB_SELECT_WRITE, - rb_ssl_tryaccept, NULL); - return; - } - default: - new_F->ssl_errno = rb_ssl_last_err(); - new_F->accept->callback(new_F, RB_ERROR_SSL, NULL, 0, new_F->accept->data); - return; - } + F->handshake_count++; + + rb_settimeout(F, 0, NULL, NULL); + rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, NULL, NULL); + + struct acceptdata *const ad = F->accept; + F->accept = NULL; + ad->callback(F, RB_OK, (struct sockaddr *)&ad->S, ad->addrlen, ad->data); + rb_free(ad); + + return; } - else + if(ret == -1 && err == SSL_ERROR_WANT_READ) { - new_F->handshake_count++; - rb_ssl_tryaccept(new_F, NULL); + rb_setselect(F, RB_SELECT_READ, rb_ssl_accept_common, NULL); + return; } -} - -static void -rb_ssl_tryaccept(rb_fde_t *const F, void *const data) -{ - lrb_assert(F->accept != NULL); - - if(! SSL_is_init_finished(SSL_P(F))) + if(ret == -1 && err == SSL_ERROR_WANT_WRITE) { - (void) rb_ssl_last_err(); - - int flags; - int ssl_err = SSL_accept(SSL_P(F)); - - if(ssl_err <= 0) - { - switch(ssl_err = SSL_get_error(SSL_P(F), ssl_err)) - { - case SSL_ERROR_WANT_READ: - case SSL_ERROR_WANT_WRITE: - if(ssl_err == SSL_ERROR_WANT_WRITE) - flags = RB_SELECT_WRITE; - else - flags = RB_SELECT_READ; - F->ssl_errno = rb_ssl_last_err(); - rb_setselect(F, flags, rb_ssl_tryaccept, NULL); - break; - case SSL_ERROR_SYSCALL: - F->accept->callback(F, RB_ERROR, NULL, 0, F->accept->data); - break; - default: - F->ssl_errno = rb_ssl_last_err(); - F->accept->callback(F, RB_ERROR_SSL, NULL, 0, F->accept->data); - break; - } - return; - } - else - F->handshake_count++; + rb_setselect(F, RB_SELECT_WRITE, rb_ssl_accept_common, NULL); + return; } - rb_settimeout(F, 0, NULL, NULL); - rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, NULL, NULL); - - struct acceptdata *const ad = F->accept; - F->accept = NULL; - ad->callback(F, RB_OK, (struct sockaddr *)&ad->S, ad->addrlen, ad->data); - rb_free(ad); + errno = EIO; + F->ssl_errno = (unsigned long) err; + F->accept->callback(F, RB_ERROR_SSL, NULL, 0, F->accept->data); } static void rb_ssl_tryconn_cb(rb_fde_t *const F, void *const data) -{ - if(! SSL_is_init_finished(SSL_P(F))) - { - (void) rb_ssl_last_err(); - - struct ssl_connect *const sconn = data; - int ssl_err = SSL_connect(SSL_P(F)); - - if(ssl_err <= 0) - { - switch(ssl_err = SSL_get_error(SSL_P(F), ssl_err)) - { - case SSL_ERROR_SYSCALL: - if(rb_ignore_errno(errno)) - case SSL_ERROR_WANT_READ: - case SSL_ERROR_WANT_WRITE: - { - F->ssl_errno = rb_ssl_last_err(); - rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, - rb_ssl_tryconn_cb, sconn); - return; - } - default: - F->ssl_errno = rb_ssl_last_err(); - rb_ssl_connect_realcb(F, RB_ERROR_SSL, sconn); - return; - } - } - else - { - F->handshake_count++; - rb_ssl_connect_realcb(F, RB_OK, sconn); - } - } -} - -static void -rb_ssl_tryconn(rb_fde_t *const F, const int status, void *const data) { lrb_assert(F != NULL); - - struct ssl_connect *const sconn = data; - - if(status != RB_OK) - { - rb_ssl_connect_realcb(F, status, sconn); - return; - } - - F->type |= RB_FD_SSL; - - rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn); - rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_OUT); + lrb_assert(F->ssl != NULL); (void) rb_ssl_last_err(); - int ssl_err = SSL_connect(SSL_P(F)); + int ret = SSL_do_handshake(SSL_P(F)); + int err = SSL_get_error(SSL_P(F), ret); - if(ssl_err <= 0) - { - switch(ssl_err = SSL_get_error(SSL_P(F), ssl_err)) - { - case SSL_ERROR_SYSCALL: - if(rb_ignore_errno(errno)) - case SSL_ERROR_WANT_READ: - case SSL_ERROR_WANT_WRITE: - { - F->ssl_errno = rb_ssl_last_err(); - rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, - rb_ssl_tryconn_cb, sconn); - return; - } - default: - F->ssl_errno = rb_ssl_last_err(); - rb_ssl_connect_realcb(F, RB_ERROR_SSL, sconn); - return; - } - } - else + if(ret == 1) { F->handshake_count++; - rb_ssl_connect_realcb(F, RB_OK, sconn); + + rb_settimeout(F, 0, NULL, NULL); + rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, NULL, NULL); + + rb_ssl_connect_realcb(F, RB_OK, data); + + return; } + if(ret == -1 && err == SSL_ERROR_WANT_READ) + { + rb_setselect(F, RB_SELECT_READ, rb_ssl_tryconn_cb, data); + return; + } + if(ret == -1 && err == SSL_ERROR_WANT_WRITE) + { + rb_setselect(F, RB_SELECT_WRITE, rb_ssl_tryconn_cb, data); + return; + } + + errno = EIO; + F->ssl_errno = (unsigned long) err; + rb_ssl_connect_realcb(F, RB_ERROR_SSL, data); } static const char * @@ -666,88 +573,6 @@ rb_ssl_write(rb_fde_t *const F, const void *const buf, const size_t count) return rb_ssl_read_or_write(1, F, NULL, buf, count); } -void -rb_ssl_start_accepted(rb_fde_t *const F, ACCB *const cb, void *const data, const int timeout) -{ - F->type |= RB_FD_SSL; - - F->accept = rb_malloc(sizeof(struct acceptdata)); - F->accept->callback = cb; - F->accept->data = data; - F->accept->addrlen = 0; - (void) memset(&F->accept->S, 0x00, sizeof F->accept->S); - - rb_settimeout(F, timeout, rb_ssl_timeout, NULL); - rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_IN); - rb_ssl_accept_common(F); -} - -void -rb_ssl_accept_setup(rb_fde_t *const srv_F, rb_fde_t *const cli_F, struct sockaddr *const st, const int addrlen) -{ - cli_F->type |= RB_FD_SSL; - - cli_F->accept = rb_malloc(sizeof(struct acceptdata)); - cli_F->accept->callback = srv_F->accept->callback; - cli_F->accept->data = srv_F->accept->data; - cli_F->accept->addrlen = addrlen; - (void) memset(&cli_F->accept->S, 0x00, sizeof cli_F->accept->S); - (void) memcpy(&cli_F->accept->S, st, addrlen); - - rb_settimeout(cli_F, 10, rb_ssl_timeout, NULL); - rb_ssl_init_fd(cli_F, RB_FD_TLS_DIRECTION_IN); - rb_ssl_accept_common(cli_F); -} - -void -rb_ssl_start_connected(rb_fde_t *const F, CNCB *const callback, void *const data, const int timeout) -{ - if(F == NULL) - return; - - struct ssl_connect *const sconn = rb_malloc(sizeof *sconn); - sconn->data = data; - sconn->callback = callback; - sconn->timeout = timeout; - - F->connect = rb_malloc(sizeof(struct conndata)); - F->connect->callback = callback; - F->connect->data = data; - F->type |= RB_FD_SSL; - - rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn); - rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_OUT); - - (void) rb_ssl_last_err(); - - int ssl_err = SSL_connect(SSL_P(F)); - - if(ssl_err <= 0) - { - switch((ssl_err = SSL_get_error(SSL_P(F), ssl_err))) - { - case SSL_ERROR_SYSCALL: - if(rb_ignore_errno(errno)) - case SSL_ERROR_WANT_READ: - case SSL_ERROR_WANT_WRITE: - { - F->ssl_errno = rb_ssl_last_err(); - rb_setselect(F, RB_SELECT_READ | RB_SELECT_WRITE, - rb_ssl_tryconn_cb, sconn); - return; - } - default: - F->ssl_errno = rb_ssl_last_err(); - rb_ssl_connect_realcb(F, RB_ERROR_SSL, sconn); - return; - } - } - else - { - rb_ssl_connect_realcb(F, RB_OK, sconn); - } -} - /* @@ -776,6 +601,26 @@ rb_ssl_tryconn_timeout_cb(rb_fde_t *const F, void *const data) rb_ssl_connect_realcb(F, RB_ERR_TIMEOUT, data); } +static void +rb_ssl_tryconn(rb_fde_t *const F, const int status, void *const data) +{ + lrb_assert(F != NULL); + + struct ssl_connect *const sconn = data; + + if(status != RB_OK) + { + rb_ssl_connect_realcb(F, status, sconn); + return; + } + + F->type |= RB_FD_SSL; + + rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn); + rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_OUT); + rb_ssl_tryconn_cb(F, sconn); +} + /* @@ -800,6 +645,39 @@ rb_ssl_clear_handshake_count(rb_fde_t *const F) F->handshake_count = 0; } +void +rb_ssl_start_accepted(rb_fde_t *const F, ACCB *const cb, void *const data, const int timeout) +{ + F->type |= RB_FD_SSL; + + F->accept = rb_malloc(sizeof(struct acceptdata)); + F->accept->callback = cb; + F->accept->data = data; + F->accept->addrlen = 0; + (void) memset(&F->accept->S, 0x00, sizeof F->accept->S); + + rb_settimeout(F, timeout, rb_ssl_timeout, NULL); + rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_IN); + rb_ssl_accept_common(F, NULL); +} + +void +rb_ssl_accept_setup(rb_fde_t *const srv_F, rb_fde_t *const cli_F, struct sockaddr *const st, const int addrlen) +{ + cli_F->type |= RB_FD_SSL; + + cli_F->accept = rb_malloc(sizeof(struct acceptdata)); + cli_F->accept->callback = srv_F->accept->callback; + cli_F->accept->data = srv_F->accept->data; + cli_F->accept->addrlen = addrlen; + (void) memset(&cli_F->accept->S, 0x00, sizeof cli_F->accept->S); + (void) memcpy(&cli_F->accept->S, st, addrlen); + + rb_settimeout(cli_F, 10, rb_ssl_timeout, NULL); + rb_ssl_init_fd(cli_F, RB_FD_TLS_DIRECTION_IN); + rb_ssl_accept_common(cli_F, NULL); +} + int rb_ssl_listen(rb_fde_t *const F, const int backlog, const int defer_accept) { @@ -825,4 +703,25 @@ rb_connect_tcp_ssl(rb_fde_t *const F, struct sockaddr *const dest, struct sockad rb_connect_tcp(F, dest, clocal, socklen, rb_ssl_tryconn, sconn, timeout); } +void +rb_ssl_start_connected(rb_fde_t *const F, CNCB *const callback, void *const data, const int timeout) +{ + if(F == NULL) + return; + + struct ssl_connect *const sconn = rb_malloc(sizeof *sconn); + sconn->data = data; + sconn->callback = callback; + sconn->timeout = timeout; + + F->connect = rb_malloc(sizeof(struct conndata)); + F->connect->callback = callback; + F->connect->data = data; + F->type |= RB_FD_SSL; + + rb_settimeout(F, sconn->timeout, rb_ssl_tryconn_timeout_cb, sconn); + rb_ssl_init_fd(F, RB_FD_TLS_DIRECTION_OUT); + rb_ssl_tryconn_cb(F, sconn); +} + #endif /* HAVE_OPESSL */ From bd8097c459be342a29217432685b6cea69cf1081 Mon Sep 17 00:00:00 2001 From: Aaron Jones Date: Thu, 15 Sep 2016 19:14:41 +0000 Subject: [PATCH 14/25] OpenSSL: Tweak connection shutdown logic --- libratbox/src/openssl.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libratbox/src/openssl.c b/libratbox/src/openssl.c index 7c7d989a..5737ace2 100644 --- a/libratbox/src/openssl.c +++ b/libratbox/src/openssl.c @@ -259,11 +259,12 @@ rb_ssl_shutdown(rb_fde_t *const F) (void) rb_ssl_last_err(); - SSL_set_shutdown(SSL_P(F), SSL_RECEIVED_SHUTDOWN); - for(int i = 0; i < 4; i++) { - if(SSL_shutdown(SSL_P(F))) + int ret = SSL_shutdown(SSL_P(F)); + int err = SSL_get_error(SSL_P(F), ret); + + if(ret >= 0 || (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)) break; } From 45d05d88822e6e38eb9ad8e6d491eddd7b85c701 Mon Sep 17 00:00:00 2001 From: Aaron Jones Date: Thu, 15 Sep 2016 19:21:38 +0000 Subject: [PATCH 15/25] OpenSSL: Improve error logging in rb_setup_ssl_server() --- libratbox/src/openssl.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/libratbox/src/openssl.c b/libratbox/src/openssl.c index 5737ace2..13b7afb9 100644 --- a/libratbox/src/openssl.c +++ b/libratbox/src/openssl.c @@ -311,14 +311,13 @@ rb_setup_ssl_server(const char *const certfile, const char *keyfile, if(ssl_ctx_new == NULL) { - rb_lib_log("%s: Unable to initialize OpenSSL context: %s", __func__, - rb_ssl_strerror(rb_ssl_last_err())); + rb_lib_log("%s: SSL_CTX_new: %s", __func__, rb_ssl_strerror(rb_ssl_last_err())); return 0; } if(SSL_CTX_use_certificate_chain_file(ssl_ctx_new, certfile) != 1) { - rb_lib_log("%s: Error loading certificate file ('%s'): %s", __func__, certfile, + rb_lib_log("%s: SSL_CTX_use_certificate_chain_file ('%s'): %s", __func__, certfile, rb_ssl_strerror(rb_ssl_last_err())); SSL_CTX_free(ssl_ctx_new); @@ -327,7 +326,7 @@ rb_setup_ssl_server(const char *const certfile, const char *keyfile, if(SSL_CTX_use_PrivateKey_file(ssl_ctx_new, keyfile, SSL_FILETYPE_PEM) != 1) { - rb_lib_log("%s: Error loading keyfile ('%s'): %s", __func__, keyfile, + rb_lib_log("%s: SSL_CTX_use_PrivateKey_file ('%s'): %s", __func__, keyfile, rb_ssl_strerror(rb_ssl_last_err())); SSL_CTX_free(ssl_ctx_new); @@ -345,11 +344,11 @@ rb_setup_ssl_server(const char *const certfile, const char *keyfile, if(dhf == NULL) { - rb_lib_log("%s: Error loading DH params file ('%s'): %s", __func__, dhfile, strerror(errno)); + rb_lib_log("%s: fopen ('%s'): %s", __func__, dhfile, strerror(errno)); } else if(PEM_read_DHparams(dhf, &dhp, NULL, NULL) == NULL) { - rb_lib_log("%s: Error loading DH params file ('%s'): %s", __func__, dhfile, + rb_lib_log("%s: PEM_read_DHparams ('%s'): %s", __func__, dhfile, rb_ssl_strerror(rb_ssl_last_err())); fclose(dhf); } From a8db009575349fe21e3e59dca4ff22a1929adf4c Mon Sep 17 00:00:00 2001 From: Aaron Jones Date: Thu, 15 Sep 2016 19:22:45 +0000 Subject: [PATCH 16/25] OpenSSL: Modify rb_ssl_strerror() in line with other backends --- libratbox/src/openssl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libratbox/src/openssl.c b/libratbox/src/openssl.c index 13b7afb9..6bcf366b 100644 --- a/libratbox/src/openssl.c +++ b/libratbox/src/openssl.c @@ -183,11 +183,11 @@ rb_ssl_tryconn_cb(rb_fde_t *const F, void *const data) static const char * rb_ssl_strerror(unsigned long err) { - static char buf[512]; + static char errbuf[512]; - ERR_error_string_n(err, buf, sizeof buf); + ERR_error_string_n(err, errbuf, sizeof errbuf); - return buf; + return errbuf; } static int From 767fad345f9e6f254711b8826d52ccc46f5d2bee Mon Sep 17 00:00:00 2001 From: Aaron Jones Date: Thu, 15 Sep 2016 19:24:40 +0000 Subject: [PATCH 17/25] OpenSSL: Properly wrap long lines. [ci skip] --- libratbox/src/openssl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libratbox/src/openssl.c b/libratbox/src/openssl.c index 6bcf366b..18e45469 100644 --- a/libratbox/src/openssl.c +++ b/libratbox/src/openssl.c @@ -318,7 +318,7 @@ rb_setup_ssl_server(const char *const certfile, const char *keyfile, if(SSL_CTX_use_certificate_chain_file(ssl_ctx_new, certfile) != 1) { rb_lib_log("%s: SSL_CTX_use_certificate_chain_file ('%s'): %s", __func__, certfile, - rb_ssl_strerror(rb_ssl_last_err())); + rb_ssl_strerror(rb_ssl_last_err())); SSL_CTX_free(ssl_ctx_new); return 0; @@ -327,7 +327,7 @@ rb_setup_ssl_server(const char *const certfile, const char *keyfile, if(SSL_CTX_use_PrivateKey_file(ssl_ctx_new, keyfile, SSL_FILETYPE_PEM) != 1) { rb_lib_log("%s: SSL_CTX_use_PrivateKey_file ('%s'): %s", __func__, keyfile, - rb_ssl_strerror(rb_ssl_last_err())); + rb_ssl_strerror(rb_ssl_last_err())); SSL_CTX_free(ssl_ctx_new); return 0; From 06c588e535aaad07cfbaa2bd484b8b624ec9590a Mon Sep 17 00:00:00 2001 From: Aaron Jones Date: Thu, 15 Sep 2016 19:25:50 +0000 Subject: [PATCH 18/25] OpenSSL: Apply consistent coding style [ci skip] --- libratbox/src/openssl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libratbox/src/openssl.c b/libratbox/src/openssl.c index 18e45469..e5a0f584 100644 --- a/libratbox/src/openssl.c +++ b/libratbox/src/openssl.c @@ -360,7 +360,7 @@ rb_setup_ssl_server(const char *const certfile, const char *keyfile, } } - if (SSL_CTX_set_cipher_list(ssl_ctx_new, cipherlist) != 1) + if(SSL_CTX_set_cipher_list(ssl_ctx_new, cipherlist) != 1) { rb_lib_log("%s: SSL_CTX_set_cipher_list: could not configure any ciphers", __func__); SSL_CTX_free(ssl_ctx_new); From d9c825c4def90d3b64cdc303224abf586000264b Mon Sep 17 00:00:00 2001 From: Aaron Jones Date: Thu, 15 Sep 2016 19:27:15 +0000 Subject: [PATCH 19/25] OpenSSL: Correct closing comment [ci skip] --- libratbox/src/openssl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libratbox/src/openssl.c b/libratbox/src/openssl.c index e5a0f584..b338efba 100644 --- a/libratbox/src/openssl.c +++ b/libratbox/src/openssl.c @@ -724,4 +724,4 @@ rb_ssl_start_connected(rb_fde_t *const F, CNCB *const callback, void *const data rb_ssl_tryconn_cb(F, sconn); } -#endif /* HAVE_OPESSL */ +#endif /* HAVE_OPENSSL */ From b4a0b60dff373bbd2d55227f50159e298cf31f19 Mon Sep 17 00:00:00 2001 From: Aaron Jones Date: Thu, 15 Sep 2016 19:28:25 +0000 Subject: [PATCH 20/25] OpenSSL: Cast sockaddr len variable appropriately --- libratbox/src/openssl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libratbox/src/openssl.c b/libratbox/src/openssl.c index b338efba..f285d9dc 100644 --- a/libratbox/src/openssl.c +++ b/libratbox/src/openssl.c @@ -669,9 +669,9 @@ rb_ssl_accept_setup(rb_fde_t *const srv_F, rb_fde_t *const cli_F, struct sockadd cli_F->accept = rb_malloc(sizeof(struct acceptdata)); cli_F->accept->callback = srv_F->accept->callback; cli_F->accept->data = srv_F->accept->data; - cli_F->accept->addrlen = addrlen; + cli_F->accept->addrlen = (rb_socklen_t) addrlen; (void) memset(&cli_F->accept->S, 0x00, sizeof cli_F->accept->S); - (void) memcpy(&cli_F->accept->S, st, addrlen); + (void) memcpy(&cli_F->accept->S, st, (size_t) addrlen); rb_settimeout(cli_F, 10, rb_ssl_timeout, NULL); rb_ssl_init_fd(cli_F, RB_FD_TLS_DIRECTION_IN); From 01ce1c508ddb7d110fab0cc5cb433c6af9d542f1 Mon Sep 17 00:00:00 2001 From: Aaron Jones Date: Thu, 15 Sep 2016 19:31:28 +0000 Subject: [PATCH 21/25] OpenSSL: Add a debugging assert for timeouts --- libratbox/src/openssl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libratbox/src/openssl.c b/libratbox/src/openssl.c index f285d9dc..aa27748e 100644 --- a/libratbox/src/openssl.c +++ b/libratbox/src/openssl.c @@ -592,6 +592,8 @@ static void rb_ssl_timeout(rb_fde_t *const F, void *const notused) { lrb_assert(F->accept != NULL); + lrb_assert(F->accept->callback != NULL); + F->accept->callback(F, RB_ERR_TIMEOUT, NULL, 0, F->accept->data); } From 15e2cab1e5759f4055c235b066e28ae4f4e28785 Mon Sep 17 00:00:00 2001 From: Aaron Jones Date: Thu, 15 Sep 2016 19:34:11 +0000 Subject: [PATCH 22/25] OpenSSL: Add another debugging assert --- libratbox/src/openssl.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libratbox/src/openssl.c b/libratbox/src/openssl.c index aa27748e..ccb14f4e 100644 --- a/libratbox/src/openssl.c +++ b/libratbox/src/openssl.c @@ -582,10 +582,13 @@ rb_ssl_write(rb_fde_t *const F, const void *const buf, const size_t count) static void rb_ssl_connect_realcb(rb_fde_t *const F, const int status, struct ssl_connect *const sconn) { + lrb_assert(F->connect != NULL); + F->connect->callback = sconn->callback; F->connect->data = sconn->data; - rb_free(sconn); + rb_connect_callback(F, status); + rb_free(sconn); } static void From 5bb5226edc7243fb4b4c3db81a80e8d60dba4574 Mon Sep 17 00:00:00 2001 From: Aaron Jones Date: Thu, 15 Sep 2016 19:51:36 +0000 Subject: [PATCH 23/25] OpenSSL: Simplify the RNG code --- libratbox/src/openssl.c | 41 ++++++++++++++--------------------------- 1 file changed, 14 insertions(+), 27 deletions(-) diff --git a/libratbox/src/openssl.c b/libratbox/src/openssl.c index ccb14f4e..90f017d3 100644 --- a/libratbox/src/openssl.c +++ b/libratbox/src/openssl.c @@ -429,45 +429,32 @@ rb_setup_ssl_server(const char *const certfile, const char *keyfile, int rb_init_prng(const char *const path, prng_seed_t seed_type) { - if(seed_type == RB_PRNG_DEFAULT) - { -#ifdef _WIN32 - RAND_screen(); -#endif - return RAND_status(); - } - if(path == NULL) - return RAND_status(); + (void) rb_ssl_last_err(); - switch(seed_type) + if(seed_type == RB_PRNG_FILE && RAND_load_file(path, -1) < 0) + rb_lib_log("%s: RAND_load_file: %s", __func__, rb_ssl_strerror(rb_ssl_last_err())); + + if(RAND_status() != 1) { - case RB_PRNG_FILE: - if(RAND_load_file(path, -1) == -1) - return -1; - break; -#ifdef _WIN32 - case RB_PRNGWIN32: - RAND_screen(); - break; -#endif - default: - return -1; + rb_lib_log("%s: RAND_status: %s", __func__, rb_ssl_strerror(rb_ssl_last_err())); + return 0; } - return RAND_status(); + return 1; } int rb_get_random(void *const buf, const size_t length) { - int ret; + (void) rb_ssl_last_err(); - if((ret = RAND_bytes(buf, length)) == 0) + if(RAND_bytes(buf, (int) length) != 1) { - /* remove the error from the queue */ - rb_ssl_last_err(); + rb_lib_log("%s: RAND_bytes: %s", __func__, rb_ssl_strerror(rb_ssl_last_err())); + return 0; } - return ret; + + return 1; } const char * From 5feb292aa937810809c9651e7119428e96e8fb95 Mon Sep 17 00:00:00 2001 From: Aaron Jones Date: Thu, 15 Sep 2016 19:54:54 +0000 Subject: [PATCH 24/25] OpenSSL: Indicate successful RNG initialisation --- libratbox/src/openssl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libratbox/src/openssl.c b/libratbox/src/openssl.c index 90f017d3..cff12c78 100644 --- a/libratbox/src/openssl.c +++ b/libratbox/src/openssl.c @@ -440,6 +440,7 @@ rb_init_prng(const char *const path, prng_seed_t seed_type) return 0; } + rb_lib_log("%s: PRNG initialised", __func__); return 1; } From 92c04c6b9dbdd11cd0432cb19b6fb2ae0d01c141 Mon Sep 17 00:00:00 2001 From: Aaron Jones Date: Thu, 15 Sep 2016 20:14:01 +0000 Subject: [PATCH 25/25] OpenSSL: Final round of const correctness I'm happy with the state of this backend now. I don't anticipate making any further changes. --- libratbox/src/openssl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libratbox/src/openssl.c b/libratbox/src/openssl.c index cff12c78..0e362bfe 100644 --- a/libratbox/src/openssl.c +++ b/libratbox/src/openssl.c @@ -181,7 +181,7 @@ rb_ssl_tryconn_cb(rb_fde_t *const F, void *const data) } static const char * -rb_ssl_strerror(unsigned long err) +rb_ssl_strerror(const unsigned long err) { static char errbuf[512];