diff options
Diffstat (limited to 'src/network/ssl/qsslsocket_opensslpre11.cpp')
-rw-r--r-- | src/network/ssl/qsslsocket_opensslpre11.cpp | 408 |
1 files changed, 0 insertions, 408 deletions
diff --git a/src/network/ssl/qsslsocket_opensslpre11.cpp b/src/network/ssl/qsslsocket_opensslpre11.cpp deleted file mode 100644 index 2af437f0fa..0000000000 --- a/src/network/ssl/qsslsocket_opensslpre11.cpp +++ /dev/null @@ -1,408 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Copyright (C) 2014 Governikus GmbH & Co. KG -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/**************************************************************************** -** -** In addition, as a special exception, the copyright holders listed above give -** permission to link the code of its release of Qt with the OpenSSL project's -** "OpenSSL" library (or modified versions of the "OpenSSL" library that use the -** same license as the original version), and distribute the linked executables. -** -** You must comply with the GNU General Public License version 2 in all -** respects for all of the code used other than the "OpenSSL" code. If you -** modify this file, you may extend this exception to your version of the file, -** but you are not obligated to do so. If you do not wish to do so, delete -** this exception statement from your version of this file. -** -****************************************************************************/ - -//#define QT_DECRYPT_SSL_TRAFFIC - -#include "qssl_p.h" -#include "qsslsocket_openssl_p.h" -#include "qsslsocket_openssl_symbols_p.h" -#include "qsslsocket.h" -#include "qsslkey.h" - -#include <QtCore/qdebug.h> -#include <QtCore/qdir.h> -#include <QtCore/qdiriterator.h> -#include <QtCore/qthread.h> -#include <QtCore/qfile.h> -#include <QtCore/qmutex.h> - -QT_BEGIN_NAMESPACE - -/* \internal - - From OpenSSL's thread(3) manual page: - - OpenSSL can safely be used in multi-threaded applications provided that at - least two callback functions are set. - - locking_function(int mode, int n, const char *file, int line) is needed to - perform locking on shared data structures. (Note that OpenSSL uses a - number of global data structures that will be implicitly shared - whenever multiple threads use OpenSSL.) Multi-threaded - applications will crash at random if it is not set. ... - ... - id_function(void) is a function that returns a thread ID. It is not - needed on Windows nor on platforms where getpid() returns a different - ID for each thread (most notably Linux) -*/ - -class QOpenSslLocks -{ -public: - QOpenSslLocks() - : initLocker(QMutex::Recursive), - locksLocker(QMutex::Recursive) - { - QMutexLocker locker(&locksLocker); - int numLocks = q_CRYPTO_num_locks(); - locks = new QMutex *[numLocks]; - memset(locks, 0, numLocks * sizeof(QMutex *)); - } - ~QOpenSslLocks() - { - QMutexLocker locker(&locksLocker); - for (int i = 0; i < q_CRYPTO_num_locks(); ++i) - delete locks[i]; - delete [] locks; - - QSslSocketPrivate::deinitialize(); - } - QMutex *lock(int num) - { - QMutexLocker locker(&locksLocker); - QMutex *tmp = locks[num]; - if (!tmp) - tmp = locks[num] = new QMutex(QMutex::Recursive); - return tmp; - } - - QMutex *globalLock() - { - return &locksLocker; - } - - QMutex *initLock() - { - return &initLocker; - } - -private: - QMutex initLocker; - QMutex locksLocker; - QMutex **locks; -}; - -Q_GLOBAL_STATIC(QOpenSslLocks, openssl_locks) - -extern "C" { -static void locking_function(int mode, int lockNumber, const char *, int) -{ - QMutex *mutex = openssl_locks()->lock(lockNumber); - - // Lock or unlock it - if (mode & CRYPTO_LOCK) - mutex->lock(); - else - mutex->unlock(); -} -static unsigned long id_function() -{ - return (quintptr)QThread::currentThreadId(); -} - -} // extern "C" - -static void q_OpenSSL_add_all_algorithms_safe() -{ -#ifdef Q_OS_WIN - // Prior to version 1.0.1m an attempt to call OpenSSL_add_all_algorithms on - // Windows could result in 'exit' call from OPENSSL_config (QTBUG-43843). - // We can predict this and avoid OPENSSL_add_all_algorithms call. - // From OpenSSL docs: - // "An application does not need to add algorithms to use them explicitly, - // for example by EVP_sha1(). It just needs to add them if it (or any of - // the functions it calls) needs to lookup algorithms. - // The cipher and digest lookup functions are used in many parts of the - // library. If the table is not initialized several functions will - // misbehave and complain they cannot find algorithms. This includes the - // PEM, PKCS#12, SSL and S/MIME libraries. This is a common query in - // the OpenSSL mailing lists." - // - // Anyway, as a result, we chose not to call this function if it would exit. - - if (q_SSLeay() < 0x100010DFL) - { - // Now, before we try to call it, check if an attempt to open config file - // will result in exit: - if (char *confFileName = q_CONF_get1_default_config_file()) { - BIO *confFile = q_BIO_new_file(confFileName, "r"); - const auto lastError = q_ERR_peek_last_error(); - q_CRYPTO_free(confFileName); - if (confFile) { - q_BIO_free(confFile); - } else { - q_ERR_clear_error(); - if (ERR_GET_REASON(lastError) == ERR_R_SYS_LIB) { - qCWarning(lcSsl, "failed to open openssl.conf file"); - return; - } - } - } - } -#endif // Q_OS_WIN - - q_OpenSSL_add_all_algorithms(); -} - - -void QSslSocketPrivate::deinitialize() -{ - q_CRYPTO_set_id_callback(0); - q_CRYPTO_set_locking_callback(0); - q_ERR_free_strings(); -} - - -bool QSslSocketPrivate::ensureLibraryLoaded() -{ - if (!q_resolveOpenSslSymbols()) - return false; - - // Check if the library itself needs to be initialized. - QMutexLocker locker(openssl_locks()->initLock()); - - if (!s_libraryLoaded) { - // Initialize OpenSSL. - q_CRYPTO_set_id_callback(id_function); - q_CRYPTO_set_locking_callback(locking_function); - if (q_SSL_library_init() != 1) - return false; - q_SSL_load_error_strings(); - q_OpenSSL_add_all_algorithms_safe(); - -#if OPENSSL_VERSION_NUMBER >= 0x10001000L - if (q_SSLeay() >= 0x10001000L) - QSslSocketBackendPrivate::s_indexForSSLExtraData = q_SSL_get_ex_new_index(0L, NULL, NULL, NULL, NULL); -#endif - - // Initialize OpenSSL's random seed. - if (!q_RAND_status()) { - qWarning("Random number generator not seeded, disabling SSL support"); - return false; - } - - s_libraryLoaded = true; - } - return true; -} - -void QSslSocketPrivate::ensureCiphersAndCertsLoaded() -{ - QMutexLocker locker(openssl_locks()->initLock()); - if (s_loadedCiphersAndCerts) - return; - s_loadedCiphersAndCerts = true; - - resetDefaultCiphers(); - resetDefaultEllipticCurves(); - -#if QT_CONFIG(library) - //load symbols needed to receive certificates from system store -#if defined(Q_OS_QNX) - s_loadRootCertsOnDemand = true; -#elif defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) - // check whether we can enable on-demand root-cert loading (i.e. check whether the sym links are there) - QList<QByteArray> dirs = unixRootCertDirectories(); - QStringList symLinkFilter; - symLinkFilter << QLatin1String("[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f].[0-9]"); - for (int a = 0; a < dirs.count(); ++a) { - QDirIterator iterator(QLatin1String(dirs.at(a)), symLinkFilter, QDir::Files); - if (iterator.hasNext()) { - s_loadRootCertsOnDemand = true; - break; - } - } -#endif -#endif // QT_CONFIG(library) - // if on-demand loading was not enabled, load the certs now - if (!s_loadRootCertsOnDemand) - setDefaultCaCertificates(systemCaCertificates()); -#ifdef Q_OS_WIN - //Enabled for fetching additional root certs from windows update on windows 6+ - //This flag is set false by setDefaultCaCertificates() indicating the app uses - //its own cert bundle rather than the system one. - //Same logic that disables the unix on demand cert loading. - //Unlike unix, we do preload the certificates from the cert store. - s_loadRootCertsOnDemand = true; -#endif -} - -long QSslSocketPrivate::sslLibraryVersionNumber() -{ - if (!supportsSsl()) - return 0; - - return q_SSLeay(); -} - -QString QSslSocketPrivate::sslLibraryVersionString() -{ - if (!supportsSsl()) - return QString(); - - const char *versionString = q_SSLeay_version(SSLEAY_VERSION); - if (!versionString) - return QString(); - - return QString::fromLatin1(versionString); -} - -void QSslSocketBackendPrivate::continueHandshake() -{ - Q_Q(QSslSocket); - // if we have a max read buffer size, reset the plain socket's to match - if (readBufferMaxSize) - plainSocket->setReadBufferSize(readBufferMaxSize); - - if (q_SSL_ctrl((ssl), SSL_CTRL_GET_SESSION_REUSED, 0, NULL)) - configuration.peerSessionShared = true; - -#ifdef QT_DECRYPT_SSL_TRAFFIC - if (ssl->session && ssl->s3) { - const char *mk = reinterpret_cast<const char *>(ssl->session->master_key); - QByteArray masterKey(mk, ssl->session->master_key_length); - const char *random = reinterpret_cast<const char *>(ssl->s3->client_random); - QByteArray clientRandom(random, SSL3_RANDOM_SIZE); - - // different format, needed for e.g. older Wireshark versions: -// const char *sid = reinterpret_cast<const char *>(ssl->session->session_id); -// QByteArray sessionID(sid, ssl->session->session_id_length); -// QByteArray debugLineRSA("RSA Session-ID:"); -// debugLineRSA.append(sessionID.toHex().toUpper()); -// debugLineRSA.append(" Master-Key:"); -// debugLineRSA.append(masterKey.toHex().toUpper()); -// debugLineRSA.append("\n"); - - QByteArray debugLineClientRandom("CLIENT_RANDOM "); - debugLineClientRandom.append(clientRandom.toHex().toUpper()); - debugLineClientRandom.append(" "); - debugLineClientRandom.append(masterKey.toHex().toUpper()); - debugLineClientRandom.append("\n"); - - QString sslKeyFile = QDir::tempPath() + QLatin1String("/qt-ssl-keys"); - QFile file(sslKeyFile); - if (!file.open(QIODevice::Append)) - qCWarning(lcSsl) << "could not open file" << sslKeyFile << "for appending"; - if (!file.write(debugLineClientRandom)) - qCWarning(lcSsl) << "could not write to file" << sslKeyFile; - file.close(); - } else { - qCWarning(lcSsl, "could not decrypt SSL traffic"); - } -#endif - - // Cache this SSL session inside the QSslContext - if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionSharing)) { - if (!sslContextPointer->cacheSession(ssl)) { - sslContextPointer.clear(); // we could not cache the session - } else { - // Cache the session for permanent usage as well - if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionPersistence)) { - if (!sslContextPointer->sessionASN1().isEmpty()) - configuration.sslSession = sslContextPointer->sessionASN1(); - configuration.sslSessionTicketLifeTimeHint = sslContextPointer->sessionTicketLifeTimeHint(); - } - } - } - -#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG) - - configuration.nextProtocolNegotiationStatus = sslContextPointer->npnContext().status; - if (sslContextPointer->npnContext().status == QSslConfiguration::NextProtocolNegotiationUnsupported) { - // we could not agree -> be conservative and use HTTP/1.1 - configuration.nextNegotiatedProtocol = QByteArrayLiteral("http/1.1"); - } else { - const unsigned char *proto = 0; - unsigned int proto_len = 0; -#if OPENSSL_VERSION_NUMBER >= 0x10002000L - if (q_SSLeay() >= 0x10002000L) { - q_SSL_get0_alpn_selected(ssl, &proto, &proto_len); - if (proto_len && mode == QSslSocket::SslClientMode) { - // Client does not have a callback that sets it ... - configuration.nextProtocolNegotiationStatus = QSslConfiguration::NextProtocolNegotiationNegotiated; - } - } - - if (!proto_len) { // Test if NPN was more lucky ... -#else - { -#endif - q_SSL_get0_next_proto_negotiated(ssl, &proto, &proto_len); - } - - if (proto_len) - configuration.nextNegotiatedProtocol = QByteArray(reinterpret_cast<const char *>(proto), proto_len); - else - configuration.nextNegotiatedProtocol.clear(); - } -#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ... - -#if OPENSSL_VERSION_NUMBER >= 0x10002000L - if (q_SSLeay() >= 0x10002000L && mode == QSslSocket::SslClientMode) { - EVP_PKEY *key; - if (q_SSL_get_server_tmp_key(ssl, &key)) - configuration.ephemeralServerKey = QSslKey(key, QSsl::PublicKey); - } -#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L ... - - connectionEncrypted = true; - emit q->encrypted(); - if (autoStartHandshake && pendingClose) { - pendingClose = false; - q->disconnectFromHost(); - } -} - -QT_END_NAMESPACE |