Merge pull request #86 from vcrhonek/ssl-thread-safe
Fix SSL library usage is not thread safe
diff --git a/src/server/wsmand-listener.c b/src/server/wsmand-listener.c
index a1cfe1f..3bbf4a6 100644
--- a/src/server/wsmand-listener.c
+++ b/src/server/wsmand-listener.c
@@ -83,6 +83,10 @@
#endif
#include <sys/socket.h>
+/* SSL thread safe */
+#include <openssl/crypto.h>
+static pthread_mutex_t *lock_cs;
+static long *lock_count;
static pthread_mutex_t shttpd_mutex;
static pthread_cond_t shttpd_cond;
@@ -107,6 +111,50 @@
int gss_encrypt(struct shttpd_arg *arg, char *input, int inlen, char **output, int *outlen);
#endif
+/* SSL thread safe */
+void pthreads_locking_callback(int mode, int type, char *file, int line) {
+ if (mode & CRYPTO_LOCK) {
+ pthread_mutex_lock(&(lock_cs[type]));
+ lock_count[type]++;
+ }
+ else {
+ pthread_mutex_unlock(&(lock_cs[type]));
+ }
+}
+
+unsigned long pthreads_thread_id(void) {
+ unsigned long ret;
+
+ ret = (unsigned long)pthread_self();
+ return(ret);
+}
+
+void thread_setup(void) {
+ int i;
+
+ lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
+ lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
+ for (i = 0; i < CRYPTO_num_locks(); i++) {
+ lock_count[i] = 0;
+ pthread_mutex_init(&(lock_cs[i]), NULL);
+ }
+
+ CRYPTO_set_id_callback((unsigned long (*)())pthreads_thread_id);
+ CRYPTO_set_locking_callback((void (*)())pthreads_locking_callback);
+}
+
+void thread_cleanup(void) {
+ int i;
+
+ CRYPTO_set_locking_callback(NULL);
+ for (i = 0; i < CRYPTO_num_locks(); i++) {
+ pthread_mutex_destroy(&(lock_cs[i]));
+ }
+
+ OPENSSL_free(lock_cs);
+ OPENSSL_free(lock_count);
+}
+
/* Check HTTP headers */
static
int check_request_content_type(struct shttpd_arg *arg) {
@@ -723,6 +771,10 @@
if (wsman_setup_thread(&pattrs) == 0 )
return listener;
+
+ /* SSL thread safe */
+ thread_setup();
+
pthread_create(&tid, &pattrs, wsman_server_auxiliary_loop_thread, cntx);
#ifdef ENABLE_EVENTING_SUPPORT
@@ -749,5 +801,9 @@
}
shttpd_add_socket(thread->ctx, sock, use_ssl);
}
+
+ /* SSL thread safe */
+ thread_cleanup();
+
return listener;
}