From f20c42d05feac903612ba261230f64a2603052eb Mon Sep 17 00:00:00 2001 From: Jan Vidar Krey Date: Tue, 2 Oct 2012 23:59:11 +0200 Subject: [PATCH 1/7] Wrapped everything OpenSSL related in a SSL_USE_OPENSSL check macro. --- CMakeLists.txt | 32 +++++++++++++++++++++++------- src/core/hub.c | 6 +++++- src/core/hub.h | 2 ++ src/core/probe.c | 2 ++ src/network/backend.c | 4 +++- src/network/common.h | 9 ++++++++- src/network/connection.c | 42 +++++++++++++++++++++++++++++++++------- src/network/connection.h | 6 ++++-- src/network/network.c | 6 +++++- src/system.h | 5 +++++ src/tools/adcclient.c | 2 ++ 11 files changed, 96 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 33b20e1..8431d75 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,13 +17,21 @@ set (PROJECT_SOURCE_DIR "${CMAKE_SOURCE_DIR}/src") option(RELEASE "Release build, debug build if disabled" ON) option(LINK_SUPPORT "Allow hub linking" OFF) option(SSL_SUPPORT "Enable SSL support" ON) +option(USE_OPENSSL "Use OpenSSL's SSL support" OFF) option(SQLITE_SUPPORT "Enable SQLite support" ON) option(ADC_STRESS "Enable the stress tester client" OFF) find_package(Git) if (SSL_SUPPORT) - find_package(OpenSSL REQUIRED) + if (USE_OPENSSL) + find_package(OpenSSL) + else() + find_package(GnuTLS) + endif() + if (NOT GNUTLS_FOUND AND NOT OPENSSL_FOUND) + message(FATAL_ERROR "Neither OpenSSL nor GnuTLS are not found!") + endif() endif() if (MSVC) @@ -156,16 +164,26 @@ else() endif() if(OPENSSL_FOUND) - add_definitions(-DSSL_SUPPORT=1) + set(SSL_LIBS ${OPENSSL_LIBRARIES}) + add_definitions(-DSSL_SUPPORT=1 -DSSL_USE_OPENSSL=1) include_directories(${OPENSSL_INCLUDE_DIR}) - target_link_libraries(uhub ${OPENSSL_LIBRARIES}) +endif() + +if (GNUTLS_FOUND) + set(SSL_LIBS ${GNUTLS_LIBRARIES}) + add_definitions(-DSSL_SUPPORT=1 -DSSL_USE_GNUTLS=1 ${GNUTLS_DEFINITIONS}) + include_directories(${GNUTLS_INCLUDE_DIR}) +endif() + +if(SSL_SUPPORT) + target_link_libraries(uhub ${SSL_LIBS}) if(UNIX) - target_link_libraries(uhub-admin ${OPENSSL_LIBRARIES}) + target_link_libraries(uhub-admin ${SSL_LIBS}) endif() - target_link_libraries(mod_welcome ${OPENSSL_LIBRARIES}) - target_link_libraries(mod_logging ${OPENSSL_LIBRARIES}) + target_link_libraries(mod_welcome ${SSL_LIBS}) + target_link_libraries(mod_logging ${SSL_LIBS}) if (ADC_STRESS) - target_link_libraries(adcrush ${OPENSSL_LIBRARIES}) + target_link_libraries(adcrush ${SSL_LIBS}) endif() endif() diff --git a/src/core/hub.c b/src/core/hub.c index 714f8ec..25f9608 100644 --- a/src/core/hub.c +++ b/src/core/hub.c @@ -731,6 +731,7 @@ static int load_ssl_certificates(struct hub_info* hub, struct hub_config* config { if (config->tls_enable) { +#ifdef SSL_USE_OPENSSL hub->ssl_method = (SSL_METHOD*) SSLv23_method(); /* TLSv1_method() */ hub->ssl_ctx = SSL_CTX_new(hub->ssl_method); @@ -754,18 +755,21 @@ static int load_ssl_certificates(struct hub_info* hub, struct hub_config* config return 0; } LOG_INFO("Enabling TLS, using certificate: %s, private key: %s", config->tls_certificate, config->tls_private_key); +#endif /* SSL_USE_OPENSSL */ } return 1; } static void unload_ssl_certificates(struct hub_info* hub) { +#ifdef SSL_USE_OPENSSL if (hub->ssl_ctx) { SSL_CTX_free(hub->ssl_ctx); } +#endif /* SSL_USE_OPENSSL */ } -#endif +#endif /* SSL_SUPPORT */ struct hub_info* hub_start_service(struct hub_config* config) { diff --git a/src/core/hub.h b/src/core/hub.h index b0edee0..d313e9c 100644 --- a/src/core/hub.h +++ b/src/core/hub.h @@ -116,8 +116,10 @@ struct hub_info struct uhub_plugins* plugins; /* Plug-ins loaded for this hub instance. */ #ifdef SSL_SUPPORT +#ifdef SSL_USE_OPENSSL SSL_METHOD* ssl_method; SSL_CTX* ssl_ctx; +#endif // SSL_USE_OPENSSL #endif /* SSL_SUPPORT */ }; diff --git a/src/core/probe.c b/src/core/probe.c index 293cf45..276d6f1 100644 --- a/src/core/probe.c +++ b/src/core/probe.c @@ -85,7 +85,9 @@ static void probe_net_event(struct net_connection* con, int events, void *arg) { probe->connection = 0; } +#ifdef SSL_USE_OPENSSL net_con_ssl_handshake(con, net_con_ssl_mode_server, probe->hub->ssl_ctx); +#endif /* SSL_USE_OPENSSL */ } else { diff --git a/src/network/backend.c b/src/network/backend.c index b74d798..97b8426 100644 --- a/src/network/backend.c +++ b/src/network/backend.c @@ -180,12 +180,14 @@ void net_con_close(struct net_connection* con) g_backend->handler.con_del(g_backend->data, con); #ifdef SSL_SUPPORT +#ifdef SSL_USE_OPENSSL if (con->ssl) { SSL_shutdown(con->ssl); SSL_clear(con->ssl); } -#endif +#endif /* SSL_USE_OPENSSL */ +#endif /* SSL_SUPPORT */ net_close(con->sd); con->sd = -1; diff --git a/src/network/common.h b/src/network/common.h index 014ddfb..8f60477 100644 --- a/src/network/common.h +++ b/src/network/common.h @@ -35,10 +35,17 @@ net_connection_cb callback; /** Callback function */ \ struct timeout_evt* timeout; /** timeout event handler */ +#ifdef SSL_USE_OPENSSL #define NET_CON_STRUCT_SSL \ SSL* ssl; /** SSL handle */ \ uint32_t ssl_state; /** SSL state */ \ - size_t write_len; /** Length of last SSL_write(), only used if flags is NET_WANT_SSL_READ. */ \ + size_t write_len; /** Length of last SSL_write(), only used if flags is NET_WANT_SSL_READ. */ +#endif + +#ifdef SSL_USE_GNUTLS +#define NET_CON_STRUCT_SSL \ + uint32_t ssl_state; /** SSL state */ +#endif #ifdef SSL_SUPPORT #define NET_CON_STRUCT_COMMON \ diff --git a/src/network/connection.c b/src/network/connection.c index b30b46c..ef3c6fe 100644 --- a/src/network/connection.c +++ b/src/network/connection.c @@ -32,6 +32,7 @@ enum uhub_tls_state tls_st_disconnecting, }; +#ifdef SSL_USE_OPENSSL static int handle_openssl_error(struct net_connection* con, int ret) { uhub_assert(con); @@ -72,15 +73,18 @@ static int handle_openssl_error(struct net_connection* con, int ret) } return -1; } +#endif /* SSL_USE_OPENSSL */ ssize_t net_con_ssl_accept(struct net_connection* con) { uhub_assert(con); con->ssl_state = tls_st_accepting; - ssize_t ret = SSL_accept(con->ssl); + ssize_t ret; +#ifdef SSL_USE_OPENSSL + ret = SSL_accept(con->ssl); #ifdef NETWORK_DUMP_DEBUG LOG_PROTO("SSL_accept() ret=%d", ret); -#endif +#endif /* NETWORK_DUMP_DEBUG */ if (ret > 0) { net_con_update(con, NET_EVENT_READ); @@ -90,18 +94,20 @@ ssize_t net_con_ssl_accept(struct net_connection* con) { return handle_openssl_error(con, ret); } +#endif /* SSL_USE_OPENSSL */ return ret; } ssize_t net_con_ssl_connect(struct net_connection* con) { uhub_assert(con); - + ssize_t ret; con->ssl_state = tls_st_connecting; - ssize_t ret = SSL_connect(con->ssl); +#ifdef SSL_USE_OPENSSL + ret = SSL_connect(con->ssl); #ifdef NETWORK_DUMP_DEBUG LOG_PROTO("SSL_connect() ret=%d", ret); -#endif +#endif /* NETWORK_DUMP_DEBUG */ if (ret > 0) { con->ssl_state = tls_st_connected; @@ -111,12 +117,15 @@ ssize_t net_con_ssl_connect(struct net_connection* con) { return handle_openssl_error(con, ret); } +#endif /* SSL_USE_OPENSSL */ return ret; } +#ifdef SSL_USE_OPENSSL ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode ssl_mode, SSL_CTX* ssl_ctx) { uhub_assert(con); + SSL* ssl = 0; if (ssl_mode == net_con_ssl_mode_server) @@ -138,7 +147,9 @@ ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode net_con_set_ssl(con, ssl); return net_con_ssl_connect(con); } + } +#endif /* SSL_USE_OPENSSL */ #endif /* SSL_SUPPORT */ #ifdef SSL_SUPPORT @@ -150,7 +161,9 @@ ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len) { int ret; #ifdef SSL_SUPPORT +#ifdef SSL_USE_OPENSSL if (!con->ssl) +#endif /* SSL_USE_OPENSSL */ { #endif ret = net_send(con->sd, buf, len, UHUB_SEND_SIGNAL); @@ -168,6 +181,7 @@ ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len) } #ifdef SSL_SUPPORT } +#ifdef SSL_USE_OPENSSL else { con->write_len = len; @@ -182,7 +196,8 @@ ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len) net_stats_add_tx(ret); } } -#endif +#endif /* SSL_USE_OPENSSL */ +#endif /* SSL_SUPPORT */ return ret; } @@ -214,6 +229,7 @@ ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len) } else { +#ifdef SSL_USE_OPENSSL if (con->ssl_state == tls_st_error) return -1; @@ -228,8 +244,9 @@ ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len) { return handle_openssl_error(con, ret); } +#endif /* SSL_USE_OPENSSL */ } -#endif +#endif /* SSL_SUPPORT */ return ret; } @@ -254,11 +271,15 @@ ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len) } #ifdef SSL_SUPPORT + int net_con_is_ssl(struct net_connection* con) { +#ifdef SSL_USE_OPENSSL return con->ssl != 0; +#endif } +#ifdef SSL_USE_OPENSSL SSL* net_con_get_ssl(struct net_connection* con) { return con->ssl; @@ -268,6 +289,7 @@ void net_con_set_ssl(struct net_connection* con, SSL* ssl) { con->ssl = ssl; } +#endif /* SSL_USE_OPENSSL */ #endif /* SSL_SUPPORT */ int net_con_get_sd(struct net_connection* con) @@ -283,7 +305,9 @@ void* net_con_get_ptr(struct net_connection* con) void net_con_destroy(struct net_connection* con) { #ifdef SSL_SUPPORT +#ifdef SSL_USE_OPENSSL SSL_free(con->ssl); +#endif /* SSL_USE_OPENSSL */ #endif hub_free(con); } @@ -301,13 +325,17 @@ void net_con_callback(struct net_connection* con, int events) } #ifdef SSL_SUPPORT +#ifdef SSL_USE_OPENSSL if (!con->ssl) +#endif /* SSL_USE_OPENSSL */ { #endif con->callback(con, events, con->ptr); #ifdef SSL_SUPPORT } +#ifdef SSL_USE_OPENSSL else +#endif /* SSL_USE_OPENSSL */ { #ifdef NETWORK_DUMP_DEBUG LOG_PROTO("net_con_event: events=%d, con=%p, state=%d", events, con, con->ssl_state); diff --git a/src/network/connection.h b/src/network/connection.h index ff69262..53fd15e 100644 --- a/src/network/connection.h +++ b/src/network/connection.h @@ -100,11 +100,13 @@ enum net_con_ssl_mode net_con_ssl_mode_client, }; +#ifdef SSL_USE_OPENSSL extern ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode, SSL_CTX* ssl_ctx); - -extern int net_con_is_ssl(struct net_connection* con); extern SSL* net_con_get_ssl(struct net_connection* con); extern void net_con_set_ssl(struct net_connection* con, SSL*); +#endif // SSL_USE_OPENSSL +extern int net_con_is_ssl(struct net_connection* con); + #endif /* SSL_SUPPORT */ #endif /* HAVE_UHUB_NETWORK_CONNECTION_H */ diff --git a/src/network/network.c b/src/network/network.c index a7164d6..8268934 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -59,9 +59,11 @@ int net_initialize() net_stats_initialize(); #ifdef SSL_SUPPORT +#ifdef SSL_USE_OPENSSL LOG_TRACE("Initializing OpenSSL..."); SSL_library_init(); SSL_load_error_strings(); +#endif /* SSL_USE_OPENSSL */ #endif /* SSL_SUPPORT */ net_initialized = 1; @@ -100,10 +102,12 @@ int net_destroy() net_backend_shutdown(); #ifdef SSL_SUPPORT +#ifdef SSL_USE_OPENSSL ERR_free_strings(); EVP_cleanup(); CRYPTO_cleanup_all_ex_data(); -#endif +#endif /* SSL_USE_OPENSSL */ +#endif /* SSL_SUPPORT */ #ifdef WINSOCK WSACleanup(); diff --git a/src/system.h b/src/system.h index 12e5b3c..75542c1 100644 --- a/src/system.h +++ b/src/system.h @@ -99,8 +99,13 @@ #endif #ifdef SSL_SUPPORT +#ifdef SSL_USE_OPENSSL #include #include +#endif /* SSL_USE_OPENSSL */ +#ifdef SSL_USE_GNUTLS +#include +#endif /* SSL_USE_GNUTLS */ #endif #include "version.h" diff --git a/src/tools/adcclient.c b/src/tools/adcclient.c index 69bb8e4..bf1402c 100644 --- a/src/tools/adcclient.c +++ b/src/tools/adcclient.c @@ -66,8 +66,10 @@ struct ADC_client int flags; void* ptr; #ifdef SSL_SUPPORT +#ifdef SSL_USE_OPENSSL const SSL_METHOD* ssl_method; SSL_CTX* ssl_ctx; +#endif /* SSL_USE_OPENSSL */ #endif /* SSL_SUPPORT */ }; From f3922bb3e00cf87dd52f3cfbd98191ba3ee883b0 Mon Sep 17 00:00:00 2001 From: Jan Vidar Krey Date: Fri, 12 Oct 2012 14:24:03 +0200 Subject: [PATCH 2/7] Work on splitting out OpenSSL cleanly. --- CMakeLists.txt | 1 + src/network/backend.c | 5 +- src/network/common.h | 17 +-- src/network/connection.c | 246 ++------------------------------------ src/network/connection.h | 29 +---- src/network/openssl.c | 252 +++++++++++++++++++++++++++++++++++++++ src/network/tls.h | 71 +++++++++++ 7 files changed, 341 insertions(+), 280 deletions(-) create mode 100644 src/network/openssl.c create mode 100644 src/network/tls.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8431d75..61ea77c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,7 @@ set (network_SOURCES ${PROJECT_SOURCE_DIR}/network/timeout.c ${PROJECT_SOURCE_DIR}/network/timer.c ${PROJECT_SOURCE_DIR}/network/network.c + ${PROJECT_SOURCE_DIR}/network/openssl.c ${PROJECT_SOURCE_DIR}/network/ipcalc.c ) diff --git a/src/network/backend.c b/src/network/backend.c index 97b8426..62c892d 100644 --- a/src/network/backend.c +++ b/src/network/backend.c @@ -182,10 +182,7 @@ void net_con_close(struct net_connection* con) #ifdef SSL_SUPPORT #ifdef SSL_USE_OPENSSL if (con->ssl) - { - SSL_shutdown(con->ssl); - SSL_clear(con->ssl); - } + net_ssl_shutdown(con); #endif /* SSL_USE_OPENSSL */ #endif /* SSL_SUPPORT */ diff --git a/src/network/common.h b/src/network/common.h index 8f60477..48eeec4 100644 --- a/src/network/common.h +++ b/src/network/common.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2012, Jan Vidar Krey * * 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 @@ -26,6 +26,10 @@ #define NET_WANT_SSL_CONNECT 0x0080 #define NET_WANT_SSL_X509_LOOKUP 0x0100 +#define NET_SSL_ANY NET_WANT_SSL_READ | NET_WANT_SSL_WRITE | NET_WANT_SSL_ACCEPT | NET_WANT_SSL_CONNECT | NET_WANT_SSL_X509_LOOKUP + +struct ssl_handle; /* abstract type */ + #define NET_CLEANUP 0x8000 #define NET_CON_STRUCT_BASIC \ @@ -35,17 +39,8 @@ net_connection_cb callback; /** Callback function */ \ struct timeout_evt* timeout; /** timeout event handler */ -#ifdef SSL_USE_OPENSSL #define NET_CON_STRUCT_SSL \ - SSL* ssl; /** SSL handle */ \ - uint32_t ssl_state; /** SSL state */ \ - size_t write_len; /** Length of last SSL_write(), only used if flags is NET_WANT_SSL_READ. */ -#endif - -#ifdef SSL_USE_GNUTLS -#define NET_CON_STRUCT_SSL \ - uint32_t ssl_state; /** SSL state */ -#endif + struct ssl_handle* ssl; /** SSL handle */ #ifdef SSL_SUPPORT #define NET_CON_STRUCT_COMMON \ diff --git a/src/network/connection.c b/src/network/connection.c index ef3c6fe..56a27c3 100644 --- a/src/network/connection.c +++ b/src/network/connection.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2012, Jan Vidar Krey * * 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,138 +20,6 @@ #include "uhub.h" #include "network/common.h" -#ifdef SSL_SUPPORT - -enum uhub_tls_state -{ - tls_st_none, - tls_st_error, - tls_st_accepting, - tls_st_connecting, - tls_st_connected, - tls_st_disconnecting, -}; - -#ifdef SSL_USE_OPENSSL -static int handle_openssl_error(struct net_connection* con, int ret) -{ - uhub_assert(con); - - int error = SSL_get_error(con->ssl, ret); - switch (error) - { - case SSL_ERROR_ZERO_RETURN: - LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_ZERO_RETURN", ret, error); - con->ssl_state = tls_st_error; - return -1; - - case SSL_ERROR_WANT_READ: - LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_READ", ret, error); - con->flags |= NET_WANT_SSL_READ; - net_con_update(con, NET_EVENT_READ); - return 0; - - case SSL_ERROR_WANT_WRITE: - LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_WRITE", ret, error); - con->flags |= NET_WANT_SSL_WRITE; - net_con_update(con, NET_EVENT_READ | NET_EVENT_WRITE); - return 0; - - case SSL_ERROR_SYSCALL: - LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_SYSCALL", ret, error); - /* if ret == 0, connection closed, if ret == -1, check with errno */ - if (ret == 0) - return -1; - else - return -net_error(); - - case SSL_ERROR_SSL: - LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_SSL", ret, error); - /* internal openssl error */ - con->ssl_state = tls_st_error; - return -1; - } - return -1; -} -#endif /* SSL_USE_OPENSSL */ - -ssize_t net_con_ssl_accept(struct net_connection* con) -{ - uhub_assert(con); - con->ssl_state = tls_st_accepting; - ssize_t ret; -#ifdef SSL_USE_OPENSSL - ret = SSL_accept(con->ssl); -#ifdef NETWORK_DUMP_DEBUG - LOG_PROTO("SSL_accept() ret=%d", ret); -#endif /* NETWORK_DUMP_DEBUG */ - if (ret > 0) - { - net_con_update(con, NET_EVENT_READ); - con->ssl_state = tls_st_connected; - } - else - { - return handle_openssl_error(con, ret); - } -#endif /* SSL_USE_OPENSSL */ - return ret; -} - -ssize_t net_con_ssl_connect(struct net_connection* con) -{ - uhub_assert(con); - ssize_t ret; - con->ssl_state = tls_st_connecting; -#ifdef SSL_USE_OPENSSL - ret = SSL_connect(con->ssl); -#ifdef NETWORK_DUMP_DEBUG - LOG_PROTO("SSL_connect() ret=%d", ret); -#endif /* NETWORK_DUMP_DEBUG */ - if (ret > 0) - { - con->ssl_state = tls_st_connected; - net_con_update(con, NET_EVENT_READ); - } - else - { - return handle_openssl_error(con, ret); - } -#endif /* SSL_USE_OPENSSL */ - return ret; -} - -#ifdef SSL_USE_OPENSSL -ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode ssl_mode, SSL_CTX* ssl_ctx) -{ - uhub_assert(con); - - SSL* ssl = 0; - - if (ssl_mode == net_con_ssl_mode_server) - { - ssl = SSL_new(ssl_ctx); - if (!ssl) - { - LOG_ERROR("Unable to create new SSL stream\n"); - return -1; - } - SSL_set_fd(ssl, con->sd); - net_con_set_ssl(con, ssl); - return net_con_ssl_accept(con); - } - else - { - ssl = SSL_new(SSL_CTX_new(TLSv1_method())); - SSL_set_fd(ssl, con->sd); - net_con_set_ssl(con, ssl); - return net_con_ssl_connect(con); - } - -} -#endif /* SSL_USE_OPENSSL */ -#endif /* SSL_SUPPORT */ - #ifdef SSL_SUPPORT void net_stats_add_tx(size_t bytes); void net_stats_add_rx(size_t bytes); @@ -161,9 +29,7 @@ ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len) { int ret; #ifdef SSL_SUPPORT -#ifdef SSL_USE_OPENSSL if (!con->ssl) -#endif /* SSL_USE_OPENSSL */ { #endif ret = net_send(con->sd, buf, len, UHUB_SEND_SIGNAL); @@ -181,22 +47,10 @@ ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len) } #ifdef SSL_SUPPORT } -#ifdef SSL_USE_OPENSSL else { - con->write_len = len; - ret = SSL_write(con->ssl, buf, len); - LOG_PROTO("SSL_write(con=%p, buf=%p, len=" PRINTF_SIZE_T ") => %d", con, buf, len, ret); - if (ret <= 0) - { - return handle_openssl_error(con, ret); - } - else - { - net_stats_add_tx(ret); - } + ret = net_ssl_send(con, buf, len); } -#endif /* SSL_USE_OPENSSL */ #endif /* SSL_SUPPORT */ return ret; } @@ -205,7 +59,7 @@ ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len) { int ret; #ifdef SSL_SUPPORT - if (!net_con_is_ssl(con)) + if (!con->ssl) { #endif ret = net_recv(con->sd, buf, len, 0); @@ -229,22 +83,7 @@ ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len) } else { -#ifdef SSL_USE_OPENSSL - if (con->ssl_state == tls_st_error) - return -1; - - ret = SSL_read(con->ssl, buf, len); - LOG_PROTO("SSL_read(con=%p, buf=%p, len=" PRINTF_SIZE_T ") => %d", con, buf, len, ret); - if (ret > 0) - { - net_con_update(con, NET_EVENT_READ); - net_stats_add_rx(ret); - } - else - { - return handle_openssl_error(con, ret); - } -#endif /* SSL_USE_OPENSSL */ + ret = net_ssl_recv(con, buf, len); } #endif /* SSL_SUPPORT */ return ret; @@ -274,22 +113,8 @@ ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len) int net_con_is_ssl(struct net_connection* con) { -#ifdef SSL_USE_OPENSSL - return con->ssl != 0; -#endif + return !!con->ssl; } - -#ifdef SSL_USE_OPENSSL -SSL* net_con_get_ssl(struct net_connection* con) -{ - return con->ssl; -} - -void net_con_set_ssl(struct net_connection* con, SSL* ssl) -{ - con->ssl = ssl; -} -#endif /* SSL_USE_OPENSSL */ #endif /* SSL_SUPPORT */ int net_con_get_sd(struct net_connection* con) @@ -305,9 +130,8 @@ void* net_con_get_ptr(struct net_connection* con) void net_con_destroy(struct net_connection* con) { #ifdef SSL_SUPPORT -#ifdef SSL_USE_OPENSSL - SSL_free(con->ssl); -#endif /* SSL_USE_OPENSSL */ + if (con->ssl) + net_ssl_destroy(con); #endif hub_free(con); } @@ -325,66 +149,12 @@ void net_con_callback(struct net_connection* con, int events) } #ifdef SSL_SUPPORT -#ifdef SSL_USE_OPENSSL if (!con->ssl) -#endif /* SSL_USE_OPENSSL */ - { #endif con->callback(con, events, con->ptr); #ifdef SSL_SUPPORT - } -#ifdef SSL_USE_OPENSSL else -#endif /* SSL_USE_OPENSSL */ - { -#ifdef NETWORK_DUMP_DEBUG - LOG_PROTO("net_con_event: events=%d, con=%p, state=%d", events, con, con->ssl_state); -#endif - switch (con->ssl_state) - { - case tls_st_none: - con->callback(con, events, con->ptr); - break; - - case tls_st_error: - con->callback(con, NET_EVENT_READ, con->ptr); - break; - - case tls_st_accepting: - if (net_con_ssl_accept(con) < 0) - { - con->callback(con, NET_EVENT_READ, con->ptr); - } - break; - - case tls_st_connecting: - if (net_con_ssl_connect(con) < 0) - { - con->callback(con, NET_EVENT_READ, con->ptr); - } - break; - - case tls_st_connected: - LOG_PROTO("tls_st_connected, events=%s%s, ssl_flags=%s%s", (events & NET_EVENT_READ ? "R" : ""), (events & NET_EVENT_WRITE ? "W" : ""), con->flags & NET_WANT_SSL_READ ? "R" : "", con->flags & NET_WANT_SSL_WRITE ? "W" : ""); - if (events & NET_EVENT_WRITE && con->flags & NET_WANT_SSL_READ) - { - con->callback(con, events & NET_EVENT_READ, con->ptr); - return; - } - - if (events & NET_EVENT_READ && con->flags & NET_WANT_SSL_WRITE) - { - con->callback(con, events & NET_EVENT_READ, con->ptr); - return; - } - - con->callback(con, events, con->ptr); - break; - - case tls_st_disconnecting: - return; - } - } + net_ssl_callback(con, events); #endif } diff --git a/src/network/connection.h b/src/network/connection.h index 53fd15e..84cc96a 100644 --- a/src/network/connection.h +++ b/src/network/connection.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2012, Jan Vidar Krey * * 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 @@ -23,6 +23,7 @@ #include "uhub.h" #include "network/common.h" #include "network/backend.h" +#include "network/tls.h" #define NET_EVENT_TIMEOUT 0x0001 #define NET_EVENT_READ 0x0002 @@ -83,31 +84,5 @@ extern ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len); extern void net_con_set_timeout(struct net_connection* con, int seconds); extern void net_con_clear_timeout(struct net_connection* con); -#ifdef SSL_SUPPORT -/** - * Start SSL_accept() - */ -extern ssize_t net_con_ssl_accept(struct net_connection*); - -/** - * Start SSL_connect() - */ -extern ssize_t net_con_ssl_connect(struct net_connection*); - -enum net_con_ssl_mode -{ - net_con_ssl_mode_server, - net_con_ssl_mode_client, -}; - -#ifdef SSL_USE_OPENSSL -extern ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode, SSL_CTX* ssl_ctx); -extern SSL* net_con_get_ssl(struct net_connection* con); -extern void net_con_set_ssl(struct net_connection* con, SSL*); -#endif // SSL_USE_OPENSSL -extern int net_con_is_ssl(struct net_connection* con); - -#endif /* SSL_SUPPORT */ - #endif /* HAVE_UHUB_NETWORK_CONNECTION_H */ diff --git a/src/network/openssl.c b/src/network/openssl.c new file mode 100644 index 0000000..509555d --- /dev/null +++ b/src/network/openssl.c @@ -0,0 +1,252 @@ +/* + * uhub - A tiny ADC p2p connection hub + * Copyright (C) 2007-2012, Jan Vidar Krey + * + * 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 3 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, see . + * + */ + +#include "uhub.h" +#include "network/common.h" +#include "network/tls.h" + +#ifdef SSL_SUPPORT +#ifdef SSL_USE_OPENSSL + +struct net_ssl_openssl +{ + SSL* ssl; + enum ssl_state state; +}; + +static struct net_ssl_openssl* get_handle(struct net_connection* con) +{ + uhub_assert(con); + return (struct net_ssl_openssl*) con->ssl; +} + +static int handle_openssl_error(struct net_connection* con, int ret) +{ + struct net_ssl_openssl* handle = get_handle(con); + + int error = SSL_get_error(handle->ssl, ret); + switch (error) + { + case SSL_ERROR_ZERO_RETURN: + LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_ZERO_RETURN", ret, error); + handle->state = tls_st_error; + return -1; + + case SSL_ERROR_WANT_READ: + LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_READ", ret, error); + con->flags |= NET_WANT_SSL_READ; + net_con_update(con, NET_EVENT_READ); + return 0; + + case SSL_ERROR_WANT_WRITE: + LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_WRITE", ret, error); + con->flags |= NET_WANT_SSL_WRITE; + net_con_update(con, NET_EVENT_READ | NET_EVENT_WRITE); + return 0; + + case SSL_ERROR_SYSCALL: + LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_SYSCALL", ret, error); + /* if ret == 0, connection closed, if ret == -1, check with errno */ + if (ret == 0) + return -1; + else + return -net_error(); + + case SSL_ERROR_SSL: + LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_SSL", ret, error); + /* internal openssl error */ + handle->state = tls_st_error; + return -1; + } + return -1; +} + +ssize_t net_con_ssl_accept(struct net_connection* con) +{ + struct net_ssl_openssl* handle = get_handle(con); + handle->state = tls_st_accepting; + ssize_t ret; + + ret = SSL_accept(handle->ssl); + LOG_PROTO("SSL_accept() ret=%d", ret); + if (ret > 0) + { + net_con_update(con, NET_EVENT_READ); + handle->state = tls_st_connected; + } + else + { + return handle_openssl_error(con, ret); + } + return ret; +} + +ssize_t net_con_ssl_connect(struct net_connection* con) +{ + struct net_ssl_openssl* handle = get_handle(con); + ssize_t ret; + handle->state = tls_st_connecting; + + ret = SSL_connect(handle->ssl); +#ifdef NETWORK_DUMP_DEBUG + LOG_PROTO("SSL_connect() ret=%d", ret); +#endif /* NETWORK_DUMP_DEBUG */ + if (ret > 0) + { + handle->state = tls_st_connected; + net_con_update(con, NET_EVENT_READ); + } + else + { + return handle_openssl_error(con, ret); + } + return ret; +} + +ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode ssl_mode, SSL_CTX* ssl_ctx) +{ + uhub_assert(con); + + struct net_ssl_openssl* handle = (struct net_ssl_openssl*) hub_malloc_zero(sizeof(struct net_ssl_openssl)); + + if (ssl_mode == net_con_ssl_mode_server) + { + handle->ssl = SSL_new(ssl_ctx); + if (!handle->ssl) + { + LOG_ERROR("Unable to create new SSL stream\n"); + return -1; + } + SSL_set_fd(handle->ssl, con->sd); + con->ssl = (struct ssl_handle*) handle; + return net_con_ssl_accept(con); + } + else + { + handle->ssl = SSL_new(SSL_CTX_new(TLSv1_method())); + SSL_set_fd(handle->ssl, con->sd); + con->ssl = (struct ssl_handle*) handle; + return net_con_ssl_connect(con); + } + +} + +ssize_t net_ssl_send(struct net_connection* con, const void* buf, size_t len) +{ + struct net_ssl_openssl* handle = get_handle(con); +// con->write_len = len; + ssize_t ret = SSL_write(handle->ssl, buf, len); + LOG_PROTO("SSL_write(con=%p, buf=%p, len=" PRINTF_SIZE_T ") => %d", con, buf, len, ret); + if (ret <= 0) + { + return handle_openssl_error(con, ret); + } + return ret; +} + +ssize_t net_ssl_recv(struct net_connection* con, void* buf, size_t len) +{ + struct net_ssl_openssl* handle = get_handle(con); + ssize_t ret; + + if (handle->state == tls_st_error) + return -1; + + ret = SSL_read(handle->ssl, buf, len); + LOG_PROTO("SSL_read(con=%p, buf=%p, len=" PRINTF_SIZE_T ") => %d", con, buf, len, ret); + if (ret > 0) + { + net_con_update(con, NET_EVENT_READ); + } + else + { + return handle_openssl_error(con, ret); + } + return ret; +} + +void net_ssl_shutdown(struct net_connection* con) +{ + struct net_ssl_openssl* handle = get_handle(con); + SSL_shutdown(handle->ssl); + SSL_clear(handle->ssl); +} + +void net_ssl_destroy(struct net_connection* con) +{ + struct net_ssl_openssl* handle = get_handle(con); + SSL_free(handle->ssl); +} + +void net_ssl_callback(struct net_connection* con, int events) +{ + struct net_ssl_openssl* handle = get_handle(con); + + uint32_t flags = con->flags; + con->flags &= ~NET_SSL_ANY; /* reset the SSL related flags */ + + switch (handle->state) + { + case tls_st_none: + con->callback(con, events, con->ptr); + break; + + case tls_st_error: + con->callback(con, NET_EVENT_READ, con->ptr); + break; + + case tls_st_accepting: + if (net_con_ssl_accept(con) < 0) + { + con->callback(con, NET_EVENT_READ, con->ptr); + } + break; + + case tls_st_connecting: + if (net_con_ssl_connect(con) < 0) + { + con->callback(con, NET_EVENT_READ, con->ptr); + } + break; + + case tls_st_connected: + LOG_PROTO("tls_st_connected, events=%s%s, ssl_flags=%s%s", (events & NET_EVENT_READ ? "R" : ""), (events & NET_EVENT_WRITE ? "W" : ""), flags & NET_WANT_SSL_READ ? "R" : "", flags & NET_WANT_SSL_WRITE ? "W" : ""); + if (events & NET_EVENT_WRITE && flags & NET_WANT_SSL_READ) + { + con->callback(con, events & NET_EVENT_READ, con->ptr); + return; + } + + if (events & NET_EVENT_READ && flags & NET_WANT_SSL_WRITE) + { + con->callback(con, events & NET_EVENT_READ, con->ptr); + return; + } + + con->callback(con, events, con->ptr); + break; + + case tls_st_disconnecting: + return; + } +} + + +#endif /* SSL_USE_OPENSSL */ +#endif /* SSL_SUPPORT */ \ No newline at end of file diff --git a/src/network/tls.h b/src/network/tls.h new file mode 100644 index 0000000..eccccf7 --- /dev/null +++ b/src/network/tls.h @@ -0,0 +1,71 @@ +/* + * uhub - A tiny ADC p2p connection hub + * Copyright (C) 2007-2012, Jan Vidar Krey + * + * 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 3 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, see . + * + */ + +#ifndef HAVE_UHUB_NETWORK_TLS_H +#define HAVE_UHUB_NETWORK_TLS_H + +#include "uhub.h" + +#ifdef SSL_SUPPORT + + +enum ssl_state +{ + tls_st_none, + tls_st_error, + tls_st_accepting, + tls_st_connecting, + tls_st_connected, + tls_st_disconnecting, +}; + +enum net_con_ssl_mode +{ + net_con_ssl_mode_server, + net_con_ssl_mode_client, +}; + + +/** + * Start SSL_accept() + */ +extern ssize_t net_con_ssl_accept(struct net_connection*); + +/** + * Start SSL_connect() + */ +extern ssize_t net_con_ssl_connect(struct net_connection*); + +extern ssize_t net_ssl_send(struct net_connection* con, const void* buf, size_t len); +extern ssize_t net_ssl_recv(struct net_connection* con, void* buf, size_t len); + +extern void net_ssl_shutdown(struct net_connection* con); +extern void net_ssl_destroy(struct net_connection* con); +extern void net_ssl_callback(struct net_connection* con, int events); + + +#ifdef SSL_USE_OPENSSL +extern ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode, SSL_CTX* ssl_ctx); +extern SSL* net_con_get_ssl(struct net_connection* con); +extern void net_con_set_ssl(struct net_connection* con, SSL*); +#endif // SSL_USE_OPENSSL +extern int net_con_is_ssl(struct net_connection* con); + +#endif /* SSL_SUPPORT */ +#endif /* HAVE_UHUB_NETWORK_TLS_H */ \ No newline at end of file From 50912bdf75cedc8192de95273fd11e3e5aa072e8 Mon Sep 17 00:00:00 2001 From: Jan Vidar Krey Date: Mon, 15 Oct 2012 20:39:03 +0200 Subject: [PATCH 3/7] More work on splitting out OpenSSL specific bits. --- src/core/hub.c | 38 +++++-------------- src/core/hub.h | 7 +--- src/core/probe.c | 4 +- src/network/openssl.c | 86 ++++++++++++++++++++++++++++++++++++++++--- src/network/tls.h | 32 +++++++++++++++- src/tools/adcclient.c | 24 ++---------- 6 files changed, 126 insertions(+), 65 deletions(-) diff --git a/src/core/hub.c b/src/core/hub.c index 25f9608..7eb6570 100644 --- a/src/core/hub.c +++ b/src/core/hub.c @@ -731,43 +731,23 @@ static int load_ssl_certificates(struct hub_info* hub, struct hub_config* config { if (config->tls_enable) { -#ifdef SSL_USE_OPENSSL - hub->ssl_method = (SSL_METHOD*) SSLv23_method(); /* TLSv1_method() */ - hub->ssl_ctx = SSL_CTX_new(hub->ssl_method); - - /* Disable SSLv2 */ - SSL_CTX_set_options(hub->ssl_ctx, SSL_OP_NO_SSLv2); - SSL_CTX_set_quiet_shutdown(hub->ssl_ctx, 1); - - if (SSL_CTX_use_certificate_file(hub->ssl_ctx, config->tls_certificate, SSL_FILETYPE_PEM) < 0) + hub->ctx = net_ssl_context_create(); + if (ssl_load_certificate(hub->ctx, config->tls_certificate) && + ssl_load_private_key(hub->ctx, config->tls_private_key) && + ssl_check_private_key(hub->ctx)) { - LOG_ERROR("SSL_CTX_use_certificate_file: %s", ERR_error_string(ERR_get_error(), NULL)); + LOG_INFO("Enabling TLS (%s), using certificate: %s, private key: %s", net_ssl_get_provider(), config->tls_certificate, config->tls_private_key); + return 1; } - - if (SSL_CTX_use_PrivateKey_file(hub->ssl_ctx, config->tls_private_key, SSL_FILETYPE_PEM) < 0) - { - LOG_ERROR("SSL_CTX_use_PrivateKey_file: %s", ERR_error_string(ERR_get_error(), NULL)); - } - - if (SSL_CTX_check_private_key(hub->ssl_ctx) != 1) - { - LOG_FATAL("SSL_CTX_check_private_key: Private key does not match the certificate public key: %s", ERR_error_string(ERR_get_error(), NULL)); - return 0; - } - LOG_INFO("Enabling TLS, using certificate: %s, private key: %s", config->tls_certificate, config->tls_private_key); -#endif /* SSL_USE_OPENSSL */ + return 0; } return 1; } static void unload_ssl_certificates(struct hub_info* hub) { -#ifdef SSL_USE_OPENSSL - if (hub->ssl_ctx) - { - SSL_CTX_free(hub->ssl_ctx); - } -#endif /* SSL_USE_OPENSSL */ + if (hub->ctx) + net_ssl_context_destroy(hub->ctx); } #endif /* SSL_SUPPORT */ diff --git a/src/core/hub.h b/src/core/hub.h index d313e9c..cf1cd4b 100644 --- a/src/core/hub.h +++ b/src/core/hub.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2011, Jan Vidar Krey + * Copyright (C) 2007-2012, Jan Vidar Krey * * 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 @@ -116,10 +116,7 @@ struct hub_info struct uhub_plugins* plugins; /* Plug-ins loaded for this hub instance. */ #ifdef SSL_SUPPORT -#ifdef SSL_USE_OPENSSL - SSL_METHOD* ssl_method; - SSL_CTX* ssl_ctx; -#endif // SSL_USE_OPENSSL + struct ssl_context_handle* ctx; #endif /* SSL_SUPPORT */ }; diff --git a/src/core/probe.c b/src/core/probe.c index 276d6f1..c217d34 100644 --- a/src/core/probe.c +++ b/src/core/probe.c @@ -85,9 +85,7 @@ static void probe_net_event(struct net_connection* con, int events, void *arg) { probe->connection = 0; } -#ifdef SSL_USE_OPENSSL - net_con_ssl_handshake(con, net_con_ssl_mode_server, probe->hub->ssl_ctx); -#endif /* SSL_USE_OPENSSL */ + net_con_ssl_handshake(con, net_con_ssl_mode_server, probe->hub->ctx); } else { diff --git a/src/network/openssl.c b/src/network/openssl.c index 509555d..9dc0866 100644 --- a/src/network/openssl.c +++ b/src/network/openssl.c @@ -24,18 +24,90 @@ #ifdef SSL_SUPPORT #ifdef SSL_USE_OPENSSL +#define NETWORK_DUMP_DEBUG + struct net_ssl_openssl { SSL* ssl; enum ssl_state state; }; +struct net_context_openssl +{ + SSL_METHOD* ssl_method; + SSL_CTX* ssl_ctx; +}; + static struct net_ssl_openssl* get_handle(struct net_connection* con) { uhub_assert(con); return (struct net_ssl_openssl*) con->ssl; } +const char* net_ssl_get_provider() +{ + return OPENSSL_VERSION_TEXT; +} + + +/** + * Create a new SSL context. + */ +struct ssl_context_handle* net_ssl_context_create() +{ + + struct net_context_openssl* ctx = (struct net_context_openssl*) hub_malloc_zero(sizeof(struct net_context_openssl)); + ctx->ssl_method = (SSL_METHOD*) SSLv23_method(); /* TLSv1_method() */ + ctx->ssl_ctx = SSL_CTX_new(ctx->ssl_method); + + /* Disable SSLv2 */ + SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_SSLv2); + SSL_CTX_set_quiet_shutdown(ctx->ssl_ctx, 1); + + return (struct ssl_context_handle*) ctx; +} + +extern void net_ssl_context_destroy(struct ssl_context_handle* ctx_) +{ + struct net_context_openssl* ctx = (struct net_context_openssl*) ctx_; + SSL_CTX_free(ctx->ssl_ctx); + hub_free(ctx); +} + +int ssl_load_certificate(struct ssl_context_handle* ctx_, const char* pem_file) +{ + struct net_context_openssl* ctx = (struct net_context_openssl*) ctx_; + if (SSL_CTX_use_certificate_file(ctx->ssl_ctx, pem_file, SSL_FILETYPE_PEM) < 0) + { + LOG_ERROR("SSL_CTX_use_certificate_file: %s", ERR_error_string(ERR_get_error(), NULL)); + return 0; + } + + return 1; +} + +int ssl_load_private_key(struct ssl_context_handle* ctx_, const char* pem_file) +{ + struct net_context_openssl* ctx = (struct net_context_openssl*) ctx_; + if (SSL_CTX_use_PrivateKey_file(ctx->ssl_ctx, pem_file, SSL_FILETYPE_PEM) < 0) + { + LOG_ERROR("SSL_CTX_use_PrivateKey_file: %s", ERR_error_string(ERR_get_error(), NULL)); + return 0; + } + return 1; +} + +int ssl_check_private_key(struct ssl_context_handle* ctx_) +{ + struct net_context_openssl* ctx = (struct net_context_openssl*) ctx_; + if (SSL_CTX_check_private_key(ctx->ssl_ctx) != 1) + { + LOG_FATAL("SSL_CTX_check_private_key: Private key does not match the certificate public key: %s", ERR_error_string(ERR_get_error(), NULL)); + return 0; + } + return 1; +} + static int handle_openssl_error(struct net_connection* con, int ret) { struct net_ssl_openssl* handle = get_handle(con); @@ -103,10 +175,12 @@ ssize_t net_con_ssl_connect(struct net_connection* con) ssize_t ret; handle->state = tls_st_connecting; + ret = SSL_connect(handle->ssl); #ifdef NETWORK_DUMP_DEBUG LOG_PROTO("SSL_connect() ret=%d", ret); #endif /* NETWORK_DUMP_DEBUG */ + if (ret > 0) { handle->state = tls_st_connected; @@ -119,15 +193,16 @@ ssize_t net_con_ssl_connect(struct net_connection* con) return ret; } -ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode ssl_mode, SSL_CTX* ssl_ctx) +ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode ssl_mode, struct ssl_context_handle* ssl_ctx) { uhub_assert(con); + struct net_context_openssl* ctx = (struct net_context_openssl*) ssl_ctx; struct net_ssl_openssl* handle = (struct net_ssl_openssl*) hub_malloc_zero(sizeof(struct net_ssl_openssl)); if (ssl_mode == net_con_ssl_mode_server) { - handle->ssl = SSL_new(ssl_ctx); + handle->ssl = SSL_new(ctx->ssl_ctx); if (!handle->ssl) { LOG_ERROR("Unable to create new SSL stream\n"); @@ -197,7 +272,7 @@ void net_ssl_destroy(struct net_connection* con) void net_ssl_callback(struct net_connection* con, int events) { struct net_ssl_openssl* handle = get_handle(con); - + int ret; uint32_t flags = con->flags; con->flags &= ~NET_SSL_ANY; /* reset the SSL related flags */ @@ -219,10 +294,9 @@ void net_ssl_callback(struct net_connection* con, int events) break; case tls_st_connecting: - if (net_con_ssl_connect(con) < 0) - { + ret = net_con_ssl_connect(con); + if (ret != 0) con->callback(con, NET_EVENT_READ, con->ptr); - } break; case tls_st_connected: diff --git a/src/network/tls.h b/src/network/tls.h index eccccf7..08b4da6 100644 --- a/src/network/tls.h +++ b/src/network/tls.h @@ -41,6 +41,33 @@ enum net_con_ssl_mode net_con_ssl_mode_client, }; +struct ssl_context_handle; + +/** + * Returns a string describing the TLS/SSL provider information + */ +extern const char* net_ssl_get_provider(); + +/** + * Create a new SSL context. + */ +extern struct ssl_context_handle* net_ssl_context_create(); +extern void net_ssl_context_destroy(struct ssl_context_handle* ctx); + +/** + * Return 0 on error, 1 otherwise. + */ +extern int ssl_load_certificate(struct ssl_context_handle* ctx, const char* pem_file); + +/** + * Return 0 on error, 1 otherwise. + */ +extern int ssl_load_private_key(struct ssl_context_handle* ctx, const char* pem_file); + +/** + * Return 0 if private key does not match certificate, 1 if everything is OK. + */ +extern int ssl_check_private_key(struct ssl_context_handle* ctx); /** * Start SSL_accept() @@ -60,9 +87,10 @@ extern void net_ssl_destroy(struct net_connection* con); extern void net_ssl_callback(struct net_connection* con, int events); -#ifdef SSL_USE_OPENSSL -extern ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode, SSL_CTX* ssl_ctx); + +extern ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode, struct ssl_context_handle* ssl_ctx); extern SSL* net_con_get_ssl(struct net_connection* con); +#ifdef SSL_USE_OPENSSL extern void net_con_set_ssl(struct net_connection* con, SSL*); #endif // SSL_USE_OPENSSL extern int net_con_is_ssl(struct net_connection* con); diff --git a/src/tools/adcclient.c b/src/tools/adcclient.c index bf1402c..a320da9 100644 --- a/src/tools/adcclient.c +++ b/src/tools/adcclient.c @@ -65,12 +65,6 @@ struct ADC_client char* desc; int flags; void* ptr; -#ifdef SSL_SUPPORT -#ifdef SSL_USE_OPENSSL - const SSL_METHOD* ssl_method; - SSL_CTX* ssl_ctx; -#endif /* SSL_USE_OPENSSL */ -#endif /* SSL_SUPPORT */ }; @@ -524,15 +518,7 @@ struct ADC_client* ADC_client_create(const char* nickname, const char* descripti if (sd == -1) return NULL; client->con = net_con_create(); -#if 0 - /* FIXME */ - client->timer = 0; /* FIXME: hub_malloc(sizeof(struct net_timer)); */ -#endif net_con_initialize(client->con, sd, event_callback, client, 0); -#if 0 - /* FIXME */ - net_timer_initialize(client->timer, timer_callback, client); -#endif ADC_client_set_state(client, ps_none); client->nick = hub_strdup(nickname); @@ -549,10 +535,6 @@ void ADC_client_destroy(struct ADC_client* client) { ADC_TRACE; ADC_client_disconnect(client); -#if 0 - /* FIXME */ - net_timer_shutdown(client->timer); -#endif ioq_send_destroy(client->send_queue); ioq_recv_destroy(client->recv_queue); hub_free(client->timer); @@ -600,6 +582,8 @@ static void ADC_client_on_connected(struct ADC_client* client) net_con_update(client->con, NET_EVENT_READ | NET_EVENT_WRITE); client->callback(client, ADC_CLIENT_SSL_HANDSHAKE, 0); ADC_client_set_state(client, ps_conn_ssl); + + net_con_ssl_handshake(client->con, net_con_ssl_mode_client, NULL); } else #endif @@ -615,9 +599,9 @@ static void ADC_client_on_connected(struct ADC_client* client) static void ADC_client_on_connected_ssl(struct ADC_client* client) { ADC_TRACE; - net_con_update(client->con, NET_EVENT_READ); client->callback(client, ADC_CLIENT_SSL_OK, 0); client->callback(client, ADC_CLIENT_CONNECTED, 0); + net_con_update(client->con, NET_EVENT_READ); ADC_client_send(client, adc_msg_create(ADC_HANDSHAKE)); ADC_client_set_state(client, ps_protocol); } @@ -729,4 +713,4 @@ const char* ADC_client_get_description(const struct ADC_client* client) void* ADC_client_get_ptr(const struct ADC_client* client) { return client->ptr; -} \ No newline at end of file +} From b1f2c937384d7dd23e1cdf75112e37422250b9b6 Mon Sep 17 00:00:00 2001 From: Jan Vidar Krey Date: Tue, 16 Oct 2012 20:15:38 +0200 Subject: [PATCH 4/7] Reworked the error handling of non-blocking reads and writes. This should prevent busy loops where the socket is makred readable but we are really only looking for it to become writable. --- src/network/backend.c | 4 +- src/network/backend.h | 2 +- src/network/connection.c | 44 ++++------ src/network/openssl.c | 173 ++++++++++++++++++++++++--------------- src/network/tls.h | 2 + 5 files changed, 130 insertions(+), 95 deletions(-) diff --git a/src/network/backend.c b/src/network/backend.c index 62c892d..e347b3e 100644 --- a/src/network/backend.c +++ b/src/network/backend.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2012, Jan Vidar Krey * * 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 @@ -180,10 +180,8 @@ void net_con_close(struct net_connection* con) g_backend->handler.con_del(g_backend->data, con); #ifdef SSL_SUPPORT -#ifdef SSL_USE_OPENSSL if (con->ssl) net_ssl_shutdown(con); -#endif /* SSL_USE_OPENSSL */ #endif /* SSL_SUPPORT */ net_close(con->sd); diff --git a/src/network/backend.h b/src/network/backend.h index ba5febe..b908f28 100644 --- a/src/network/backend.h +++ b/src/network/backend.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2012, Jan Vidar Krey * * 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 diff --git a/src/network/connection.c b/src/network/connection.c index 56a27c3..5f664cf 100644 --- a/src/network/connection.c +++ b/src/network/connection.c @@ -25,6 +25,18 @@ void net_stats_add_tx(size_t bytes); void net_stats_add_rx(size_t bytes); #endif +static int is_blocked_or_interrupted() +{ + int err = net_error(); + return +#ifdef WINSOCK + err == WSAEWOULDBLOCK +#else + err == EWOULDBLOCK +#endif + || err == EINTR; +} + ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len) { int ret; @@ -35,13 +47,7 @@ ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len) ret = net_send(con->sd, buf, len, UHUB_SEND_SIGNAL); if (ret == -1) { - if ( -#ifdef WINSOCK - net_error() == WSAEWOULDBLOCK -#else - net_error() == EWOULDBLOCK -#endif - || net_error() == EINTR) + if (is_blocked_or_interrupted()) return 0; return -1; } @@ -65,13 +71,7 @@ ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len) ret = net_recv(con->sd, buf, len, 0); if (ret == -1) { - if ( -#ifdef WINSOCK - net_error() == WSAEWOULDBLOCK -#else - net_error() == EWOULDBLOCK -#endif - || net_error() == EINTR) + if (is_blocked_or_interrupted()) return 0; return -net_error(); } @@ -94,13 +94,7 @@ ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len) int ret = net_recv(con->sd, buf, len, MSG_PEEK); if (ret == -1) { - if ( -#ifdef WINSOCK - net_error() == WSAEWOULDBLOCK -#else - net_error() == EWOULDBLOCK -#endif - || net_error() == EINTR) + if (is_blocked_or_interrupted()) return 0; return -net_error(); } @@ -149,12 +143,10 @@ void net_con_callback(struct net_connection* con, int events) } #ifdef SSL_SUPPORT - if (!con->ssl) + if (con->ssl) + net_ssl_callback(con, events); + else #endif con->callback(con, events, con->ptr); -#ifdef SSL_SUPPORT - else - net_ssl_callback(con, events); -#endif } diff --git a/src/network/openssl.c b/src/network/openssl.c index 9dc0866..cd09d4d 100644 --- a/src/network/openssl.c +++ b/src/network/openssl.c @@ -30,6 +30,9 @@ struct net_ssl_openssl { SSL* ssl; enum ssl_state state; + uint32_t flags; + BIO* biow; + BIO* bior; }; struct net_context_openssl @@ -108,47 +111,6 @@ int ssl_check_private_key(struct ssl_context_handle* ctx_) return 1; } -static int handle_openssl_error(struct net_connection* con, int ret) -{ - struct net_ssl_openssl* handle = get_handle(con); - - int error = SSL_get_error(handle->ssl, ret); - switch (error) - { - case SSL_ERROR_ZERO_RETURN: - LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_ZERO_RETURN", ret, error); - handle->state = tls_st_error; - return -1; - - case SSL_ERROR_WANT_READ: - LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_READ", ret, error); - con->flags |= NET_WANT_SSL_READ; - net_con_update(con, NET_EVENT_READ); - return 0; - - case SSL_ERROR_WANT_WRITE: - LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_WRITE", ret, error); - con->flags |= NET_WANT_SSL_WRITE; - net_con_update(con, NET_EVENT_READ | NET_EVENT_WRITE); - return 0; - - case SSL_ERROR_SYSCALL: - LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_SYSCALL", ret, error); - /* if ret == 0, connection closed, if ret == -1, check with errno */ - if (ret == 0) - return -1; - else - return -net_error(); - - case SSL_ERROR_SSL: - LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_SSL", ret, error); - /* internal openssl error */ - handle->state = tls_st_error; - return -1; - } - return -1; -} - ssize_t net_con_ssl_accept(struct net_connection* con) { struct net_ssl_openssl* handle = get_handle(con); @@ -164,7 +126,24 @@ ssize_t net_con_ssl_accept(struct net_connection* con) } else { - return handle_openssl_error(con, ret); + int err = SSL_get_error(handle->ssl, ret); + switch (err) + { + case SSL_ERROR_ZERO_RETURN: + // Not really an error, but SSL was shut down. + return -1; + + case SSL_ERROR_WANT_READ: + net_con_update(con, NET_EVENT_READ); + return 0; + + case SSL_ERROR_WANT_WRITE: + net_con_update(con, NET_EVENT_WRITE); + return 0; + + case SSL_ERROR_SYSCALL: + return -1; + } } return ret; } @@ -175,7 +154,6 @@ ssize_t net_con_ssl_connect(struct net_connection* con) ssize_t ret; handle->state = tls_st_connecting; - ret = SSL_connect(handle->ssl); #ifdef NETWORK_DUMP_DEBUG LOG_PROTO("SSL_connect() ret=%d", ret); @@ -188,7 +166,24 @@ ssize_t net_con_ssl_connect(struct net_connection* con) } else { - return handle_openssl_error(con, ret); + int err = SSL_get_error(handle->ssl, ret); + switch (err) + { + case SSL_ERROR_ZERO_RETURN: + // Not really an error, but SSL was shut down. + return -1; + + case SSL_ERROR_WANT_READ: + net_con_update(con, NET_EVENT_READ); + return 0; + + case SSL_ERROR_WANT_WRITE: + net_con_update(con, NET_EVENT_WRITE); + return 0; + + case SSL_ERROR_SYSCALL: + return -1; + } } return ret; } @@ -209,6 +204,8 @@ ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode return -1; } SSL_set_fd(handle->ssl, con->sd); + handle->bior = SSL_get_rbio(handle->ssl); + handle->biow = SSL_get_wbio(handle->ssl); con->ssl = (struct ssl_handle*) handle; return net_con_ssl_accept(con); } @@ -216,6 +213,8 @@ ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode { handle->ssl = SSL_new(SSL_CTX_new(TLSv1_method())); SSL_set_fd(handle->ssl, con->sd); + handle->bior = SSL_get_rbio(handle->ssl); + handle->biow = SSL_get_wbio(handle->ssl); con->ssl = (struct ssl_handle*) handle; return net_con_ssl_connect(con); } @@ -225,14 +224,40 @@ ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode ssize_t net_ssl_send(struct net_connection* con, const void* buf, size_t len) { struct net_ssl_openssl* handle = get_handle(con); -// con->write_len = len; + + uhub_assert(handle->state == tls_st_connected || handle->state == tls_st_need_write); + + ERR_clear_error(); ssize_t ret = SSL_write(handle->ssl, buf, len); LOG_PROTO("SSL_write(con=%p, buf=%p, len=" PRINTF_SIZE_T ") => %d", con, buf, len, ret); - if (ret <= 0) + if (ret > 0) { - return handle_openssl_error(con, ret); + handle->state = tls_st_connected; + return ret; + } + else if (ret <= 0) + { + int err = SSL_get_error(handle->ssl, ret); + switch (err) + { + case SSL_ERROR_ZERO_RETURN: + // Not really an error, but SSL was shut down. + return -1; + + case SSL_ERROR_WANT_READ: + handle->state = tls_st_need_write; + net_con_update(con, NET_EVENT_READ); + return 0; + + case SSL_ERROR_WANT_WRITE: + handle->state = tls_st_need_write; + net_con_update(con, NET_EVENT_WRITE); + return 0; + + case SSL_ERROR_SYSCALL: + return -1; + } } - return ret; } ssize_t net_ssl_recv(struct net_connection* con, void* buf, size_t len) @@ -243,17 +268,40 @@ ssize_t net_ssl_recv(struct net_connection* con, void* buf, size_t len) if (handle->state == tls_st_error) return -1; + uhub_assert(handle->state == tls_st_connected || handle->state == tls_st_need_read); + + ERR_clear_error(); + ret = SSL_read(handle->ssl, buf, len); LOG_PROTO("SSL_read(con=%p, buf=%p, len=" PRINTF_SIZE_T ") => %d", con, buf, len, ret); if (ret > 0) { - net_con_update(con, NET_EVENT_READ); + handle->state = tls_st_connected; + return ret; } - else + else if (ret <= 0) { - return handle_openssl_error(con, ret); + int err = SSL_get_error(handle->ssl, ret); + switch (err) + { + case SSL_ERROR_ZERO_RETURN: + // Not really an error, but SSL was shut down. + return -1; + + case SSL_ERROR_WANT_READ: + handle->state = tls_st_need_read; + net_con_update(con, NET_EVENT_READ); + return 0; + + case SSL_ERROR_WANT_WRITE: + handle->state = tls_st_need_read; + net_con_update(con, NET_EVENT_WRITE); + return 0; + + case SSL_ERROR_SYSCALL: + return -1; + } } - return ret; } void net_ssl_shutdown(struct net_connection* con) @@ -299,20 +347,15 @@ void net_ssl_callback(struct net_connection* con, int events) con->callback(con, NET_EVENT_READ, con->ptr); break; + case tls_st_need_read: + con->callback(con, NET_EVENT_READ, con->ptr); + break; + + case tls_st_need_write: + con->callback(con, NET_EVENT_WRITE, con->ptr); + break; + case tls_st_connected: - LOG_PROTO("tls_st_connected, events=%s%s, ssl_flags=%s%s", (events & NET_EVENT_READ ? "R" : ""), (events & NET_EVENT_WRITE ? "W" : ""), flags & NET_WANT_SSL_READ ? "R" : "", flags & NET_WANT_SSL_WRITE ? "W" : ""); - if (events & NET_EVENT_WRITE && flags & NET_WANT_SSL_READ) - { - con->callback(con, events & NET_EVENT_READ, con->ptr); - return; - } - - if (events & NET_EVENT_READ && flags & NET_WANT_SSL_WRITE) - { - con->callback(con, events & NET_EVENT_READ, con->ptr); - return; - } - con->callback(con, events, con->ptr); break; diff --git a/src/network/tls.h b/src/network/tls.h index 08b4da6..25391a4 100644 --- a/src/network/tls.h +++ b/src/network/tls.h @@ -32,6 +32,8 @@ enum ssl_state tls_st_accepting, tls_st_connecting, tls_st_connected, + tls_st_need_read, /* special case of connected */ + tls_st_need_write, /* special case of connected */ tls_st_disconnecting, }; From c43acd97bd8a6264820dd2dcce57ff64760bbb16 Mon Sep 17 00:00:00 2001 From: Jan Vidar Krey Date: Tue, 16 Oct 2012 20:15:38 +0200 Subject: [PATCH 5/7] Fixed accept/connect state event propagation. Also removed some unused states and flags. --- src/network/common.h | 5 ----- src/network/openssl.c | 10 ++-------- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/src/network/common.h b/src/network/common.h index 48eeec4..8270da2 100644 --- a/src/network/common.h +++ b/src/network/common.h @@ -20,11 +20,6 @@ #define NET_WANT_READ NET_EVENT_READ #define NET_WANT_WRITE NET_EVENT_WRITE #define NET_WANT_ACCEPT NET_EVENT_READ -#define NET_WANT_SSL_READ 0x0010 -#define NET_WANT_SSL_WRITE 0x0020 -#define NET_WANT_SSL_ACCEPT 0x0040 -#define NET_WANT_SSL_CONNECT 0x0080 -#define NET_WANT_SSL_X509_LOOKUP 0x0100 #define NET_SSL_ANY NET_WANT_SSL_READ | NET_WANT_SSL_WRITE | NET_WANT_SSL_ACCEPT | NET_WANT_SSL_CONNECT | NET_WANT_SSL_X509_LOOKUP diff --git a/src/network/openssl.c b/src/network/openssl.c index cd09d4d..322dfd1 100644 --- a/src/network/openssl.c +++ b/src/network/openssl.c @@ -320,9 +320,6 @@ void net_ssl_destroy(struct net_connection* con) void net_ssl_callback(struct net_connection* con, int events) { struct net_ssl_openssl* handle = get_handle(con); - int ret; - uint32_t flags = con->flags; - con->flags &= ~NET_SSL_ANY; /* reset the SSL related flags */ switch (handle->state) { @@ -335,15 +332,12 @@ void net_ssl_callback(struct net_connection* con, int events) break; case tls_st_accepting: - if (net_con_ssl_accept(con) < 0) - { + if (net_con_ssl_accept(con) != 0) con->callback(con, NET_EVENT_READ, con->ptr); - } break; case tls_st_connecting: - ret = net_con_ssl_connect(con); - if (ret != 0) + if (net_con_ssl_connect(con) != 0) con->callback(con, NET_EVENT_READ, con->ptr); break; From 5884983a2f16b023ef6ad017aa3db0d01c9ede63 Mon Sep 17 00:00:00 2001 From: Jan Vidar Krey Date: Tue, 16 Oct 2012 20:15:38 +0200 Subject: [PATCH 6/7] Return -1 as error for recv/send only to signal socket has closed, use a number < -1 for socket errors. --- src/network/openssl.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/network/openssl.c b/src/network/openssl.c index 322dfd1..fe5cfa4 100644 --- a/src/network/openssl.c +++ b/src/network/openssl.c @@ -142,7 +142,7 @@ ssize_t net_con_ssl_accept(struct net_connection* con) return 0; case SSL_ERROR_SYSCALL: - return -1; + return -2; } } return ret; @@ -182,7 +182,7 @@ ssize_t net_con_ssl_connect(struct net_connection* con) return 0; case SSL_ERROR_SYSCALL: - return -1; + return -2; } } return ret; @@ -255,7 +255,7 @@ ssize_t net_ssl_send(struct net_connection* con, const void* buf, size_t len) return 0; case SSL_ERROR_SYSCALL: - return -1; + return -2; } } } @@ -266,7 +266,7 @@ ssize_t net_ssl_recv(struct net_connection* con, void* buf, size_t len) ssize_t ret; if (handle->state == tls_st_error) - return -1; + return -2; uhub_assert(handle->state == tls_st_connected || handle->state == tls_st_need_read); @@ -299,7 +299,7 @@ ssize_t net_ssl_recv(struct net_connection* con, void* buf, size_t len) return 0; case SSL_ERROR_SYSCALL: - return -1; + return -2; } } } From 2f830d3132a4868bc84e71fafbd69a0c48f28918 Mon Sep 17 00:00:00 2001 From: Jan Vidar Krey Date: Tue, 16 Oct 2012 20:15:38 +0200 Subject: [PATCH 7/7] Cleaned up error handling. --- src/network/openssl.c | 122 +++++++++++------------------------------- 1 file changed, 32 insertions(+), 90 deletions(-) diff --git a/src/network/openssl.c b/src/network/openssl.c index fe5cfa4..78f6a5d 100644 --- a/src/network/openssl.c +++ b/src/network/openssl.c @@ -111,6 +111,32 @@ int ssl_check_private_key(struct ssl_context_handle* ctx_) return 1; } +static int handle_openssl_error(struct net_connection* con, int ret, enum ssl_state forced_rwstate) +{ + struct net_ssl_openssl* handle = get_handle(con); + int err = SSL_get_error(handle->ssl, ret); + switch (err) + { + case SSL_ERROR_ZERO_RETURN: + // Not really an error, but SSL was shut down. + return -1; + + case SSL_ERROR_WANT_READ: + handle->state = forced_rwstate; + net_con_update(con, NET_EVENT_READ); + return 0; + + case SSL_ERROR_WANT_WRITE: + handle->state = forced_rwstate; + net_con_update(con, NET_EVENT_WRITE); + return 0; + + case SSL_ERROR_SYSCALL: + handle->state = tls_st_error; + return -2; + } +} + ssize_t net_con_ssl_accept(struct net_connection* con) { struct net_ssl_openssl* handle = get_handle(con); @@ -123,29 +149,9 @@ ssize_t net_con_ssl_accept(struct net_connection* con) { net_con_update(con, NET_EVENT_READ); handle->state = tls_st_connected; + return ret; } - else - { - int err = SSL_get_error(handle->ssl, ret); - switch (err) - { - case SSL_ERROR_ZERO_RETURN: - // Not really an error, but SSL was shut down. - return -1; - - case SSL_ERROR_WANT_READ: - net_con_update(con, NET_EVENT_READ); - return 0; - - case SSL_ERROR_WANT_WRITE: - net_con_update(con, NET_EVENT_WRITE); - return 0; - - case SSL_ERROR_SYSCALL: - return -2; - } - } - return ret; + return handle_openssl_error(con, ret, tls_st_accepting); } ssize_t net_con_ssl_connect(struct net_connection* con) @@ -163,29 +169,9 @@ ssize_t net_con_ssl_connect(struct net_connection* con) { handle->state = tls_st_connected; net_con_update(con, NET_EVENT_READ); + return ret; } - else - { - int err = SSL_get_error(handle->ssl, ret); - switch (err) - { - case SSL_ERROR_ZERO_RETURN: - // Not really an error, but SSL was shut down. - return -1; - - case SSL_ERROR_WANT_READ: - net_con_update(con, NET_EVENT_READ); - return 0; - - case SSL_ERROR_WANT_WRITE: - net_con_update(con, NET_EVENT_WRITE); - return 0; - - case SSL_ERROR_SYSCALL: - return -2; - } - } - return ret; + return handle_openssl_error(con, ret, tls_st_connecting); } ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode ssl_mode, struct ssl_context_handle* ssl_ctx) @@ -235,29 +221,7 @@ ssize_t net_ssl_send(struct net_connection* con, const void* buf, size_t len) handle->state = tls_st_connected; return ret; } - else if (ret <= 0) - { - int err = SSL_get_error(handle->ssl, ret); - switch (err) - { - case SSL_ERROR_ZERO_RETURN: - // Not really an error, but SSL was shut down. - return -1; - - case SSL_ERROR_WANT_READ: - handle->state = tls_st_need_write; - net_con_update(con, NET_EVENT_READ); - return 0; - - case SSL_ERROR_WANT_WRITE: - handle->state = tls_st_need_write; - net_con_update(con, NET_EVENT_WRITE); - return 0; - - case SSL_ERROR_SYSCALL: - return -2; - } - } + return handle_openssl_error(con, ret, tls_st_need_write); } ssize_t net_ssl_recv(struct net_connection* con, void* buf, size_t len) @@ -279,29 +243,7 @@ ssize_t net_ssl_recv(struct net_connection* con, void* buf, size_t len) handle->state = tls_st_connected; return ret; } - else if (ret <= 0) - { - int err = SSL_get_error(handle->ssl, ret); - switch (err) - { - case SSL_ERROR_ZERO_RETURN: - // Not really an error, but SSL was shut down. - return -1; - - case SSL_ERROR_WANT_READ: - handle->state = tls_st_need_read; - net_con_update(con, NET_EVENT_READ); - return 0; - - case SSL_ERROR_WANT_WRITE: - handle->state = tls_st_need_read; - net_con_update(con, NET_EVENT_WRITE); - return 0; - - case SSL_ERROR_SYSCALL: - return -2; - } - } + return handle_openssl_error(con, ret, tls_st_need_read); } void net_ssl_shutdown(struct net_connection* con)