From 50912bdf75cedc8192de95273fd11e3e5aa072e8 Mon Sep 17 00:00:00 2001 From: Jan Vidar Krey Date: Mon, 15 Oct 2012 20:39:03 +0200 Subject: [PATCH] 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 +}