Code

ssl: Register OpenSSL thread-ID and locking callbacks.
authorSebastian Harl <sh@tokkee.org>
Tue, 10 Feb 2015 07:46:41 +0000 (08:46 +0100)
committerSebastian Harl <sh@tokkee.org>
Tue, 10 Feb 2015 07:46:41 +0000 (08:46 +0100)
This is required for multi-threaded applications. Else, they "will crash at
random".

src/include/utils/ssl.h
src/tools/sysdb/main.c
src/tools/sysdbd/main.c
src/utils/ssl.c

index f15d3fab362cdbf3bc63ccf2a0d0ab776fc78c3c..53a794f68b3c9add760ba43a7e4bb6a9f3d6fe75 100644 (file)
@@ -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);
index c58c735675106da0ebc33afd94680cc7478dfc89..792faf9d93a7ff62d407b23320729e35c83cd6d7 100644 (file)
@@ -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) {
index 179ec791ab97302fbac8fc422b3e0f3651678f85..759eee2f5652ebee72c9131d22a05ddbf8f704b2 100644 (file)
@@ -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);
 
index fe509d05c3dd461e5e0d79620070abdeb5d97444..0bd41a3641766379a47d0ef14cc5ca4622219efe 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 
+#include <pthread.h>
+
 #include <openssl/ssl.h>
 #include <openssl/bio.h>
+#include <openssl/crypto.h>
 #include <openssl/x509.h>
 #include <openssl/err.h>
 
@@ -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 */