From c837ea62546dfd018f9c1793376c2af97abb48c9 Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Tue, 10 Feb 2015 08:46:41 +0100 Subject: [PATCH] ssl: Register OpenSSL thread-ID and locking callbacks. This is required for multi-threaded applications. Else, they "will crash at random". --- src/include/utils/ssl.h | 2 +- src/tools/sysdb/main.c | 3 +- src/tools/sysdbd/main.c | 3 +- src/utils/ssl.c | 72 ++++++++++++++++++++++++++++++++++++++++- 4 files changed, 76 insertions(+), 4 deletions(-) diff --git a/src/include/utils/ssl.h b/src/include/utils/ssl.h index f15d3fa..53a794f 100644 --- a/src/include/utils/ssl.h +++ b/src/include/utils/ssl.h @@ -72,7 +72,7 @@ typedef struct sdb_ssl_session sdb_ssl_session_t; * Global setup and shutdown of SSL/TLS. This is required before any other * function can be used. */ -void +int sdb_ssl_init(void); void sdb_ssl_shutdown(void); diff --git a/src/tools/sysdb/main.c b/src/tools/sysdb/main.c index c58c735..792faf9 100644 --- a/src/tools/sysdb/main.c +++ b/src/tools/sysdb/main.c @@ -297,7 +297,8 @@ main(int argc, char **argv) if (! input.user) exit(1); - sdb_ssl_init(); + if (sdb_ssl_init()) + exit(1); input.client = sdb_client_create(host); if (! input.client) { diff --git a/src/tools/sysdbd/main.c b/src/tools/sysdbd/main.c index 179ec79..759eee2 100644 --- a/src/tools/sysdbd/main.c +++ b/src/tools/sysdbd/main.c @@ -368,7 +368,8 @@ main(int argc, char **argv) if (daemonize()) exit(1); - sdb_ssl_init(); + if (sdb_ssl_init()) + exit(1); sdb_plugin_init_all(); plugin_main_loop.default_interval = SECS_TO_SDB_TIME(60); diff --git a/src/utils/ssl.c b/src/utils/ssl.c index fe509d0..0bd41a3 100644 --- a/src/utils/ssl.c +++ b/src/utils/ssl.c @@ -37,8 +37,11 @@ #include #include +#include + #include #include +#include #include #include @@ -60,6 +63,40 @@ struct sdb_ssl_session { SSL *ssl; }; +/* + * OpenSSL helper functions + */ + +static pthread_mutex_t *mutexes = NULL; +static int mutexes_num = 0; + +static void +locking_callback(int mode, int n, const char *file, int line) +{ + if (! mutexes) { + sdb_log(SDB_LOG_EMERG, "ssl: CRYPTO_lock called from %s:%d " + "before initializing SSL", file, line); + return; + } + if (n >= mutexes_num) { + sdb_log(SDB_LOG_EMERG, "ssl: CRYPTO_lock called from %s:%d " + "for mutex %d but only %d are available", + file, line, n, mutexes_num); + return; + } + + if (mode & CRYPTO_LOCK) + pthread_mutex_lock(&mutexes[n]); + else + pthread_mutex_unlock(&mutexes[n]); +} /* locking_callback */ + +static void +threadid_callback(CRYPTO_THREADID *id) +{ + CRYPTO_THREADID_set_numeric(id, (unsigned long)pthread_self()); +} /* threadid_callback */ + /* * private helper functions */ @@ -171,16 +208,49 @@ copy_options(sdb_ssl_options_t *dst, const sdb_ssl_options_t *src) * public API */ -void +int sdb_ssl_init(void) { + int i; + SSL_load_error_strings(); OpenSSL_add_ssl_algorithms(); + + mutexes = calloc(CRYPTO_num_locks(), sizeof(*mutexes)); + if (! mutexes) { + char errbuf[1024]; + sdb_log(SDB_LOG_ERR, "ssl: Failed to allocate mutexes: %s", + sdb_strerror(errno, errbuf, sizeof(errbuf))); + return -1; + } + for (i = 0; i < CRYPTO_num_locks(); ++i) { + errno = pthread_mutex_init(&mutexes[i], /* attr = */ NULL); + if (errno) { + char errbuf[1024]; + sdb_log(SDB_LOG_ERR, "ssl: Failed to initialize mutex: %s", + sdb_strerror(errno, errbuf, sizeof(errbuf))); + return -1; + } + mutexes_num = i + 1; + } + + CRYPTO_set_locking_callback(locking_callback); + CRYPTO_THREADID_set_callback(threadid_callback); + return 0; } /* sdb_ssl_init */ void sdb_ssl_shutdown(void) { + int i; + + for (i = 0; i < mutexes_num; ++i) + pthread_mutex_destroy(&mutexes[i]); + if (mutexes) + free(mutexes); + mutexes = NULL; + mutexes_num = 0; + ERR_free_strings(); } /* sdb_ssl_shutdown */ -- 2.30.2