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_ ();  } | 
