From 3efc86a3419d04f3a323583b977af539e915be39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilja=20Karta=C5=A1ov?= Date: Fri, 8 Mar 2019 23:19:54 +0100 Subject: [PATCH] Refactored SSL and callbacks --- include/aisl/config.h | 2 +- include/aisl/instance.h | 2 +- src/callback.c | 11 ++ src/callback.h | 42 ++++++++ src/instance.c | 231 +++++++++++++++++----------------------- src/list.h | 87 ++------------- src/server.h | 3 +- src/ssl.c | 118 ++++++++++++++++++++ src/ssl.h | 39 +++++++ 9 files changed, 316 insertions(+), 219 deletions(-) create mode 100644 src/callback.c create mode 100644 src/callback.h create mode 100644 src/ssl.c create mode 100644 src/ssl.h diff --git a/include/aisl/config.h b/include/aisl/config.h index 9643c71..83bc27f 100644 --- a/include/aisl/config.h +++ b/include/aisl/config.h @@ -18,7 +18,7 @@ struct aisl_config uint32_t servers_spool_size; uint32_t clients_spool_size; uint32_t ssl_spool_size; - uint32_t events_spool_size; + uint32_t callbacks_spool_size; uint32_t initial_buffer_size; uint32_t clients_accept_limit; }; diff --git a/include/aisl/instance.h b/include/aisl/instance.h index 177bc78..ae82134 100644 --- a/include/aisl/instance.h +++ b/include/aisl/instance.h @@ -31,7 +31,7 @@ aisl_server_t aisl_listen( aisl_t instance, const char * address, uint16_t port ); -#ifdef AISL_WITH_SSL +#ifndef AISL_WITHOUT_SSL aisl_status_t aisl_set_ssl( aisl_t instance, diff --git a/src/callback.c b/src/callback.c new file mode 100644 index 0000000..d7c2b89 --- /dev/null +++ b/src/callback.c @@ -0,0 +1,11 @@ +/* + * callback.c + * Copyright (C) 2019 Ilja Kartašov + * + * Distributed under terms of the MIT license. + */ + +#include "callback.h" + + + diff --git a/src/callback.h b/src/callback.h new file mode 100644 index 0000000..f3fb147 --- /dev/null +++ b/src/callback.h @@ -0,0 +1,42 @@ +/* + * src/callback.h + * + * Copyright (C) 2019 Ilja Kartašov + * + * Project homepage: https://lowenware.com/aisl/ + * + */ + +#ifndef AISL_CALLBACK_H_43D3FC6B_22E5_481C_8EB2_00BF8C3D52CA +#define AISL_CALLBACK_H_43D3FC6B_22E5_481C_8EB2_00BF8C3D52CA + +#include + + +struct callback +{ + void * source; + aisl_callback_t callback; + aisl_event_t eevent; +}; + +typedef struct callback * callback_t; + + +static listener_t +listener_new( void * source, aisl_event_t e_id, aisl_callback_t cb) +{ + listener_t self = malloc(sizeof(struct listener)); + if (self) + { + self->source = source; + self->e_id = e_id; + self->cb = cb; + } + + return self; +} + + + +#endif /* !AISL_CALLBACK_H */ diff --git a/src/instance.c b/src/instance.c index dbba0b3..35a5ebb 100644 --- a/src/instance.c +++ b/src/instance.c @@ -21,6 +21,7 @@ #include "client.h" #include "server.h" +#include "ssl.h" //#include "globals.h" //#include "stream.h" #include "instance.h" @@ -32,12 +33,22 @@ enum { }; +struct callback +{ + void * source; + aisl_callback_t callback; + aisl_event_t eevent; +}; + +typedef struct callback * callback_t; + + struct aisl { list_t servers; list_t clients; list_t callbacks; - #ifdef AISL_WITH_SSL + #ifndef AISL_WITHOUT_SSL list_t ssl; #endif buffer_t buffer; @@ -49,7 +60,7 @@ struct aisl }; -#ifdef AISL_WITH_SSL +#ifndef AISL_WITHOUT_SSL static uint32_t m_instances = 0; #endif @@ -62,7 +73,7 @@ aisl_new( aisl_config_t config ) { aisl_t instance; - #ifdef AISL_WITH_SSL + #ifndef AISL_WITHOUT_SSL if ((m_instances++) == 0) { SSL_load_error_strings(); @@ -85,7 +96,7 @@ aisl_new( aisl_config_t config ) if ( !(instance->buffer = buffer_new(config->initial_buffer_size)) ) goto release; - #ifdef AISL_WITH_SSL + #ifndef AISL_WITHOUT_SSL if ( !(instance->ssl = list_new(config->ssl_spool_size)) ) goto release; #endif @@ -119,15 +130,17 @@ aisl_free( aisl_t instance ) if (instance->buffer) buffer_free(instance->buffer); + #ifndef AISL_WITHOUT_SSL if (instance->ssl) list_free(instance->ssl, (list_destructor_t) ssl_free ); + #endif if (instance->last_error) free(instance->last_error); free(instance); - #ifdef AISL_WITH_SSL + #ifndef AISL_WITHOUT_SSL if ((--m_instances) == 0) { EVP_cleanup(); @@ -142,10 +155,8 @@ aisl_listen( aisl_t instance, const char * address, uint16_t port ) { aisl_server_t result; - if ( (result = aisl_server_new(address, port)) != NULL ) + if ( (result = aisl_server_new(instance, address, port)) != NULL ) { - result->instance = instance; - if (list_append(instance->servers, result) == LIST_NAN) { aisl_server_free(result); @@ -156,128 +167,71 @@ aisl_listen( aisl_t instance, const char * address, uint16_t port ) } -#ifdef AISL_WITH_SSL - - -static int -get_ssl_context( SSL * ssl, int * ptr, void * handle ) -{ - const char * server_name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); - - SSL_CTX * ctx = aisl_get_ssl_ctx( (aisl_t) handle, server_name ); - - if (ctx) - { - SSL_set_SSL_CTX(ssl, ctx); - } - - return SSL_TLSEXT_ERR_OK; -} - -/* -------------------------------------------------------------------------- */ - -static SSL_CTX * -create_ssl_context( aisl_t instance, - const char * key_file, - const char * crt_file ) -{ - const SSL_METHOD * method; - SSL_CTX * ctx; - - method = SSLv23_server_method(); - - if ( !(ctx = SSL_CTX_new(method)) ) - goto except; - - SSL_CTX_set_ecdh_auto(ctx, 1); - - SSL_CTX_set_tlsext_servername_callback( ctx, get_ssl_context ); - SSL_CTX_set_tlsext_servername_arg( ctx, (void *) instance ); - - if (!(SSL_CTX_use_certificate_file(ctx, crt_file, SSL_FILETYPE_PEM) > 0)) - goto release; - - if (!(SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) > 0)) - goto release; - - goto finally; - -release: - SSL_CTX_free(ctx); - ctx = NULL; - -except: - aisl_set_error( instance, ERR_error_string(ERR_get_error(),NULL) ); - -finally: - return ctx; -} +#ifndef AISL_WITHOUT_SSL __attribute__ ((visibility ("default") )) aisl_status_t -aisl_set_ssl( aisl_t instance, const char * server_name, - const char * key_file, - const char * crt_file ) +aisl_set_ssl( aisl_t instance, const char * domain, + const char * key_file, + const char * crt_file ) { SSL_CTX * ssl_ctx = NULL; - int i; - crypter_t crypter; + ssl_t ssl; + size_t i; /* lookup for existing contexts */ - for (i=0; icrypters->count; i++) + for (i=0; issl->count; i++) { - crypter = list_index(instance->crypters, i); - if (crypter->keyFile && strcmp(crypter->keyFile, key_file)==0 && - crypter->crtFile && strcmp(crypter->crtFile, crt_file)==0 ) + ssl = list_index(instance->ssl, i); + if (ssl->key_file && strcmp(ssl->key_file, key_file)==0 && + ssl->crt_file && strcmp(ssl->crt_file, crt_file)==0 ) { - ssl_ctx = crypter->sslCtx; - key_file = NULL; - crt_file = NULL; - break; + if ((ssl_ctx = crypter->ssl_ctx) != NULL) + { + key_file = NULL; + crt_file = NULL; + break; + } } } - if (! (crypter = crypter_new(server_name, key_file, crt_file)) ) + if ((ssl = ssl_new(domain, key_file, crt_file)) != NULL) { - return AISL_MALLOC_ERROR; - } + if (! ssl_ctx) + ssl_ctx = ssl__new_context(key_file, crt_file, (void*)instance); - if (! ssl_ctx) - { - if (!(ssl_ctx = create_ssl_context(instance, key_file, crt_file))) + if (ssl_ctx) { - crypter_free(crypter); - return AISL_EXTCALL_ERROR; + ssl->ctx = ssl_ctx; + if (list_append(instance->ssl, ssl) != LIST_NAN) + { + return AISL_SUCCESS; + } } + + ssl_free(ssl); } - crypter->sslCtx = ssl_ctx; - - if (list_append(instance->crypters, crypter)==-1) - { - crypter_free(crypter); - return AISL_MALLOC_ERROR; - } - - return AISL_SUCCESS; + return AISL_MALLOC_ERROR; } + SSL_CTX * -aisl_get_ssl_ctx( aisl_t instance, const char * server_name ) +aisl_get_ssl_ctx( aisl_t instance, const char * domain ) { - int i; - crypter_t crypter; + size_t i; + ssl_t ssl; - for (i=0; icrypters->count; i++) + if (domain) { - crypter = list_index(instance->crypters, i); - if (server_name) + for (i=0; issl->count; i++) { - if (strcmp(crypter->srvName, server_name)!=0) + ssl = list_index(instance->ssl, i); + if (strcmp(ssl->domain, domain) != 0) continue; - } - return crypter->sslCtx; + return ssl->ctx; + } } return NULL; @@ -288,35 +242,39 @@ aisl_get_ssl_ctx( aisl_t instance, const char * server_name ) __attribute__ ((visibility ("default") )) aisl_status_t -aisl_set_callback( aisl_t instance, +aisl_set_callback( aisl_t instance, void * source, - aisl_event_t e_id, - aisl_callback_t cb ) + aisl_event_t event, + aisl_callback_t callback ) { - listener_t listener; + callback_t cb; - if (! (listener = listener_new(source, e_id, cb)) ) - return AISL_MALLOC_ERROR; - - if (list_append(instance->callbacks, listener) == -1) + if ( (cb = malloc(sizeof(struct callback))) != NULL ) { - free(listener); - return AISL_MALLOC_ERROR; - } + cb->source = source; + cb->event = event; + cb->callback = callback; - if (e_id == AISL_STREAM_OUTPUT) /* subscribtion for chunked output */ - { - if (source) + if ( list_append(instance->callbacks, cb) != LIST_NAN ) { - ( (stream_t) source )->flags |= STREAM_FLAG_OUTPUT_CHUNKED; - } - } - else if (e_id == AISL_STREAM_OPEN) - { - instance->flags |= AISL_HANDLE_HAS_STREAM_LISTENERS; - } + switch(event) + { + case AISL_STREAM_OUTPUT: + if (source) + stream_set_chunked_output( (aisl_stream_t) source ); + //( (stream_t) source )->flags |= STREAM_FLAG_OUTPUT_CHUNKED; + break; - return AISL_SUCCESS; + case AISL_STREAM_OPEN: + instance->flags |= AISL_FLAG_HAS_STREAM_LISTENERS; + break; + } + + return AISL_SUCCESS; + } + free(cb); + } + return AISL_MALLOC_ERROR; } @@ -324,20 +282,23 @@ __attribute__ ((visibility ("default") )) void aisl_unset_callback_for( aisl_t instance, void * source ) { - int i=instance->callbacks->count-1; - while ( !(i < 0) ) - { - listener_t listener = list_index(instance->callbacks, i); - if ( listener->source == source ) - { - free(listener); - list_remove_index(instance->callbacks, i); - } + size_t i = instance->callbacks->count; - i--; + if (i) + { + for(i=i-1; i <= 0; i-- ) + { + callback_t callback = list_index(instance->callbacks, i); + if ( callback->source == source ) + { + free(callback); + list_remove_index(instance->callbacks, i); + } + } } } + __attribute__ ((visibility ("default") )) bool aisl_raise( aisl_t instance, diff --git a/src/list.h b/src/list.h index 3ac90e4..b66a391 100644 --- a/src/list.h +++ b/src/list.h @@ -1,120 +1,47 @@ -/* list.h - header file of the list_t module - * Copyright (c) 2017 Löwenware Ltd (https://lowenware.com) - * - * REPOSITORY: - * https://github.com/lowenware.com:cStuff.git - * MAINTAINER: - * Ilja Kartaschoff - * - * LICENSE and DISCLAIMER: - * All code stored in this repository is designed to solve - * very common and widely meet development tasks. We are not about to patent - * wheels here, so all code you can find in this repository is FREE: - * you can use, redistribute and/or modify it without any limits or - * restrictions. - * - * All code described above is distributed in hope to be useful for somebody - * else WITHOUT ANY WARRANTY, without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * In case of questions or suggestions, feel free to contact maintainer. - * - * */ - -#ifndef _CSTUFF_LIST_H_ -#define _CSTUFF_LIST_H_ +#ifndef AISL_LIST_H_3223EF5C_CCF2_4D7C_8A3B_8BAF122E473F +#define AISL_LIST_H_3223EF5C_CCF2_4D7C_8A3B_8BAF122E473F #include -/* MODULE: list_t - * Dynamic storage for pointers */ - -/* structure ---------------------------------------------------------------- */ +#define LIST_NAN (~0) struct list { - void **list; /* list itself */ - int size; /* number of bytes allocated for list */ - int count; /* number of defined items in list */ + void ** list; + size_t size; + size_t count; }; typedef struct list * list_t; -/* callback to free memory used by stored item ------------------------------ */ typedef void (* list_destructor_t)(void * list_item); -/* functions ---------------------------------------------------------------- */ - -/* get list item by index macro - * @self : list_t instance - * @index : item index - * @result : stored pointer - * */ #define list_index(self, index) (self->list[index]) -/* -------------------------------------------------------------------------- */ - -/* create new list_t object - * @size : initial list size - * @result new list_t instance - * */ list_t list_new(int size); -/* -------------------------------------------------------------------------- */ - -/* free resources allocated for list_t instance - * @self : list_t instance - * @destructor : if set, destructor method will be called for each not-null - * list entry - * */ void list_free(list_t self, list_destructor_t destructor); -/* -------------------------------------------------------------------------- */ - -/* insert new item into list at some position, - * memory will be allocated if necessary - * @self : list_t instance - * @item : pointer to be inserted - * @position : number from 0(prepend) to list size (append) - * */ int list_insert( list_t self, void * item, int position ); -/* append item to queue list - * @self : list_t object - * @item : pointer to be appended - * @result : position at which pointer was stored - * */ int list_append(list_t self, void * item); -/* remove pointer from list - * @self : list_t object - * @item : to be removed - * */ void list_remove( list_t self, void * item ); -/* remove pointer from list by index - * @self : list_t object - * @index : index of pointer to be removed - * */ void * list_remove_index( list_t self, int index ); -/* set pointer by index. if element does not exist, list won't be extended - * @self : list_t object - * @index : index of pointer to be removed - * @value : value to be set - * */ void list_set_item(list_t self, int index, void * value); -#endif +#endif /* !AISL_LIST_H */ diff --git a/src/server.h b/src/server.h index 74d5c5b..b61b2f0 100644 --- a/src/server.h +++ b/src/server.h @@ -3,7 +3,6 @@ #include #include -#include #include @@ -11,7 +10,7 @@ aisl_server_t -aisl_server_new(const char * address, int port); +aisl_server_new(aisl_t instance, const char * address, int port); void diff --git a/src/ssl.c b/src/ssl.c new file mode 100644 index 0000000..fad8d9c --- /dev/null +++ b/src/ssl.c @@ -0,0 +1,118 @@ +/* + * ssl.c + * Copyright (C) 2019 Ilja Kartašov + * + * Distributed under terms of the MIT license. + */ + +#include +#include "ssl.h" + + +#ifndef AISL_WITHOUT_SSL + +static int +get_ssl_context( SSL * ssl, int * ptr, void * handle ) +{ + const char * server_name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); + + SSL_CTX * ctx = aisl_get_ssl_ctx( (aisl_t) handle, server_name ); + + if (ctx) + { + SSL_set_SSL_CTX(ssl, ctx); + } + + return SSL_TLSEXT_ERR_OK; +} + +/* -------------------------------------------------------------------------- */ + +static SSL_CTX * +create_ssl_context( aisl_t instance, + const char * key_file, + const char * crt_file ) +{ + const SSL_METHOD * method; + SSL_CTX * ctx; + + method = SSLv23_server_method(); + + if ( !(ctx = SSL_CTX_new(method)) ) + goto except; + + SSL_CTX_set_ecdh_auto(ctx, 1); + + SSL_CTX_set_tlsext_servername_callback( ctx, get_ssl_context ); + SSL_CTX_set_tlsext_servername_arg( ctx, (void *) instance ); + + if (!(SSL_CTX_use_certificate_file(ctx, crt_file, SSL_FILETYPE_PEM) > 0)) + goto release; + + if (!(SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) > 0)) + goto release; + + goto finally; + +release: + SSL_CTX_free(ctx); + ctx = NULL; + +except: + aisl_set_error( instance, ERR_error_string(ERR_get_error(),NULL) ); + +finally: + return ctx; +} + +static void +crypter_free( crypter_t self ) +{ + if (self->srvName) + free(self->srvName); + + if (self->keyFile) + { + free(self->keyFile); + SSL_CTX_free(self->sslCtx); + } + + if (self->crtFile) + free(self->crtFile); + + free(self); +} + + +static crypter_t +crypter_new( const char * server_name, + const char * key_file, + const char * crt_file ) +{ + crypter_t self; + + if ( (self=calloc(1, sizeof(struct crypter))) != NULL ) + { + if (!(self->srvName = str_copy( server_name ? server_name : "*" ))) + goto release; + + if ( key_file && !(self->keyFile = str_copy(key_file))) + goto release; + + if ( crt_file && !(self->crtFile = str_copy(crt_file))) + goto release; + + } + + goto finally; + + +release: + crypter_free(self); + self = NULL; + +finally: + return self; +} + +#endif diff --git a/src/ssl.h b/src/ssl.h new file mode 100644 index 0000000..7d77100 --- /dev/null +++ b/src/ssl.h @@ -0,0 +1,39 @@ +/* + * src/ssl.h + * + * Copyright (C) 2019 Ilja Kartašov + * + * Project homepage: https://lowenware.com/aisl/ + * + */ + +#ifndef AISL_SSL_H_6F82B0BA_7C59_45BA_AF3B_C82A67C8585E +#define AISL_SSL_H_6F82B0BA_7C59_45BA_AF3B_C82A67C8585E + +#include +#include + + +struct ssl +{ + char * key_file; + char * crt_file; + char * domain; + SSL_CTX * ctx; +}; + +typedef struct ssl * ssl_t; + + +ssl_t +ssl_new( const char * key_file, const char * crt_file, const char * domain ); + + +void +ssl_free( ssl_t self ); + + +SSL_CTX * +ssl__new_context( const char * key_file, const char * crt_file, void * u_ptr ); + +#endif /* !AISL_SSL_H */