Added dynamic locking function for the OpenSSL library.

This is needed when using OpenSSL from multiple threads.

git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@5168 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
thunder2 2012-05-15 13:51:24 +00:00
parent 39c3d013f5
commit 14c1f9f599

View File

@ -57,6 +57,144 @@
// initialisation du pointeur de singleton // initialisation du pointeur de singleton
static AuthSSL *instance_ssl = NULL; static AuthSSL *instance_ssl = NULL;
static pthread_mutex_t *mutex_buf = NULL;
struct CRYPTO_dynlock_value
{
pthread_mutex_t mutex;
};
/**
* OpenSSL locking function.
*
* @param mode lock mode
* @param n lock number
* @param file source file name
* @param line source file line number
* @return none
*/
static void locking_function(int mode, int n, const char */*file*/, int /*line*/)
{
if (mode & CRYPTO_LOCK) {
pthread_mutex_lock(&mutex_buf[n]);
} else {
pthread_mutex_unlock(&mutex_buf[n]);
}
}
/**
* OpenSSL uniq id function.
*
* @return thread id
*/
static unsigned long id_function(void)
{
#ifdef WINDOWS_SYS
return (unsigned long) pthread_self().p;
#else
return (unsigned long) pthread_self();
#endif
}
/**
* OpenSSL allocate and initialize dynamic crypto lock.
*
* @param file source file name
* @param line source file line number
*/
static struct CRYPTO_dynlock_value *dyn_create_function(const char */*file*/, int /*line*/)
{
struct CRYPTO_dynlock_value *value;
value = (struct CRYPTO_dynlock_value*) malloc(sizeof(struct CRYPTO_dynlock_value));
if (!value) {
return NULL;
}
pthread_mutex_init(&value->mutex, NULL);
return value;
}
/**
* OpenSSL dynamic locking function.
*
* @param mode lock mode
* @param l lock structure pointer
* @param file source file name
* @param line source file line number
* @return none
*/
static void dyn_lock_function(int mode, struct CRYPTO_dynlock_value *l, const char */*file*/, int /*line*/)
{
if (mode & CRYPTO_LOCK) {
pthread_mutex_lock(&l->mutex);
} else {
pthread_mutex_unlock(&l->mutex);
}
}
/**
* OpenSSL destroy dynamic crypto lock.
*
* @param l lock structure pointer
* @param file source file name
* @param line source file line number
* @return none
*/
static void dyn_destroy_function(struct CRYPTO_dynlock_value *l, const char */*file*/, int /*line*/)
{
pthread_mutex_destroy(&l->mutex);
free(l);
}
/**
* Initialize TLS library.
*
* @return true on success, false on error
*/
bool tls_init()
{
/* static locks area */
mutex_buf = (pthread_mutex_t*) malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
if (mutex_buf == NULL) {
return false;
}
for (int i = 0; i < CRYPTO_num_locks(); i++) {
pthread_mutex_init(&mutex_buf[i], NULL);
}
/* static locks callbacks */
CRYPTO_set_locking_callback(locking_function);
CRYPTO_set_id_callback(id_function);
/* dynamic locks callbacks */
CRYPTO_set_dynlock_create_callback(dyn_create_function);
CRYPTO_set_dynlock_lock_callback(dyn_lock_function);
CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function);
return true;
}
/**
* Cleanup TLS library.
*
* @return 0
*/
void tls_cleanup()
{
CRYPTO_set_dynlock_create_callback(NULL);
CRYPTO_set_dynlock_lock_callback(NULL);
CRYPTO_set_dynlock_destroy_callback(NULL);
CRYPTO_set_locking_callback(NULL);
CRYPTO_set_id_callback(NULL);
if (mutex_buf == NULL) {
for (int i = 0; i < CRYPTO_num_locks(); i++) {
pthread_mutex_destroy(&mutex_buf[i]);
}
free(mutex_buf);
mutex_buf = NULL;
}
}
/* hidden function - for testing purposes() */ /* hidden function - for testing purposes() */
void setAuthSSL(AuthSSL *newssl) void setAuthSSL(AuthSSL *newssl)
@ -148,6 +286,11 @@ static int initLib = 0;
if (!initLib) if (!initLib)
{ {
initLib = 1; initLib = 1;
if (!tls_init()) {
return 0;
}
SSL_load_error_strings(); SSL_load_error_strings();
SSL_library_init(); SSL_library_init();
} }
@ -287,6 +430,8 @@ bool AuthSSLimpl::validateOwnCertificate(X509 *x509, EVP_PKEY *pkey)
bool AuthSSLimpl::CloseAuth() bool AuthSSLimpl::CloseAuth()
{ {
tls_cleanup();
#ifdef AUTHSSL_DEBUG #ifdef AUTHSSL_DEBUG
std::cerr << "AuthSSLimpl::CloseAuth()"; std::cerr << "AuthSSLimpl::CloseAuth()";
std::cerr << std::endl; std::cerr << std::endl;