From f2187e31de13a6ab8631a9067487dab555f7c2e7 Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Tue, 6 Jul 2010 11:06:40 +0200 Subject: SSL backend: load libraries for certificates only once Reviewed-by: Olivier Goffart --- src/network/ssl/qsslsocket.cpp | 6 ++--- src/network/ssl/qsslsocket_openssl.cpp | 42 ++++++++++++++++++---------------- src/network/ssl/qsslsocket_p.h | 11 ++++----- 3 files changed, 30 insertions(+), 29 deletions(-) diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index f85fa84..809e8aa 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -1849,7 +1849,7 @@ QList QSslSocketPrivate::defaultCiphers() */ QList QSslSocketPrivate::supportedCiphers() { - QSslSocketPrivate::ensureInitialized(); + QSslSocketPrivate::ensureCertsAndCiphersLoaded(); QMutexLocker locker(&globalData()->mutex); return globalData()->supportedCiphers; } @@ -1879,7 +1879,7 @@ void QSslSocketPrivate::setDefaultSupportedCiphers(const QList &ciph */ QList QSslSocketPrivate::defaultCaCertificates() { - QSslSocketPrivate::ensureInitialized(); + QSslSocketPrivate::ensureCertsAndCiphersLoaded(); QMutexLocker locker(&globalData()->mutex); return globalData()->config->caCertificates; } @@ -1962,7 +1962,7 @@ void QSslConfigurationPrivate::setDefaultConfiguration(const QSslConfiguration & */ void QSslConfigurationPrivate::deepCopyDefaultConfiguration(QSslConfigurationPrivate *ptr) { - QSslSocketPrivate::ensureInitialized(); + QSslSocketPrivate::ensureCertsAndCiphersLoaded(); QMutexLocker locker(&globalData()->mutex); const QSslConfigurationPrivate *global = globalData()->config.constData(); diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index d7088ee..b602b29 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -74,8 +74,9 @@ QT_BEGIN_NAMESPACE -bool QSslSocketPrivate::s_libraryLoaded = false; -bool QSslSocketPrivate::s_loadedCiphersAndCerts = false; +bool QSslSocketPrivate::s_initialized = false; +QBasicAtomicInt QSslSocketPrivate::s_CertsAndCiphersLoaded; +Q_GLOBAL_STATIC(QMutex, s_CertsAndCiphersLoadedMutex); // Useful defines #define SSL_ERRORSTR() QString::fromLocal8Bit(q_ERR_error_string(q_ERR_get_error(), NULL)) @@ -170,7 +171,7 @@ QSslSocketBackendPrivate::QSslSocketBackendPrivate() session(0) { // Calls SSL_library_init(). - ensureInitialized(); + ensureCertsAndCiphersLoaded(); } QSslSocketBackendPrivate::~QSslSocketBackendPrivate() @@ -421,18 +422,18 @@ void QSslSocketPrivate::deinitialize() bool QSslSocketPrivate::supportsSsl() { - return ensureLibraryLoaded(); + return ensureInitialized(); } -bool QSslSocketPrivate::ensureLibraryLoaded() +bool QSslSocketPrivate::ensureInitialized() { if (!q_resolveOpenSslSymbols()) return false; // Check if the library itself needs to be initialized. QMutexLocker locker(openssl_locks()->initLock()); - if (!s_libraryLoaded) { - s_libraryLoaded = true; + if (!s_initialized) { + s_initialized = true; // Initialize OpenSSL. q_CRYPTO_set_id_callback(id_function); @@ -473,16 +474,6 @@ bool QSslSocketPrivate::ensureLibraryLoaded() return true; } -void QSslSocketPrivate::ensureCiphersAndCertsLoaded() -{ - if (s_loadedCiphersAndCerts) - return; - s_loadedCiphersAndCerts = true; - - resetDefaultCiphers(); - setDefaultCaCertificates(systemCaCertificates()); -} - /*! \internal @@ -490,13 +481,18 @@ void QSslSocketPrivate::ensureCiphersAndCertsLoaded() been initialized. */ -void QSslSocketPrivate::ensureInitialized() +void QSslSocketPrivate::ensureCertsAndCiphersLoaded() { - if (!supportsSsl()) + // use double-checked locking to speed up this function + if (s_CertsAndCiphersLoaded) return; - ensureCiphersAndCertsLoaded(); + QMutexLocker locker(s_CertsAndCiphersLoadedMutex()); + if (s_CertsAndCiphersLoaded) + return; + if (!supportsSsl()) + return; //load symbols needed to receive certificates from system store #if defined(Q_OS_MAC) QLibrary securityLib("/System/Library/Frameworks/Security.framework/Versions/Current/Security"); @@ -532,6 +528,12 @@ void QSslSocketPrivate::ensureInitialized() qWarning("could not load crypt32 library"); // should never happen } #endif + resetDefaultCiphers(); + setDefaultCaCertificates(systemCaCertificates()); + // we need to make sure that s_CertsAndCiphersLoaded is executed after the library loading above + // (the compiler/processor might reorder instructions otherwise) + if (!s_CertsAndCiphersLoaded.testAndSetRelease(0, 1)) + Q_ASSERT_X(false, "certificate store", "certificate store has already been initialized!"); } /*! diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h index 72b3ef7..b474175 100644 --- a/src/network/ssl/qsslsocket_p.h +++ b/src/network/ssl/qsslsocket_p.h @@ -63,6 +63,7 @@ #include #include +#include QT_BEGIN_NAMESPACE @@ -113,7 +114,8 @@ public: QString verificationPeerName; static bool supportsSsl(); - static void ensureInitialized(); + static bool ensureInitialized(); + static void ensureCertsAndCiphersLoaded(); static void deinitialize(); static QList defaultCiphers(); static QList supportedCiphers(); @@ -161,11 +163,8 @@ public: virtual QSslCipher sessionCipher() const = 0; private: - static bool ensureLibraryLoaded(); - static void ensureCiphersAndCertsLoaded(); - - static bool s_libraryLoaded; - static bool s_loadedCiphersAndCerts; + static bool s_initialized; + static QBasicAtomicInt s_CertsAndCiphersLoaded; }; QT_END_NAMESPACE -- cgit v0.12