Cross-platform and (truly) thread-safe OpenSSL initialization.
This commit is contained in:
parent
20c1358402
commit
ea700d80f5
@ -50,79 +50,69 @@ namespace tls {
|
|||||||
|
|
||||||
|
|
||||||
ref <vmime::utility::sync::criticalSection >* OpenSSLInitializer::sm_mutexes;
|
ref <vmime::utility::sync::criticalSection >* OpenSSLInitializer::sm_mutexes;
|
||||||
int OpenSSLInitializer::sm_initCount(0);
|
|
||||||
|
|
||||||
|
|
||||||
OpenSSLInitializer::OpenSSLInitializer()
|
OpenSSLInitializer::autoInitializer::autoInitializer()
|
||||||
|
{
|
||||||
|
// The construction of this unique 'oneTimeInitializer' object will be triggered
|
||||||
|
// by the 'autoInitializer' objects from the other translation units
|
||||||
|
static OpenSSLInitializer::oneTimeInitializer oneTimeInitializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
OpenSSLInitializer::autoInitializer::~autoInitializer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
OpenSSLInitializer::oneTimeInitializer::oneTimeInitializer()
|
||||||
{
|
{
|
||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
OpenSSLInitializer::~OpenSSLInitializer()
|
OpenSSLInitializer::oneTimeInitializer::~oneTimeInitializer()
|
||||||
{
|
{
|
||||||
uninitialize();
|
uninitialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// static
|
|
||||||
ref <vmime::utility::sync::criticalSection> OpenSSLInitializer::getMutex()
|
|
||||||
{
|
|
||||||
static ref <vmime::utility::sync::criticalSection> criticalSection
|
|
||||||
= vmime::platform::getHandler()->createCriticalSection();
|
|
||||||
|
|
||||||
return criticalSection;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
void OpenSSLInitializer::initialize()
|
void OpenSSLInitializer::initialize()
|
||||||
{
|
{
|
||||||
ref <vmime::utility::sync::criticalSection> mutex = getMutex();
|
|
||||||
vmime::utility::sync::autoLock <vmime::utility::sync::criticalSection> lock(mutex);
|
|
||||||
|
|
||||||
if (++sm_initCount == 1)
|
|
||||||
{
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x0907000L
|
#if OPENSSL_VERSION_NUMBER >= 0x0907000L
|
||||||
OPENSSL_config(NULL);
|
OPENSSL_config(NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SSL_load_error_strings();
|
SSL_load_error_strings();
|
||||||
SSL_library_init();
|
SSL_library_init();
|
||||||
OpenSSL_add_all_algorithms();
|
OpenSSL_add_all_algorithms();
|
||||||
|
|
||||||
unsigned char seed[SEEDSIZE];
|
unsigned char seed[SEEDSIZE];
|
||||||
vmime::platform::getHandler()->generateRandomBytes(seed, SEEDSIZE);
|
vmime::platform::getHandler()->generateRandomBytes(seed, SEEDSIZE);
|
||||||
RAND_seed(seed, SEEDSIZE);
|
RAND_seed(seed, SEEDSIZE);
|
||||||
|
|
||||||
int numMutexes = CRYPTO_num_locks();
|
int numMutexes = CRYPTO_num_locks();
|
||||||
sm_mutexes = new ref <vmime::utility::sync::criticalSection>[numMutexes];
|
sm_mutexes = new ref <vmime::utility::sync::criticalSection>[numMutexes];
|
||||||
|
|
||||||
for (int i = 0 ; i < numMutexes ; ++i)
|
for (int i = 0 ; i < numMutexes ; ++i)
|
||||||
sm_mutexes[i] = vmime::platform::getHandler()->createCriticalSection();
|
sm_mutexes[i] = vmime::platform::getHandler()->createCriticalSection();
|
||||||
|
|
||||||
CRYPTO_set_locking_callback(&OpenSSLInitializer::lock);
|
CRYPTO_set_locking_callback(&OpenSSLInitializer::lock);
|
||||||
CRYPTO_set_id_callback(&OpenSSLInitializer::id);
|
CRYPTO_set_id_callback(&OpenSSLInitializer::id);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
void OpenSSLInitializer::uninitialize()
|
void OpenSSLInitializer::uninitialize()
|
||||||
{
|
{
|
||||||
ref <vmime::utility::sync::criticalSection> mutex = getMutex();
|
EVP_cleanup();
|
||||||
vmime::utility::sync::autoLock <vmime::utility::sync::criticalSection> lock(mutex);
|
ERR_free_strings();
|
||||||
|
|
||||||
if (--sm_initCount == 0)
|
CRYPTO_set_locking_callback(NULL);
|
||||||
{
|
CRYPTO_set_id_callback(NULL);
|
||||||
EVP_cleanup();
|
|
||||||
ERR_free_strings();
|
|
||||||
|
|
||||||
CRYPTO_set_locking_callback(NULL);
|
delete [] sm_mutexes;
|
||||||
CRYPTO_set_id_callback(NULL);
|
|
||||||
|
|
||||||
delete [] sm_mutexes;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,6 +41,9 @@ namespace net {
|
|||||||
namespace tls {
|
namespace tls {
|
||||||
|
|
||||||
|
|
||||||
|
static OpenSSLInitializer::autoInitializer openSSLInitializer;
|
||||||
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
ref <TLSSession> TLSSession::create(ref <security::cert::certificateVerifier> cv)
|
ref <TLSSession> TLSSession::create(ref <security::cert::certificateVerifier> cv)
|
||||||
{
|
{
|
||||||
@ -51,9 +54,6 @@ ref <TLSSession> TLSSession::create(ref <security::cert::certificateVerifier> cv
|
|||||||
TLSSession_OpenSSL::TLSSession_OpenSSL(ref <vmime::security::cert::certificateVerifier> cv)
|
TLSSession_OpenSSL::TLSSession_OpenSSL(ref <vmime::security::cert::certificateVerifier> cv)
|
||||||
: m_sslctx(0), m_certVerifier(cv)
|
: m_sslctx(0), m_certVerifier(cv)
|
||||||
{
|
{
|
||||||
// Thread-safe OpenSSL initialization
|
|
||||||
static OpenSSLInitializer openSSLInitialization;
|
|
||||||
|
|
||||||
m_sslctx = SSL_CTX_new(SSLv23_client_method());
|
m_sslctx = SSL_CTX_new(SSLv23_client_method());
|
||||||
SSL_CTX_set_options(m_sslctx, SSL_OP_ALL | SSL_OP_NO_SSLv2);
|
SSL_CTX_set_options(m_sslctx, SSL_OP_ALL | SSL_OP_NO_SSLv2);
|
||||||
SSL_CTX_set_mode(m_sslctx, SSL_MODE_AUTO_RETRY);
|
SSL_CTX_set_mode(m_sslctx, SSL_MODE_AUTO_RETRY);
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
|
|
||||||
#include "vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp"
|
#include "vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp"
|
||||||
#include "vmime/net/tls/openssl/TLSSession_OpenSSL.hpp"
|
#include "vmime/net/tls/openssl/TLSSession_OpenSSL.hpp"
|
||||||
|
#include "vmime/net/tls/openssl/OpenSSLInitializer.hpp"
|
||||||
|
|
||||||
#include "vmime/platform.hpp"
|
#include "vmime/platform.hpp"
|
||||||
|
|
||||||
@ -45,6 +46,9 @@ namespace net {
|
|||||||
namespace tls {
|
namespace tls {
|
||||||
|
|
||||||
|
|
||||||
|
static OpenSSLInitializer::autoInitializer openSSLInitializer;
|
||||||
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
BIO_METHOD TLSSocket_OpenSSL::sm_customBIOMethod =
|
BIO_METHOD TLSSocket_OpenSSL::sm_customBIOMethod =
|
||||||
{
|
{
|
||||||
|
@ -59,6 +59,9 @@ namespace security {
|
|||||||
namespace cert {
|
namespace cert {
|
||||||
|
|
||||||
|
|
||||||
|
static net::tls::OpenSSLInitializer::autoInitializer openSSLInitializer;
|
||||||
|
|
||||||
|
|
||||||
#ifndef VMIME_BUILDING_DOC
|
#ifndef VMIME_BUILDING_DOC
|
||||||
|
|
||||||
class monthMap
|
class monthMap
|
||||||
@ -107,9 +110,6 @@ struct OpenSSLX509CertificateInternalData
|
|||||||
{
|
{
|
||||||
OpenSSLX509CertificateInternalData()
|
OpenSSLX509CertificateInternalData()
|
||||||
{
|
{
|
||||||
// Thread-safe OpenSSL initialization
|
|
||||||
static net::tls::OpenSSLInitializer openSSLInitialization;
|
|
||||||
|
|
||||||
cert = 0;
|
cert = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,19 +48,29 @@ namespace tls {
|
|||||||
*/
|
*/
|
||||||
class OpenSSLInitializer
|
class OpenSSLInitializer
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/** Automatically initialize OpenSSL
|
/** Automatically initialize OpenSSL
|
||||||
*/
|
*/
|
||||||
OpenSSLInitializer();
|
class autoInitializer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
/** Automatically uninitialize OpenSSL
|
autoInitializer();
|
||||||
*/
|
~autoInitializer();
|
||||||
~OpenSSLInitializer();
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
class oneTimeInitializer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
oneTimeInitializer();
|
||||||
|
~oneTimeInitializer();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/** Initializes the OpenSSL lib
|
/** Initializes the OpenSSL lib
|
||||||
*/
|
*/
|
||||||
static void initialize();
|
static void initialize();
|
||||||
@ -85,7 +95,6 @@ protected:
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
static ref <vmime::utility::sync::criticalSection >* sm_mutexes;
|
static ref <vmime::utility::sync::criticalSection >* sm_mutexes;
|
||||||
static int sm_initCount;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user