Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mumble-voip/mumble.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMikkel Krautz <mikkel@krautz.dk>2017-07-16 11:48:44 +0300
committerMikkel Krautz <mikkel@krautz.dk>2017-07-17 11:19:13 +0300
commit72e0a78272d37e473f0b34d244e19bb7821393c2 (patch)
tree071f819ba4ad83298be9a12d3a4df914a516b94f /src
parentf041bdbde15fd3144f49ab63067a47480b335b09 (diff)
SSL: register OpenSSL threading callbacks when we can't access Qt's OpenSSL.
We neglected to register our own callbacks for locking and thread IDs when we removed the restriction that we only allow one copy of OpenSSL in the address space. (f544524d4c3289bf3341d685277de0e6a6895469) This commit remedies that by providing our own set of callbacks for locking and getting thread IDs to OpenSSL. Previously, we just expected that Qt would properly initialize OpenSSL. However, when Qt and us use separate copies of OpenSSL -- we have to do it ourselves.
Diffstat (limited to 'src')
-rw-r--r--src/SSL.cpp23
-rw-r--r--src/SSLLocks.cpp85
-rw-r--r--src/SSLLocks.h15
-rw-r--r--src/mumble.pri4
4 files changed, 122 insertions, 5 deletions
diff --git a/src/SSL.cpp b/src/SSL.cpp
index aea72190b..9c372569e 100644
--- a/src/SSL.cpp
+++ b/src/SSL.cpp
@@ -6,20 +6,37 @@
#include "murmur_pch.h"
#include "SSL.h"
+#include "SSLLocks.h"
#include "Version.h"
void MumbleSSL::initialize() {
+ // Let Qt initialize its copy of OpenSSL, if it's different than
+ // Mumble's. (Initialization is a side-effect of calling
+ // QSslSocket::supportsSsl()).
+ QSslSocket::supportsSsl();
+
// Initialize our copy of OpenSSL.
SSL_library_init(); // Safe to discard return value, per OpenSSL man pages.
SSL_load_error_strings();
- // Let Qt initialize its copy of OpenSSL, if it's different than
- // Mumble's.
- QSslSocket::supportsSsl();
+ // Determine if a locking callback has not been set.
+ // This should be the case if there are multiple copies
+ // of OpensSSL in the address space. This is mostly due
+ // to Qt dynamically loading OpenSSL when it is not
+ // configured with -openssl-linked.
+ //
+ // If we detect that no locking callback is configured, we
+ // have to set it up ourselves to allow multi-threaded use
+ // of OpenSSL.
+ void *lockcb = reinterpret_cast<void *>(CRYPTO_get_locking_callback());
+ if (lockcb == NULL) {
+ SSLLocks::initialize();
+ }
}
void MumbleSSL::destroy() {
+ SSLLocks::destroy();
}
QString MumbleSSL::defaultOpenSSLCipherString() {
diff --git a/src/SSLLocks.cpp b/src/SSLLocks.cpp
new file mode 100644
index 000000000..8d0dc512e
--- /dev/null
+++ b/src/SSLLocks.cpp
@@ -0,0 +1,85 @@
+// Copyright 2005-2017 The Mumble Developers. All rights reserved.
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file at the root of the
+// Mumble source tree or at <https://www.mumble.info/LICENSE>.
+
+#include "murmur_pch.h"
+
+#include "SSLLocks.h"
+
+static QMutex **locks = NULL;
+
+void locking_callback(int mode, int type, const char *, int) {
+ if (mode & CRYPTO_LOCK) {
+ locks[type]->lock();
+ } else {
+ locks[type]->unlock();
+ }
+}
+
+unsigned long id_callback() {
+ // OpenSSL's thread ID callback must return an unsigned long.
+ // It's therefore important that we make sure the value from
+ // Qt's QThread::currentThreadId actually makes sense to return
+ // in this case.
+ //
+ // On Windows, the return type is a DWORD. This is excellent,
+ // because on an LLP64 like 64-bit Windows, unsigned long is
+ // only 32-bits wide, just like DWORD.
+ //
+ // On macOS and embedded Linux, it's void *. And when Qt targets
+ // X11, it's unsigned long.
+ //
+ // So, in all cases, it's safe to use unsigned long.
+ //
+ // The trouble is, since the return type of QThread::currentThreadId()
+ // difers between platforms, we have to be clever about how we convert
+ // that type to an unsigned long. The way we do it here is to first convert
+ // it to an uintptr_t, since both pointer types and integer types will
+ // convert to that without the compiler complaining. Then, we convert
+ // *that* to an unsigned long. (Note that for LLP64 platforms, such as
+ // 64-bit Windows, this conversion is from a 64-bit type to a 32-bit type)
+ uintptr_t val = reinterpret_cast<uintptr_t>(QThread::currentThreadId());
+ return static_cast<unsigned long>(val);
+}
+
+void SSLLocks::initialize() {
+ int nlocks = CRYPTO_num_locks();
+
+ locks = reinterpret_cast<QMutex **>(calloc(nlocks, sizeof(QMutex *)));
+ if (locks == NULL) {
+ qFatal("SSLLocks: unable to allocate locks array");
+
+ // This initializer is called early during program
+ // execution, and the message handler that causes
+ // qFatal to terminate execution might not be registered
+ // yet. So, do exit(1) just in case.
+ exit(1);
+ }
+
+ for (int i = 0; i < nlocks; i++) {
+ locks[i] = new QMutex;
+ }
+
+ CRYPTO_set_locking_callback(locking_callback);
+ CRYPTO_set_id_callback(id_callback);
+}
+
+void SSLLocks::destroy() {
+ // If SSLLocks was never initialized, or has been destroyed already,
+ // don't try to do it again.
+ if (locks == NULL) {
+ return;
+ }
+
+ CRYPTO_set_locking_callback(NULL);
+ CRYPTO_set_id_callback(NULL);
+
+ int nlocks = CRYPTO_num_locks();
+ for (int i = 0; i < nlocks; i++) {
+ delete locks[i];
+ }
+
+ free(locks);
+ locks = NULL;
+}
diff --git a/src/SSLLocks.h b/src/SSLLocks.h
new file mode 100644
index 000000000..78bf2172d
--- /dev/null
+++ b/src/SSLLocks.h
@@ -0,0 +1,15 @@
+// Copyright 2005-2017 The Mumble Developers. All rights reserved.
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file at the root of the
+// Mumble source tree or at <https://www.mumble.info/LICENSE>.
+
+#ifndef MUMBLE_SSLLOCKS_H_
+#define MUMBLE_SSLLOCKS_H_
+
+class SSLLocks {
+ public:
+ static void initialize();
+ static void destroy();
+};
+
+#endif
diff --git a/src/mumble.pri b/src/mumble.pri
index 4ee2f9a3a..4ce5169f9 100644
--- a/src/mumble.pri
+++ b/src/mumble.pri
@@ -14,8 +14,8 @@ CONFIG += qt thread debug_and_release warn_on
DEFINES *= MUMBLE_VERSION_STRING=$$VERSION
INCLUDEPATH += $$PWD . ../mumble_proto
VPATH += $$PWD
-HEADERS *= ACL.h Channel.h CryptState.h Connection.h Group.h HTMLFilter.h User.h Net.h OSInfo.h Timer.h SSL.h Version.h SSLCipherInfo.h SSLCipherInfoTable.h licenses.h License.h LogEmitter.h CryptographicHash.h CryptographicRandom.h PasswordGenerator.h ByteSwap.h HostAddress.cpp Ban.h EnvUtils.h UnresolvedServerAddress.h ServerAddress.h ServerResolver.h ServerResolverRecord.h SelfSignedCertificate.h
-SOURCES *= ACL.cpp Group.cpp Channel.cpp Connection.cpp HTMLFilter.cpp User.cpp Timer.cpp CryptState.cpp OSInfo.cpp SSL.cpp Version.cpp SSLCipherInfo.cpp License.cpp LogEmitter.cpp CryptographicHash.cpp CryptographicRandom.cpp PasswordGenerator.cpp HostAddress.cpp Ban.cpp EnvUtils.cpp UnresolvedServerAddress.cpp ServerAddress.cpp ServerResolver_qt5.cpp ServerResolverRecord.cpp SelfSignedCertificate.cpp
+HEADERS *= ACL.h Channel.h CryptState.h Connection.h Group.h HTMLFilter.h User.h Net.h OSInfo.h Timer.h SSL.h Version.h SSLCipherInfo.h SSLCipherInfoTable.h licenses.h License.h LogEmitter.h CryptographicHash.h CryptographicRandom.h PasswordGenerator.h ByteSwap.h HostAddress.cpp Ban.h EnvUtils.h UnresolvedServerAddress.h ServerAddress.h ServerResolver.h ServerResolverRecord.h SelfSignedCertificate.h SSLLocks.h
+SOURCES *= ACL.cpp Group.cpp Channel.cpp Connection.cpp HTMLFilter.cpp User.cpp Timer.cpp CryptState.cpp OSInfo.cpp SSL.cpp Version.cpp SSLCipherInfo.cpp License.cpp LogEmitter.cpp CryptographicHash.cpp CryptographicRandom.cpp PasswordGenerator.cpp HostAddress.cpp Ban.cpp EnvUtils.cpp UnresolvedServerAddress.cpp ServerAddress.cpp ServerResolver_qt5.cpp ServerResolverRecord.cpp SelfSignedCertificate.cpp SSLLocks.cpp
LIBS *= -lmumble_proto
equals(QT_MAJOR_VERSION, 4) {