diff options
-rw-r--r-- | lib/CHANGES | 6 | ||||
-rw-r--r-- | lib/configure.ac | 4 | ||||
-rw-r--r-- | lib/tls.c | 57 |
3 files changed, 65 insertions, 2 deletions
diff --git a/lib/CHANGES b/lib/CHANGES index a7640e7..de83d34 100644 --- a/lib/CHANGES +++ b/lib/CHANGES @@ -1,3 +1,9 @@ +Changes between 0.0.4 and 0.0.5.dev + + - When POSIX thread support is detected at configure and build time + libradsec will be more safe to use by programs that call it from + more than one thread simultaneously. + User visible changes between 0.0.1 and 0.0.4 - TLS support is now enabled by default. Use --disable-tls to diff --git a/lib/configure.ac b/lib/configure.ac index bab02ed..7d8bd5f 100644 --- a/lib/configure.ac +++ b/lib/configure.ac @@ -17,6 +17,8 @@ AC_CHECK_LIB([confuse], [cfg_init],, AC_MSG_ERROR([required library libconfuse not found])) AC_CHECK_LIB([event_core], [event_get_version],, AC_MSG_ERROR([required library libevent_core not found])) +AH_TEMPLATE([HAVE_PTHREADS], [POSIX threads are available on this system]) +AC_SEARCH_LIBS([pthread_create], [pthread], AC_DEFINE([HAVE_PTHREADS])) # Enable-knobs. ## Enable TLS (RadSec), default on. @@ -47,7 +49,7 @@ AM_CONDITIONAL([RS_ENABLE_TLS_PSK], [test "${enable_tls_psk+set}" = set]) # Checks for header files. AC_CHECK_HEADERS( [sys/time.h time.h netdb.h netinet/in.h stdint.h stdlib.h strings.h string.h \ - sys/socket.h unistd.h syslog.h sys/select.h fcntl.h arpa/inet.h]) + sys/socket.h unistd.h syslog.h sys/select.h fcntl.h arpa/inet.h pthread.h]) # Checks for typedefs, structures, and compiler characteristics. AC_TYPE_SIZE_T @@ -10,11 +10,15 @@ #include <assert.h> #include <fcntl.h> #include <limits.h> +#if defined HAVE_PTHREAD_H +#include <pthread.h> +#endif #include <openssl/ssl.h> #include <openssl/err.h> #include <openssl/bn.h> #include <openssl/x509v3.h> #include <openssl/rand.h> +#include <openssl/crypto.h> #include <radsec/radsec.h> #include <radsec/radsec-impl.h> @@ -182,11 +186,62 @@ init_openssl_rand_ (void) return 0; } +#if defined HAVE_PTHREADS +/** Array of pthread_mutex_t for OpenSSL. Allocated and initialised in + \a init_locking_ and never freed. */ +static pthread_mutex_t *s_openssl_mutexes = NULL; +/** Number of pthread_mutex_t's allocated at s_openssl_mutexes. */ +static int s_openssl_mutexes_count = 0; + +/** Callback for OpenSSL when a lock is to be held or released. */ +static void +openssl_locking_cb_ (int mode, int i, const char *file, int line) +{ + if (s_openssl_mutexes == NULL || i >= s_openssl_mutexes_count) + return; + if (mode & CRYPTO_LOCK) + pthread_mutex_lock (&s_openssl_mutexes[i]); + else + pthread_mutex_unlock (&s_openssl_mutexes[i]); +} + +/** Initialise any locking needed for being thread safe. Libradsec has + all its own state in one or more struct rs_context and doesn't + need locks but libraries used by libradsec may need protection. */ +static int +init_locking_ () +{ + int i, n; + n = CRYPTO_num_locks (); + + s_openssl_mutexes = calloc (n, sizeof(pthread_mutex_t)); + if (s_openssl_mutexes == NULL) + return -RSE_NOMEM; + for (i = 0; i < n; i++) + pthread_mutex_init (&s_openssl_mutexes[i], NULL); + s_openssl_mutexes_count = n; + + return 0; +} +#endif /* HAVE_PTHREADS */ + /** Initialise the TLS library. Return 0 on success, -1 on failure. */ int -tls_init (void) +tls_init () { SSL_load_error_strings (); +#if defined HAVE_PTHREADS + if (CRYPTO_get_locking_callback () == NULL) + { + assert (s_openssl_mutexes_count == 0); + /* Allocate and initialise mutexes. We will never free + these. FIXME: Is there a portable way of having a function + invoked when a solib is unloaded? -ln */ + if (init_locking_ ()) + return -1; + CRYPTO_set_locking_callback (openssl_locking_cb_); + } +#endif /* HAVE_PTHREADS */ SSL_library_init (); return init_openssl_rand_ (); } |