aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--ConfigureChecks.cmake10
-rw-r--r--config.h.cmake8
-rw-r--r--include/libssh/callbacks.h15
-rw-r--r--include/libssh/threads.h13
-rw-r--r--libssh/dh.c2
-rw-r--r--libssh/threads.c121
-rw-r--r--tests/unittests/torture_rand.c5
8 files changed, 135 insertions, 41 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1276d149..e7c5b6ce 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -62,6 +62,8 @@ else (WITH_GCRYPT)
endif (NOT OPENSSL_FOUND)
endif(WITH_GCRYPT)
+#find out if we have threading available
+include(FindThreads)
# config.h checks
include(ConfigureChecks.cmake)
configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake
index e8f01a90..4a1738be 100644
--- a/ConfigureChecks.cmake
+++ b/ConfigureChecks.cmake
@@ -58,6 +58,12 @@ check_include_file(openssl/blowfish.h HAVE_OPENSSL_BLOWFISH_H)
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
check_include_file(openssl/des.h HAVE_OPENSSL_DES_H)
+include(FindThreads)
+
+if(CMAKE_HAVE_PTHREAD_H)
+ set(HAVE_PTHREAD_H)
+endif(CMAKE_HAVE_PTHREAD_H)
+
# FUNCTIONS
if (UNIX)
@@ -114,6 +120,10 @@ if (WITH_DEBUG_CALLTRACE)
set(DEBUG_CALLTRACE 1)
endif (WITH_DEBUG_CALLTRACE)
+if (CMAKE_HAVE_PTHREAD_CREATE)
+ set(HAVE_PTHREAD)
+endif (CMAKE_HAVE_PTHREAD_CREATE)
+
# ENDIAN
if (NOT WIN32)
test_big_endian(WORDS_BIGENDIAN)
diff --git a/config.h.cmake b/config.h.cmake
index 257c7bc3..44f0e459 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -35,6 +35,10 @@
/* Define to 1 if you have the <openssl/des.h> header file. */
#cmakedefine HAVE_OPENSSL_DES_H 1
+/* Define to 1 if you have the <pthread.h> header file. */
+#cmakedefine HAVE_PTHREAD_H 1
+
+
/*************************** FUNCTIONS ***************************/
/* Define to 1 if you have the `vsnprintf' function. */
@@ -78,6 +82,10 @@
/* Define to 1 if you have the `z' library (-lz). */
#cmakedefine HAVE_LIBZ 1
+/* Define to 1 if you have the `pthread' library (-lpthread). */
+#cmakedefine HAVE_PTHREAD 1
+
+
/**************************** OPTIONS ****************************/
/* Define to 1 if you want to enable ZLIB */
diff --git a/include/libssh/callbacks.h b/include/libssh/callbacks.h
index 589c0aea..e66fb64e 100644
--- a/include/libssh/callbacks.h
+++ b/include/libssh/callbacks.h
@@ -248,6 +248,21 @@ typedef struct ssh_packet_callbacks_struct *ssh_packet_callbacks;
*/
LIBSSH_API int ssh_set_callbacks(ssh_session session, ssh_callbacks cb);
+/** @} */
+
+typedef int (*ssh_thread_callback) (void **lock);
+typedef unsigned long (*ssh_thread_id_callback) (void);
+struct ssh_threads_callbacks_struct {
+ ssh_thread_callback mutex_init;
+ ssh_thread_callback mutex_destroy;
+ ssh_thread_callback mutex_lock;
+ ssh_thread_callback mutex_unlock;
+ ssh_thread_id_callback thread_id;
+};
+
+LIBSSH_API int ssh_init_set_threads_callbacks(struct ssh_threads_callbacks_struct
+ *cb);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/libssh/threads.h b/include/libssh/threads.h
index 6f82ee33..d83e4219 100644
--- a/include/libssh/threads.h
+++ b/include/libssh/threads.h
@@ -22,17 +22,10 @@
#ifndef THREADS_H_
#define THREADS_H_
-typedef int (*ssh_thread_callback) (void **lock);
-struct ssh_threads_callbacks_struct {
- ssh_thread_callback mutex_init;
- ssh_thread_callback mutex_destroy;
- ssh_thread_callback mutex_lock;
- ssh_thread_callback mutex_unlock;
-};
+#include <libssh/callbacks.h>
int ssh_threads_init(void);
-int ssh_init_set_threads_callbacks(struct ssh_threads_callbacks_struct
- *cb);
-int ssh_init_set_threads_pthreads(void);
+void ssh_threads_finalize(void);
+
#endif /* THREADS_H_ */
diff --git a/libssh/dh.c b/libssh/dh.c
index c81ed8fc..eff74bf9 100644
--- a/libssh/dh.c
+++ b/libssh/dh.c
@@ -55,6 +55,7 @@
#include "libssh/session.h"
#include "libssh/keys.h"
#include "libssh/dh.h"
+#include "libssh/threads.h"
/* todo: remove it */
#include "libssh/string.h"
@@ -155,6 +156,7 @@ void ssh_crypto_finalize(void) {
bignum_free(p);
p = NULL;
ssh_crypto_initialized=0;
+ ssh_threads_finalize();
}
}
diff --git a/libssh/threads.c b/libssh/threads.c
index c7fc37bf..63e9d83f 100644
--- a/libssh/threads.c
+++ b/libssh/threads.c
@@ -30,10 +30,13 @@
#include "libssh/priv.h"
#include "libssh/threads.h"
+#ifndef HAVE_PTHREAD
+#warning "You do not have any threading library installed. If the linked"
+#warning "application doesn't provide the threading callbacks, you're screwed"
+#endif
-#ifdef HAVE_LIBGCRYPT
-#define HAVE_PTHREADS
-#ifdef HAVE_PTHREADS
+//#define HAVE_PTHREAD
+#ifdef HAVE_PTHREAD
#include <errno.h>
#include <pthread.h>
@@ -66,31 +69,83 @@ static int ssh_pthread_mutex_unlock (void **lock){
return pthread_mutex_unlock (*lock);
}
+static unsigned long ssh_pthread_thread_id (void){
+ return (unsigned long) pthread_self();
+}
-static struct ssh_threads_callbacks_struct ssh_gcrypt_user_callbacks=
+static struct ssh_threads_callbacks_struct ssh_pthread_user_callbacks=
{
.mutex_init=ssh_pthread_mutex_init,
.mutex_destroy=ssh_pthread_mutex_destroy,
.mutex_lock=ssh_pthread_mutex_lock,
- .mutex_unlock=ssh_pthread_mutex_unlock
+ .mutex_unlock=ssh_pthread_mutex_unlock,
+ .thread_id=ssh_pthread_thread_id
};
#endif
-static struct gcry_thread_cbs gcrypt_threads_callbacks;
-
-#endif
-
static struct ssh_threads_callbacks_struct *user_callbacks;
#ifdef HAVE_LIBGCRYPT
-static void copy_callback(struct ssh_threads_callbacks_struct *cb){
+
+/* Libgcrypt specific way of handling thread callbacks */
+
+static struct gcry_thread_cbs gcrypt_threads_callbacks;
+
+static int libgcrypt_thread_init(void){
+ if(user_callbacks == NULL)
+ return SSH_ERROR;
gcrypt_threads_callbacks.option= GCRY_THREAD_OPTION_VERSION << 8 || GCRY_THREAD_OPTION_USER;
- gcrypt_threads_callbacks.mutex_init=cb->mutex_init;
- gcrypt_threads_callbacks.mutex_destroy=cb->mutex_destroy;
- gcrypt_threads_callbacks.mutex_lock=cb->mutex_lock;
- gcrypt_threads_callbacks.mutex_unlock=cb->mutex_unlock;
+ gcrypt_threads_callbacks.mutex_init=user_callbacks->mutex_init;
+ gcrypt_threads_callbacks.mutex_destroy=user_callbacks->mutex_destroy;
+ gcrypt_threads_callbacks.mutex_lock=user_callbacks->mutex_lock;
+ gcrypt_threads_callbacks.mutex_unlock=user_callbacks->mutex_unlock;
+ gcry_control(GCRYCTL_SET_THREAD_CBS, &gcrypt_threads_callbacks);
+ return SSH_OK;
+}
+#else
+
+/* Libcrypto specific stuff */
+
+void **libcrypto_mutexes;
+
+static void libcrypto_lock_callback(int mode, int i, const char *file, int line){
+ (void)file;
+ (void)line;
+ if(mode & CRYPTO_LOCK){
+ user_callbacks->mutex_lock(&libcrypto_mutexes[i]);
+ } else {
+ user_callbacks->mutex_unlock(&libcrypto_mutexes[i]);
+ }
+}
+
+static int libcrypto_thread_init(){
+ int n=CRYPTO_num_locks();
+ int i;
+ libcrypto_mutexes=malloc(sizeof(void *) * n);
+ if (libcrypto_mutexes == NULL)
+ return SSH_ERROR;
+ for (i=0;i<n;++i){
+ user_callbacks->mutex_init(&libcrypto_mutexes[i]);
+ }
+ CRYPTO_set_id_callback(user_callbacks->thread_id);
+ CRYPTO_set_locking_callback(libcrypto_lock_callback);
+
+ return SSH_OK;
+}
+
+static void libcrypto_thread_finalize(){
+ int n=CRYPTO_num_locks();
+ int i;
+ if (libcrypto_mutexes==NULL)
+ return;
+ for (i=0;i<n;++i){
+ user_callbacks->mutex_destroy(&libcrypto_mutexes[i]);
+ }
+ SAFE_FREE(libcrypto_mutexes);
+
}
+
#endif
/** @internal
@@ -98,34 +153,38 @@ static void copy_callback(struct ssh_threads_callbacks_struct *cb){
*/
int ssh_threads_init(void){
-#ifdef HAVE_LIBGCRYPT
- if(user_callbacks != NULL){
- copy_callback(user_callbacks);
- gcry_control(GCRYCTL_SET_THREAD_CBS, &gcrypt_threads_callbacks);
- return SSH_OK;
- }
-#ifdef HAVE_PTHREADS
- else {
- copy_callback(&ssh_gcrypt_user_callbacks);
- gcry_control(GCRYCTL_SET_THREAD_CBS, &gcrypt_threads_callbacks);
- return SSH_OK;
- }
+ /* first initialize the user_callbacks with our default handlers if not
+ * already the case
+ */
+ if(user_callbacks == NULL){
+#ifdef HAVE_PTHREAD
+ user_callbacks=&ssh_pthread_user_callbacks;
+ } else {
#endif
-#else
-
+ return SSH_ERROR; // Can't do anything to initialize threading
+ }
+ /* Then initialize the crypto libraries threading callbacks */
+#ifdef HAVE_LIBGCRYPT
+ return libgcrypt_thread_init();
+#else /* Libcrypto */
+ return libcrypto_thread_init();
#endif
return SSH_ERROR;
}
+void ssh_threads_finalize(void){
+#ifdef HAVE_LIBGCRYPT
+#else
+ libcrypto_thread_finalize();
+#endif
+}
+
int ssh_init_set_threads_callbacks(struct ssh_threads_callbacks_struct *cb){
user_callbacks=cb;
return SSH_OK;
}
-int ssh_init_set_threads_pthreads(void){
- return SSH_OK;
-}
/**
* @}
*/
diff --git a/tests/unittests/torture_rand.c b/tests/unittests/torture_rand.c
index 087389c7..d5a1b5c5 100644
--- a/tests/unittests/torture_rand.c
+++ b/tests/unittests/torture_rand.c
@@ -3,7 +3,12 @@
#include <pthread.h>
#include "torture.h"
+#ifdef HAVE_LIBGCRYPT
#define NUM_LOOPS 1000
+#else
+/* openssl is much faster */
+#define NUM_LOOPS 20000
+#endif
#define NUM_THREADS 100
static void setup(){