3943 lines
168 KiB
Diff
3943 lines
168 KiB
Diff
|
diff --git a/config.tests/unix/openssl11/openssl.cpp b/config.tests/unix/openssl11/openssl.cpp
|
||
|
new file mode 100644
|
||
|
index 0000000..c20cc59
|
||
|
--- /dev/null
|
||
|
+++ b/config.tests/unix/openssl11/openssl.cpp
|
||
|
@@ -0,0 +1,48 @@
|
||
|
+/****************************************************************************
|
||
|
+**
|
||
|
+** Copyright (C) 2017 The Qt Company Ltd.
|
||
|
+** Contact: https://www.qt.io/licensing/
|
||
|
+**
|
||
|
+** This file is part of the config.tests 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$
|
||
|
+**
|
||
|
+****************************************************************************/
|
||
|
+
|
||
|
+#include <openssl/opensslv.h>
|
||
|
+
|
||
|
+#if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER-0 < 0x10100000L
|
||
|
+# error "OpenSSL >= 1.1 is required"
|
||
|
+#endif
|
||
|
+
|
||
|
+int main()
|
||
|
+{
|
||
|
+}
|
||
|
diff --git a/config.tests/unix/openssl11/openssl.pro b/config.tests/unix/openssl11/openssl.pro
|
||
|
new file mode 100644
|
||
|
index 0000000..a023aee
|
||
|
--- /dev/null
|
||
|
+++ b/config.tests/unix/openssl11/openssl.pro
|
||
|
@@ -0,0 +1,2 @@
|
||
|
+SOURCES = openssl.cpp
|
||
|
+CONFIG -= x11 qt
|
||
|
diff --git a/src/network/configure.json b/src/network/configure.json
|
||
|
index 916448a..5ecf1ad 100644
|
||
|
--- a/src/network/configure.json
|
||
|
+++ b/src/network/configure.json
|
||
|
@@ -154,6 +154,12 @@
|
||
|
]
|
||
|
},
|
||
|
"use": "network"
|
||
|
+ },
|
||
|
+ "openssl11": {
|
||
|
+ "label": "OpenSSL v. 1.1 support",
|
||
|
+ "type": "compile",
|
||
|
+ "test": "unix/openssl11",
|
||
|
+ "use": "network"
|
||
|
}
|
||
|
},
|
||
|
|
||
|
@@ -221,6 +227,11 @@
|
||
|
"condition": "config.winrt || features.securetransport || features.openssl",
|
||
|
"output": [ "publicFeature", "feature" ]
|
||
|
},
|
||
|
+ "opensslv11": {
|
||
|
+ "label": "OpenSSL v. 1.1",
|
||
|
+ "condition": "tests.openssl11",
|
||
|
+ "output": ["publicFeature", "feature"]
|
||
|
+ },
|
||
|
"sctp": {
|
||
|
"label": "SCTP",
|
||
|
"autoDetect": false,
|
||
|
diff --git a/src/network/ssl/qsslcertificate_openssl.cpp b/src/network/ssl/qsslcertificate_openssl.cpp
|
||
|
index 28b7eda..71e514a 100644
|
||
|
--- a/src/network/ssl/qsslcertificate_openssl.cpp
|
||
|
+++ b/src/network/ssl/qsslcertificate_openssl.cpp
|
||
|
@@ -1,6 +1,7 @@
|
||
|
/****************************************************************************
|
||
|
**
|
||
|
-** Copyright (C) 2016 The Qt Company Ltd.
|
||
|
+** Copyright (C) 2017 The Qt Company Ltd.
|
||
|
+** Copyright (C) 2016 Richard J. Moore <rich@kde.org>
|
||
|
** Contact: https://www.qt.io/licensing/
|
||
|
**
|
||
|
** This file is part of the QtNetwork module of the Qt Toolkit.
|
||
|
@@ -64,12 +65,14 @@ bool QSslCertificate::operator==(const QSslCertificate &other) const
|
||
|
uint qHash(const QSslCertificate &key, uint seed) Q_DECL_NOTHROW
|
||
|
{
|
||
|
if (X509 * const x509 = key.d->x509) {
|
||
|
- (void)q_X509_cmp(x509, x509); // populate x509->sha1_hash
|
||
|
- // (if someone knows a better way...)
|
||
|
- return qHashBits(x509->sha1_hash, SHA_DIGEST_LENGTH, seed);
|
||
|
- } else {
|
||
|
- return seed;
|
||
|
+ const EVP_MD *sha1 = q_EVP_sha1();
|
||
|
+ unsigned int len = 0;
|
||
|
+ unsigned char md[EVP_MAX_MD_SIZE];
|
||
|
+ q_X509_digest(x509, sha1, md, &len);
|
||
|
+ return qHashBits(md, len, seed);
|
||
|
}
|
||
|
+
|
||
|
+ return seed;
|
||
|
}
|
||
|
|
||
|
bool QSslCertificate::isNull() const
|
||
|
@@ -89,8 +92,7 @@ QByteArray QSslCertificate::version() const
|
||
|
{
|
||
|
QMutexLocker lock(QMutexPool::globalInstanceGet(d.data()));
|
||
|
if (d->versionString.isEmpty() && d->x509)
|
||
|
- d->versionString =
|
||
|
- QByteArray::number(qlonglong(q_ASN1_INTEGER_get(d->x509->cert_info->version)) + 1);
|
||
|
+ d->versionString = QByteArray::number(qlonglong(q_X509_get_version(d->x509)) + 1);
|
||
|
|
||
|
return d->versionString;
|
||
|
}
|
||
|
@@ -99,7 +101,7 @@ QByteArray QSslCertificate::serialNumber() const
|
||
|
{
|
||
|
QMutexLocker lock(QMutexPool::globalInstanceGet(d.data()));
|
||
|
if (d->serialNumberString.isEmpty() && d->x509) {
|
||
|
- ASN1_INTEGER *serialNumber = d->x509->cert_info->serialNumber;
|
||
|
+ ASN1_INTEGER *serialNumber = q_X509_get_serialNumber(d->x509);
|
||
|
QByteArray hexString;
|
||
|
hexString.reserve(serialNumber->length * 3);
|
||
|
for (int a = 0; a < serialNumber->length; ++a) {
|
||
|
@@ -199,14 +201,15 @@ QMultiMap<QSsl::AlternativeNameEntryType, QString> QSslCertificate::subjectAlter
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
- const char *altNameStr = reinterpret_cast<const char *>(q_ASN1_STRING_data(genName->d.ia5));
|
||
|
+ const char *altNameStr = reinterpret_cast<const char *>(q_ASN1_STRING_get0_data(genName->d.ia5));
|
||
|
const QString altName = QString::fromLatin1(altNameStr, len);
|
||
|
if (genName->type == GEN_DNS)
|
||
|
result.insert(QSsl::DnsEntry, altName);
|
||
|
else if (genName->type == GEN_EMAIL)
|
||
|
result.insert(QSsl::EmailEntry, altName);
|
||
|
}
|
||
|
- q_sk_pop_free((STACK*)altNames, reinterpret_cast<void(*)(void*)>(q_sk_free));
|
||
|
+
|
||
|
+ q_OPENSSL_sk_pop_free((OPENSSL_STACK*)altNames, reinterpret_cast<void(*)(void*)>(q_OPENSSL_sk_free));
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
@@ -235,25 +238,26 @@ QSslKey QSslCertificate::publicKey() const
|
||
|
QSslKey key;
|
||
|
|
||
|
key.d->type = QSsl::PublicKey;
|
||
|
- X509_PUBKEY *xkey = d->x509->cert_info->key;
|
||
|
- EVP_PKEY *pkey = q_X509_PUBKEY_get(xkey);
|
||
|
+
|
||
|
+ EVP_PKEY *pkey = q_X509_get_pubkey(d->x509);
|
||
|
Q_ASSERT(pkey);
|
||
|
+ const int keyType = q_EVP_PKEY_type(q_EVP_PKEY_base_id(pkey));
|
||
|
|
||
|
- if (q_EVP_PKEY_type(pkey->type) == EVP_PKEY_RSA) {
|
||
|
+ if (keyType == EVP_PKEY_RSA) {
|
||
|
key.d->rsa = q_EVP_PKEY_get1_RSA(pkey);
|
||
|
key.d->algorithm = QSsl::Rsa;
|
||
|
key.d->isNull = false;
|
||
|
- } else if (q_EVP_PKEY_type(pkey->type) == EVP_PKEY_DSA) {
|
||
|
+ } else if (keyType == EVP_PKEY_DSA) {
|
||
|
key.d->dsa = q_EVP_PKEY_get1_DSA(pkey);
|
||
|
key.d->algorithm = QSsl::Dsa;
|
||
|
key.d->isNull = false;
|
||
|
#ifndef OPENSSL_NO_EC
|
||
|
- } else if (q_EVP_PKEY_type(pkey->type) == EVP_PKEY_EC) {
|
||
|
+ } else if (keyType == EVP_PKEY_EC) {
|
||
|
key.d->ec = q_EVP_PKEY_get1_EC_KEY(pkey);
|
||
|
key.d->algorithm = QSsl::Ec;
|
||
|
key.d->isNull = false;
|
||
|
#endif
|
||
|
- } else if (q_EVP_PKEY_type(pkey->type) == EVP_PKEY_DH) {
|
||
|
+ } else if (keyType == EVP_PKEY_DH) {
|
||
|
// DH unsupported
|
||
|
} else {
|
||
|
// error?
|
||
|
@@ -275,7 +279,7 @@ static QVariant x509UnknownExtensionToValue(X509_EXTENSION *ext)
|
||
|
X509V3_EXT_METHOD *meth = const_cast<X509V3_EXT_METHOD *>(q_X509V3_EXT_get(ext));
|
||
|
if (!meth) {
|
||
|
ASN1_OCTET_STRING *value = q_X509_EXTENSION_get_data(ext);
|
||
|
- QByteArray result( reinterpret_cast<const char *>(q_ASN1_STRING_data(value)),
|
||
|
+ QByteArray result( reinterpret_cast<const char *>(q_ASN1_STRING_get0_data(value)),
|
||
|
q_ASN1_STRING_length(value));
|
||
|
return result;
|
||
|
}
|
||
|
@@ -371,7 +375,7 @@ static QVariant x509ExtensionToValue(X509_EXTENSION *ext)
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
- const char *uriStr = reinterpret_cast<const char *>(q_ASN1_STRING_data(name->d.uniformResourceIdentifier));
|
||
|
+ const char *uriStr = reinterpret_cast<const char *>(q_ASN1_STRING_get0_data(name->d.uniformResourceIdentifier));
|
||
|
const QString uri = QString::fromUtf8(uriStr, len);
|
||
|
|
||
|
result[QString::fromUtf8(QSslCertificatePrivate::asn1ObjectName(ad->method))] = uri;
|
||
|
@@ -380,11 +384,7 @@ static QVariant x509ExtensionToValue(X509_EXTENSION *ext)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
|
||
|
- q_sk_pop_free((_STACK*)info, reinterpret_cast<void(*)(void*)>(q_sk_free));
|
||
|
-#else
|
||
|
- q_sk_pop_free((STACK*)info, reinterpret_cast<void(*)(void*)>(q_sk_free));
|
||
|
-#endif
|
||
|
+ q_OPENSSL_sk_pop_free((OPENSSL_STACK*)info, reinterpret_cast<void(*)(void *)>(q_OPENSSL_sk_free));
|
||
|
return result;
|
||
|
}
|
||
|
break;
|
||
|
@@ -607,7 +607,11 @@ static QMap<QByteArray, QString> _q_mapFromX509Name(X509_NAME *name)
|
||
|
unsigned char *data = 0;
|
||
|
int size = q_ASN1_STRING_to_UTF8(&data, q_X509_NAME_ENTRY_get_data(e));
|
||
|
info.insertMulti(name, QString::fromUtf8((char*)data, size));
|
||
|
+#if QT_CONFIG(opensslv11)
|
||
|
+ q_CRYPTO_free(data, 0, 0);
|
||
|
+#else
|
||
|
q_CRYPTO_free(data);
|
||
|
+#endif
|
||
|
}
|
||
|
|
||
|
return info;
|
||
|
@@ -619,8 +623,9 @@ QSslCertificate QSslCertificatePrivate::QSslCertificate_from_X509(X509 *x509)
|
||
|
if (!x509 || !QSslSocket::supportsSsl())
|
||
|
return certificate;
|
||
|
|
||
|
- ASN1_TIME *nbef = q_X509_get_notBefore(x509);
|
||
|
- ASN1_TIME *naft = q_X509_get_notAfter(x509);
|
||
|
+ ASN1_TIME *nbef = q_X509_getm_notBefore(x509);
|
||
|
+ ASN1_TIME *naft = q_X509_getm_notAfter(x509);
|
||
|
+
|
||
|
certificate.d->notValidBefore = q_getTimeFromASN1(nbef);
|
||
|
certificate.d->notValidAfter = q_getTimeFromASN1(naft);
|
||
|
certificate.d->null = false;
|
||
|
diff --git a/src/network/ssl/qsslcontext_openssl.cpp b/src/network/ssl/qsslcontext_openssl.cpp
|
||
|
index c92d8fc..cef5037 100644
|
||
|
--- a/src/network/ssl/qsslcontext_openssl.cpp
|
||
|
+++ b/src/network/ssl/qsslcontext_openssl.cpp
|
||
|
@@ -1,6 +1,6 @@
|
||
|
/****************************************************************************
|
||
|
**
|
||
|
-** Copyright (C) 2016 The Qt Company Ltd.
|
||
|
+** Copyright (C) 2017 The Qt Company Ltd.
|
||
|
** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
|
||
|
** Copyright (C) 2014 Governikus GmbH & Co. KG.
|
||
|
** Contact: https://www.qt.io/licensing/
|
||
|
@@ -41,22 +41,14 @@
|
||
|
|
||
|
|
||
|
#include <QtNetwork/qsslsocket.h>
|
||
|
-#include <QtNetwork/qssldiffiehellmanparameters.h>
|
||
|
-#include <QtCore/qmutex.h>
|
||
|
|
||
|
#include "private/qssl_p.h"
|
||
|
#include "private/qsslcontext_openssl_p.h"
|
||
|
-#include "private/qsslsocket_p.h"
|
||
|
#include "private/qsslsocket_openssl_p.h"
|
||
|
#include "private/qsslsocket_openssl_symbols_p.h"
|
||
|
-#include "private/qssldiffiehellmanparameters_p.h"
|
||
|
|
||
|
QT_BEGIN_NAMESPACE
|
||
|
|
||
|
-// defined in qsslsocket_openssl.cpp:
|
||
|
-extern int q_X509Callback(int ok, X509_STORE_CTX *ctx);
|
||
|
-extern QString getErrorsFromOpenSsl();
|
||
|
-
|
||
|
QSslContext::QSslContext()
|
||
|
: ctx(0),
|
||
|
pkey(0),
|
||
|
@@ -78,301 +70,6 @@ QSslContext::~QSslContext()
|
||
|
q_SSL_SESSION_free(session);
|
||
|
}
|
||
|
|
||
|
-static inline QString msgErrorSettingEllipticCurves(const QString &why)
|
||
|
-{
|
||
|
- return QSslSocket::tr("Error when setting the elliptic curves (%1)").arg(why);
|
||
|
-}
|
||
|
-
|
||
|
-// static
|
||
|
-void QSslContext::initSslContext(QSslContext *sslContext, QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading)
|
||
|
-{
|
||
|
- sslContext->sslConfiguration = configuration;
|
||
|
- sslContext->errorCode = QSslError::NoError;
|
||
|
-
|
||
|
- bool client = (mode == QSslSocket::SslClientMode);
|
||
|
-
|
||
|
- bool reinitialized = false;
|
||
|
- bool unsupportedProtocol = false;
|
||
|
-init_context:
|
||
|
- switch (sslContext->sslConfiguration.protocol()) {
|
||
|
- case QSsl::SslV2:
|
||
|
-#ifndef OPENSSL_NO_SSL2
|
||
|
- sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv2_client_method() : q_SSLv2_server_method());
|
||
|
-#else
|
||
|
- // SSL 2 not supported by the system, but chosen deliberately -> error
|
||
|
- sslContext->ctx = 0;
|
||
|
- unsupportedProtocol = true;
|
||
|
-#endif
|
||
|
- break;
|
||
|
- case QSsl::SslV3:
|
||
|
-#ifndef OPENSSL_NO_SSL3_METHOD
|
||
|
- sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv3_client_method() : q_SSLv3_server_method());
|
||
|
-#else
|
||
|
- // SSL 3 not supported by the system, but chosen deliberately -> error
|
||
|
- sslContext->ctx = 0;
|
||
|
- unsupportedProtocol = true;
|
||
|
-#endif
|
||
|
- break;
|
||
|
- case QSsl::SecureProtocols:
|
||
|
- // SSLv2 and SSLv3 will be disabled by SSL options
|
||
|
- // But we need q_SSLv23_server_method() otherwise AnyProtocol will be unable to connect on Win32.
|
||
|
- case QSsl::TlsV1SslV3:
|
||
|
- // SSLv2 will will be disabled by SSL options
|
||
|
- case QSsl::AnyProtocol:
|
||
|
- default:
|
||
|
- sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method());
|
||
|
- break;
|
||
|
- case QSsl::TlsV1_0:
|
||
|
- sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_client_method() : q_TLSv1_server_method());
|
||
|
- break;
|
||
|
- case QSsl::TlsV1_1:
|
||
|
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
|
||
|
- sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_1_client_method() : q_TLSv1_1_server_method());
|
||
|
-#else
|
||
|
- // TLS 1.1 not supported by the system, but chosen deliberately -> error
|
||
|
- sslContext->ctx = 0;
|
||
|
- unsupportedProtocol = true;
|
||
|
-#endif
|
||
|
- break;
|
||
|
- case QSsl::TlsV1_2:
|
||
|
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
|
||
|
- sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_2_client_method() : q_TLSv1_2_server_method());
|
||
|
-#else
|
||
|
- // TLS 1.2 not supported by the system, but chosen deliberately -> error
|
||
|
- sslContext->ctx = 0;
|
||
|
- unsupportedProtocol = true;
|
||
|
-#endif
|
||
|
- break;
|
||
|
- case QSsl::TlsV1_0OrLater:
|
||
|
- // Specific protocols will be specified via SSL options.
|
||
|
- sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method());
|
||
|
- break;
|
||
|
- case QSsl::TlsV1_1OrLater:
|
||
|
- case QSsl::TlsV1_2OrLater:
|
||
|
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
|
||
|
- // Specific protocols will be specified via SSL options.
|
||
|
- sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method());
|
||
|
-#else
|
||
|
- // TLS 1.1/1.2 not supported by the system, but chosen deliberately -> error
|
||
|
- sslContext->ctx = 0;
|
||
|
- unsupportedProtocol = true;
|
||
|
-#endif
|
||
|
- break;
|
||
|
- }
|
||
|
-
|
||
|
- if (!sslContext->ctx) {
|
||
|
- // After stopping Flash 10 the SSL library looses its ciphers. Try re-adding them
|
||
|
- // by re-initializing the library.
|
||
|
- if (!reinitialized) {
|
||
|
- reinitialized = true;
|
||
|
- if (q_SSL_library_init() == 1)
|
||
|
- goto init_context;
|
||
|
- }
|
||
|
-
|
||
|
- sslContext->errorStr = QSslSocket::tr("Error creating SSL context (%1)").arg(
|
||
|
- unsupportedProtocol ? QSslSocket::tr("unsupported protocol") : QSslSocketBackendPrivate::getErrorsFromOpenSsl()
|
||
|
- );
|
||
|
- sslContext->errorCode = QSslError::UnspecifiedError;
|
||
|
- return;
|
||
|
- }
|
||
|
-
|
||
|
- // Enable bug workarounds.
|
||
|
- long options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions);
|
||
|
- q_SSL_CTX_set_options(sslContext->ctx, options);
|
||
|
-
|
||
|
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
|
||
|
- // Tell OpenSSL to release memory early
|
||
|
- // http://www.openssl.org/docs/ssl/SSL_CTX_set_mode.html
|
||
|
- if (q_SSLeay() >= 0x10000000L)
|
||
|
- q_SSL_CTX_set_mode(sslContext->ctx, SSL_MODE_RELEASE_BUFFERS);
|
||
|
-#endif
|
||
|
-
|
||
|
- // Initialize ciphers
|
||
|
- QByteArray cipherString;
|
||
|
- bool first = true;
|
||
|
- QList<QSslCipher> ciphers = sslContext->sslConfiguration.ciphers();
|
||
|
- if (ciphers.isEmpty())
|
||
|
- ciphers = QSslSocketPrivate::defaultCiphers();
|
||
|
- for (const QSslCipher &cipher : qAsConst(ciphers)) {
|
||
|
- if (first)
|
||
|
- first = false;
|
||
|
- else
|
||
|
- cipherString.append(':');
|
||
|
- cipherString.append(cipher.name().toLatin1());
|
||
|
- }
|
||
|
-
|
||
|
- if (!q_SSL_CTX_set_cipher_list(sslContext->ctx, cipherString.data())) {
|
||
|
- sslContext->errorStr = QSslSocket::tr("Invalid or empty cipher list (%1)").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
|
||
|
- sslContext->errorCode = QSslError::UnspecifiedError;
|
||
|
- return;
|
||
|
- }
|
||
|
-
|
||
|
- const QDateTime now = QDateTime::currentDateTimeUtc();
|
||
|
-
|
||
|
- // Add all our CAs to this store.
|
||
|
- const auto caCertificates = sslContext->sslConfiguration.caCertificates();
|
||
|
- for (const QSslCertificate &caCertificate : caCertificates) {
|
||
|
- // From https://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html:
|
||
|
- //
|
||
|
- // If several CA certificates matching the name, key identifier, and
|
||
|
- // serial number condition are available, only the first one will be
|
||
|
- // examined. This may lead to unexpected results if the same CA
|
||
|
- // certificate is available with different expiration dates. If a
|
||
|
- // ``certificate expired'' verification error occurs, no other
|
||
|
- // certificate will be searched. Make sure to not have expired
|
||
|
- // certificates mixed with valid ones.
|
||
|
- //
|
||
|
- // See also: QSslSocketBackendPrivate::verify()
|
||
|
- if (caCertificate.expiryDate() >= now) {
|
||
|
- q_X509_STORE_add_cert(q_SSL_CTX_get_cert_store(sslContext->ctx), (X509 *)caCertificate.handle());
|
||
|
- }
|
||
|
- }
|
||
|
-
|
||
|
- if (QSslSocketPrivate::s_loadRootCertsOnDemand && allowRootCertOnDemandLoading) {
|
||
|
- // tell OpenSSL the directories where to look up the root certs on demand
|
||
|
- const QList<QByteArray> unixDirs = QSslSocketPrivate::unixRootCertDirectories();
|
||
|
- for (const QByteArray &unixDir : unixDirs)
|
||
|
- q_SSL_CTX_load_verify_locations(sslContext->ctx, 0, unixDir.constData());
|
||
|
- }
|
||
|
-
|
||
|
- if (!sslContext->sslConfiguration.localCertificate().isNull()) {
|
||
|
- // Require a private key as well.
|
||
|
- if (sslContext->sslConfiguration.privateKey().isNull()) {
|
||
|
- sslContext->errorStr = QSslSocket::tr("Cannot provide a certificate with no key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
|
||
|
- sslContext->errorCode = QSslError::UnspecifiedError;
|
||
|
- return;
|
||
|
- }
|
||
|
-
|
||
|
- // Load certificate
|
||
|
- if (!q_SSL_CTX_use_certificate(sslContext->ctx, (X509 *)sslContext->sslConfiguration.localCertificate().handle())) {
|
||
|
- sslContext->errorStr = QSslSocket::tr("Error loading local certificate, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
|
||
|
- sslContext->errorCode = QSslError::UnspecifiedError;
|
||
|
- return;
|
||
|
- }
|
||
|
-
|
||
|
- if (configuration.d->privateKey.algorithm() == QSsl::Opaque) {
|
||
|
- sslContext->pkey = reinterpret_cast<EVP_PKEY *>(configuration.d->privateKey.handle());
|
||
|
- } else {
|
||
|
- // Load private key
|
||
|
- sslContext->pkey = q_EVP_PKEY_new();
|
||
|
- // before we were using EVP_PKEY_assign_R* functions and did not use EVP_PKEY_free.
|
||
|
- // this lead to a memory leak. Now we use the *_set1_* functions which do not
|
||
|
- // take ownership of the RSA/DSA key instance because the QSslKey already has ownership.
|
||
|
- if (configuration.d->privateKey.algorithm() == QSsl::Rsa)
|
||
|
- q_EVP_PKEY_set1_RSA(sslContext->pkey, reinterpret_cast<RSA *>(configuration.d->privateKey.handle()));
|
||
|
- else if (configuration.d->privateKey.algorithm() == QSsl::Dsa)
|
||
|
- q_EVP_PKEY_set1_DSA(sslContext->pkey, reinterpret_cast<DSA *>(configuration.d->privateKey.handle()));
|
||
|
-#ifndef OPENSSL_NO_EC
|
||
|
- else if (configuration.d->privateKey.algorithm() == QSsl::Ec)
|
||
|
- q_EVP_PKEY_set1_EC_KEY(sslContext->pkey, reinterpret_cast<EC_KEY *>(configuration.d->privateKey.handle()));
|
||
|
-#endif
|
||
|
- }
|
||
|
-
|
||
|
- if (!q_SSL_CTX_use_PrivateKey(sslContext->ctx, sslContext->pkey)) {
|
||
|
- sslContext->errorStr = QSslSocket::tr("Error loading private key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
|
||
|
- sslContext->errorCode = QSslError::UnspecifiedError;
|
||
|
- return;
|
||
|
- }
|
||
|
- if (configuration.d->privateKey.algorithm() == QSsl::Opaque)
|
||
|
- sslContext->pkey = 0; // Don't free the private key, it belongs to QSslKey
|
||
|
-
|
||
|
- // Check if the certificate matches the private key.
|
||
|
- if (!q_SSL_CTX_check_private_key(sslContext->ctx)) {
|
||
|
- sslContext->errorStr = QSslSocket::tr("Private key does not certify public key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
|
||
|
- sslContext->errorCode = QSslError::UnspecifiedError;
|
||
|
- return;
|
||
|
- }
|
||
|
-
|
||
|
- // If we have any intermediate certificates then we need to add them to our chain
|
||
|
- bool first = true;
|
||
|
- for (const QSslCertificate &cert : qAsConst(configuration.d->localCertificateChain)) {
|
||
|
- if (first) {
|
||
|
- first = false;
|
||
|
- continue;
|
||
|
- }
|
||
|
- q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0,
|
||
|
- q_X509_dup(reinterpret_cast<X509 *>(cert.handle())));
|
||
|
- }
|
||
|
- }
|
||
|
-
|
||
|
- // Initialize peer verification.
|
||
|
- if (sslContext->sslConfiguration.peerVerifyMode() == QSslSocket::VerifyNone) {
|
||
|
- q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_NONE, 0);
|
||
|
- } else {
|
||
|
- q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_PEER, q_X509Callback);
|
||
|
- }
|
||
|
-
|
||
|
- // Set verification depth.
|
||
|
- if (sslContext->sslConfiguration.peerVerifyDepth() != 0)
|
||
|
- q_SSL_CTX_set_verify_depth(sslContext->ctx, sslContext->sslConfiguration.peerVerifyDepth());
|
||
|
-
|
||
|
- // set persisted session if the user set it
|
||
|
- if (!configuration.sessionTicket().isEmpty())
|
||
|
- sslContext->setSessionASN1(configuration.sessionTicket());
|
||
|
-
|
||
|
- // Set temp DH params
|
||
|
- QSslDiffieHellmanParameters dhparams = configuration.diffieHellmanParameters();
|
||
|
-
|
||
|
- if (!dhparams.isValid()) {
|
||
|
- sslContext->errorStr = QSslSocket::tr("Diffie-Hellman parameters are not valid");
|
||
|
- sslContext->errorCode = QSslError::UnspecifiedError;
|
||
|
- return;
|
||
|
- }
|
||
|
-
|
||
|
- if (!dhparams.isEmpty()) {
|
||
|
- const QByteArray ¶ms = dhparams.d->derData;
|
||
|
- const char *ptr = params.constData();
|
||
|
- DH *dh = q_d2i_DHparams(NULL, reinterpret_cast<const unsigned char **>(&ptr), params.length());
|
||
|
- if (dh == NULL)
|
||
|
- qFatal("q_d2i_DHparams failed to convert QSslDiffieHellmanParameters to DER form");
|
||
|
- q_SSL_CTX_set_tmp_dh(sslContext->ctx, dh);
|
||
|
- q_DH_free(dh);
|
||
|
- }
|
||
|
-
|
||
|
-#ifndef OPENSSL_NO_EC
|
||
|
-#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||
|
- if (q_SSLeay() >= 0x10002000L) {
|
||
|
- q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_SET_ECDH_AUTO, 1, NULL);
|
||
|
- } else
|
||
|
-#endif
|
||
|
- {
|
||
|
- // Set temp ECDH params
|
||
|
- EC_KEY *ecdh = 0;
|
||
|
- ecdh = q_EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
|
||
|
- q_SSL_CTX_set_tmp_ecdh(sslContext->ctx, ecdh);
|
||
|
- q_EC_KEY_free(ecdh);
|
||
|
- }
|
||
|
-#endif // OPENSSL_NO_EC
|
||
|
-
|
||
|
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
|
||
|
- if (!client)
|
||
|
- q_SSL_CTX_use_psk_identity_hint(sslContext->ctx, sslContext->sslConfiguration.preSharedKeyIdentityHint().constData());
|
||
|
-#endif // OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
|
||
|
-
|
||
|
- const QVector<QSslEllipticCurve> qcurves = sslContext->sslConfiguration.ellipticCurves();
|
||
|
- if (!qcurves.isEmpty()) {
|
||
|
-#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_EC)
|
||
|
- // Set the curves to be used
|
||
|
- if (q_SSLeay() >= 0x10002000L) {
|
||
|
- // SSL_CTX_ctrl wants a non-const pointer as last argument,
|
||
|
- // but let's avoid a copy into a temporary array
|
||
|
- if (!q_SSL_CTX_ctrl(sslContext->ctx,
|
||
|
- SSL_CTRL_SET_CURVES,
|
||
|
- qcurves.size(),
|
||
|
- const_cast<int *>(reinterpret_cast<const int *>(qcurves.data())))) {
|
||
|
- sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
|
||
|
- sslContext->errorCode = QSslError::UnspecifiedError;
|
||
|
- }
|
||
|
- } else
|
||
|
-#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_EC)
|
||
|
- {
|
||
|
- // specific curves requested, but not possible to set -> error
|
||
|
- sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocket::tr("OpenSSL version too old, need at least v1.0.2"));
|
||
|
- sslContext->errorCode = QSslError::UnspecifiedError;
|
||
|
- }
|
||
|
- }
|
||
|
-}
|
||
|
-
|
||
|
QSslContext* QSslContext::fromConfiguration(QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading)
|
||
|
{
|
||
|
QSslContext *sslContext = new QSslContext();
|
||
|
@@ -463,7 +160,7 @@ SSL* QSslContext::createSsl()
|
||
|
m_npnContext.len = m_supportedNPNVersions.count();
|
||
|
m_npnContext.status = QSslConfiguration::NextProtocolNegotiationNone;
|
||
|
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||
|
- if (q_SSLeay() >= 0x10002000L) {
|
||
|
+ if (QSslSocket::sslLibraryVersionNumber() >= 0x10002000L) {
|
||
|
// Callback's type has a parameter 'const unsigned char ** out'
|
||
|
// since it was introduced in 1.0.2. Internally, OpenSSL's own code
|
||
|
// (tests/examples) cast it to unsigned char * (since it's 'out').
|
||
|
@@ -508,7 +205,7 @@ bool QSslContext::cacheSession(SSL* ssl)
|
||
|
unsigned char *data = reinterpret_cast<unsigned char *>(m_sessionASN1.data());
|
||
|
if (!q_i2d_SSL_SESSION(session, &data))
|
||
|
qCWarning(lcSsl, "could not store persistent version of SSL session");
|
||
|
- m_sessionTicketLifeTimeHint = session->tlsext_tick_lifetime_hint;
|
||
|
+ m_sessionTicketLifeTimeHint = q_SSL_SESSION_get_ticket_lifetime_hint(session);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
diff --git a/src/network/ssl/qsslcontext_openssl11.cpp b/src/network/ssl/qsslcontext_openssl11.cpp
|
||
|
new file mode 100644
|
||
|
index 0000000..787b6ae
|
||
|
--- /dev/null
|
||
|
+++ b/src/network/ssl/qsslcontext_openssl11.cpp
|
||
|
@@ -0,0 +1,277 @@
|
||
|
+/****************************************************************************
|
||
|
+**
|
||
|
+** Copyright (C) 2017 The Qt Company Ltd.
|
||
|
+** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
|
||
|
+** Copyright (C) 2014 Governikus GmbH & Co. KG.
|
||
|
+** Copyright (C) 2016 Richard J. Moore <rich@kde.org>
|
||
|
+** 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$
|
||
|
+**
|
||
|
+****************************************************************************/
|
||
|
+
|
||
|
+
|
||
|
+#include <QtNetwork/qsslsocket.h>
|
||
|
+#include <QtNetwork/qssldiffiehellmanparameters.h>
|
||
|
+
|
||
|
+#include "private/qssl_p.h"
|
||
|
+#include "private/qsslcontext_openssl_p.h"
|
||
|
+#include "private/qsslsocket_p.h"
|
||
|
+#include "private/qsslsocket_openssl_p.h"
|
||
|
+#include "private/qsslsocket_openssl_symbols_p.h"
|
||
|
+#include "private/qssldiffiehellmanparameters_p.h"
|
||
|
+
|
||
|
+#include <vector>
|
||
|
+
|
||
|
+QT_BEGIN_NAMESPACE
|
||
|
+
|
||
|
+// defined in qsslsocket_openssl.cpp:
|
||
|
+extern int q_X509Callback(int ok, X509_STORE_CTX *ctx);
|
||
|
+extern QString getErrorsFromOpenSsl();
|
||
|
+
|
||
|
+static inline QString msgErrorSettingEllipticCurves(const QString &why)
|
||
|
+{
|
||
|
+ return QSslSocket::tr("Error when setting the elliptic curves (%1)").arg(why);
|
||
|
+}
|
||
|
+
|
||
|
+// static
|
||
|
+void QSslContext::initSslContext(QSslContext *sslContext, QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading)
|
||
|
+{
|
||
|
+ sslContext->sslConfiguration = configuration;
|
||
|
+ sslContext->errorCode = QSslError::NoError;
|
||
|
+
|
||
|
+ bool client = (mode == QSslSocket::SslClientMode);
|
||
|
+
|
||
|
+ bool reinitialized = false;
|
||
|
+ bool unsupportedProtocol = false;
|
||
|
+init_context:
|
||
|
+ if (sslContext->sslConfiguration.protocol() == QSsl::SslV2) {
|
||
|
+ // SSL 2 is no longer supported, but chosen deliberately -> error
|
||
|
+ sslContext->ctx = nullptr;
|
||
|
+ unsupportedProtocol = true;
|
||
|
+ } else {
|
||
|
+ // The ssl options will actually control the supported methods
|
||
|
+ sslContext->ctx = q_SSL_CTX_new(client ? q_TLS_client_method() : q_TLS_server_method());
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!sslContext->ctx) {
|
||
|
+ // After stopping Flash 10 the SSL library loses its ciphers. Try re-adding them
|
||
|
+ // by re-initializing the library.
|
||
|
+ if (!reinitialized) {
|
||
|
+ reinitialized = true;
|
||
|
+ if (q_OPENSSL_init_ssl(0, nullptr) == 1)
|
||
|
+ goto init_context;
|
||
|
+ }
|
||
|
+
|
||
|
+ sslContext->errorStr = QSslSocket::tr("Error creating SSL context (%1)").arg(
|
||
|
+ unsupportedProtocol ? QSslSocket::tr("unsupported protocol") : QSslSocketBackendPrivate::getErrorsFromOpenSsl()
|
||
|
+ );
|
||
|
+ sslContext->errorCode = QSslError::UnspecifiedError;
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ // Enable bug workarounds.
|
||
|
+ long options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions);
|
||
|
+ q_SSL_CTX_set_options(sslContext->ctx, options);
|
||
|
+
|
||
|
+ // Tell OpenSSL to release memory early
|
||
|
+ // http://www.openssl.org/docs/ssl/SSL_CTX_set_mode.html
|
||
|
+ q_SSL_CTX_set_mode(sslContext->ctx, SSL_MODE_RELEASE_BUFFERS);
|
||
|
+
|
||
|
+ // Initialize ciphers
|
||
|
+ QByteArray cipherString;
|
||
|
+ bool first = true;
|
||
|
+ QList<QSslCipher> ciphers = sslContext->sslConfiguration.ciphers();
|
||
|
+ if (ciphers.isEmpty())
|
||
|
+ ciphers = QSslSocketPrivate::defaultCiphers();
|
||
|
+ for (const QSslCipher &cipher : qAsConst(ciphers)) {
|
||
|
+ if (first)
|
||
|
+ first = false;
|
||
|
+ else
|
||
|
+ cipherString.append(':');
|
||
|
+ cipherString.append(cipher.name().toLatin1());
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!q_SSL_CTX_set_cipher_list(sslContext->ctx, cipherString.data())) {
|
||
|
+ sslContext->errorStr = QSslSocket::tr("Invalid or empty cipher list (%1)").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
|
||
|
+ sslContext->errorCode = QSslError::UnspecifiedError;
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ const QDateTime now = QDateTime::currentDateTimeUtc();
|
||
|
+
|
||
|
+ // Add all our CAs to this store.
|
||
|
+ const auto caCertificates = sslContext->sslConfiguration.caCertificates();
|
||
|
+ for (const QSslCertificate &caCertificate : caCertificates) {
|
||
|
+ // From https://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html:
|
||
|
+ //
|
||
|
+ // If several CA certificates matching the name, key identifier, and
|
||
|
+ // serial number condition are available, only the first one will be
|
||
|
+ // examined. This may lead to unexpected results if the same CA
|
||
|
+ // certificate is available with different expiration dates. If a
|
||
|
+ // ``certificate expired'' verification error occurs, no other
|
||
|
+ // certificate will be searched. Make sure to not have expired
|
||
|
+ // certificates mixed with valid ones.
|
||
|
+ //
|
||
|
+ // See also: QSslSocketBackendPrivate::verify()
|
||
|
+ if (caCertificate.expiryDate() >= now) {
|
||
|
+ q_X509_STORE_add_cert(q_SSL_CTX_get_cert_store(sslContext->ctx), (X509 *)caCertificate.handle());
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ if (QSslSocketPrivate::s_loadRootCertsOnDemand && allowRootCertOnDemandLoading) {
|
||
|
+ // tell OpenSSL the directories where to look up the root certs on demand
|
||
|
+ const QList<QByteArray> unixDirs = QSslSocketPrivate::unixRootCertDirectories();
|
||
|
+ for (const QByteArray &unixDir : unixDirs)
|
||
|
+ q_SSL_CTX_load_verify_locations(sslContext->ctx, nullptr, unixDir.constData());
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!sslContext->sslConfiguration.localCertificate().isNull()) {
|
||
|
+ // Require a private key as well.
|
||
|
+ if (sslContext->sslConfiguration.privateKey().isNull()) {
|
||
|
+ sslContext->errorStr = QSslSocket::tr("Cannot provide a certificate with no key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
|
||
|
+ sslContext->errorCode = QSslError::UnspecifiedError;
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ // Load certificate
|
||
|
+ if (!q_SSL_CTX_use_certificate(sslContext->ctx, (X509 *)sslContext->sslConfiguration.localCertificate().handle())) {
|
||
|
+ sslContext->errorStr = QSslSocket::tr("Error loading local certificate, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
|
||
|
+ sslContext->errorCode = QSslError::UnspecifiedError;
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (configuration.d->privateKey.algorithm() == QSsl::Opaque) {
|
||
|
+ sslContext->pkey = reinterpret_cast<EVP_PKEY *>(configuration.d->privateKey.handle());
|
||
|
+ } else {
|
||
|
+ // Load private key
|
||
|
+ sslContext->pkey = q_EVP_PKEY_new();
|
||
|
+ // before we were using EVP_PKEY_assign_R* functions and did not use EVP_PKEY_free.
|
||
|
+ // this lead to a memory leak. Now we use the *_set1_* functions which do not
|
||
|
+ // take ownership of the RSA/DSA key instance because the QSslKey already has ownership.
|
||
|
+ if (configuration.d->privateKey.algorithm() == QSsl::Rsa)
|
||
|
+ q_EVP_PKEY_set1_RSA(sslContext->pkey, reinterpret_cast<RSA *>(configuration.d->privateKey.handle()));
|
||
|
+ else if (configuration.d->privateKey.algorithm() == QSsl::Dsa)
|
||
|
+ q_EVP_PKEY_set1_DSA(sslContext->pkey, reinterpret_cast<DSA *>(configuration.d->privateKey.handle()));
|
||
|
+#ifndef OPENSSL_NO_EC
|
||
|
+ else if (configuration.d->privateKey.algorithm() == QSsl::Ec)
|
||
|
+ q_EVP_PKEY_set1_EC_KEY(sslContext->pkey, reinterpret_cast<EC_KEY *>(configuration.d->privateKey.handle()));
|
||
|
+#endif
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!q_SSL_CTX_use_PrivateKey(sslContext->ctx, sslContext->pkey)) {
|
||
|
+ sslContext->errorStr = QSslSocket::tr("Error loading private key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
|
||
|
+ sslContext->errorCode = QSslError::UnspecifiedError;
|
||
|
+ return;
|
||
|
+ }
|
||
|
+ if (configuration.d->privateKey.algorithm() == QSsl::Opaque)
|
||
|
+ sslContext->pkey = nullptr; // Don't free the private key, it belongs to QSslKey
|
||
|
+
|
||
|
+ // Check if the certificate matches the private key.
|
||
|
+ if (!q_SSL_CTX_check_private_key(sslContext->ctx)) {
|
||
|
+ sslContext->errorStr = QSslSocket::tr("Private key does not certify public key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
|
||
|
+ sslContext->errorCode = QSslError::UnspecifiedError;
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ // If we have any intermediate certificates then we need to add them to our chain
|
||
|
+ bool first = true;
|
||
|
+ for (const QSslCertificate &cert : qAsConst(configuration.d->localCertificateChain)) {
|
||
|
+ if (first) {
|
||
|
+ first = false;
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+ q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0,
|
||
|
+ q_X509_dup(reinterpret_cast<X509 *>(cert.handle())));
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ // Initialize peer verification.
|
||
|
+ if (sslContext->sslConfiguration.peerVerifyMode() == QSslSocket::VerifyNone) {
|
||
|
+ q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_NONE, nullptr);
|
||
|
+ } else {
|
||
|
+ q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_PEER, q_X509Callback);
|
||
|
+ }
|
||
|
+
|
||
|
+ // Set verification depth.
|
||
|
+ if (sslContext->sslConfiguration.peerVerifyDepth() != 0)
|
||
|
+ q_SSL_CTX_set_verify_depth(sslContext->ctx, sslContext->sslConfiguration.peerVerifyDepth());
|
||
|
+
|
||
|
+ // set persisted session if the user set it
|
||
|
+ if (!configuration.sessionTicket().isEmpty())
|
||
|
+ sslContext->setSessionASN1(configuration.sessionTicket());
|
||
|
+
|
||
|
+ // Set temp DH params
|
||
|
+ QSslDiffieHellmanParameters dhparams = configuration.diffieHellmanParameters();
|
||
|
+
|
||
|
+ if (!dhparams.isValid()) {
|
||
|
+ sslContext->errorStr = QSslSocket::tr("Diffie-Hellman parameters are not valid");
|
||
|
+ sslContext->errorCode = QSslError::UnspecifiedError;
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!dhparams.isEmpty()) {
|
||
|
+ const QByteArray ¶ms = dhparams.d->derData;
|
||
|
+ const char *ptr = params.constData();
|
||
|
+ DH *dh = q_d2i_DHparams(NULL, reinterpret_cast<const unsigned char **>(&ptr), params.length());
|
||
|
+ if (dh == NULL)
|
||
|
+ qFatal("q_d2i_DHparams failed to convert QSslDiffieHellmanParameters to DER form");
|
||
|
+ q_SSL_CTX_set_tmp_dh(sslContext->ctx, dh);
|
||
|
+ q_DH_free(dh);
|
||
|
+ }
|
||
|
+
|
||
|
+#ifndef OPENSSL_NO_PSK
|
||
|
+ if (!client)
|
||
|
+ q_SSL_CTX_use_psk_identity_hint(sslContext->ctx, sslContext->sslConfiguration.preSharedKeyIdentityHint().constData());
|
||
|
+#endif // !OPENSSL_NO_PSK
|
||
|
+
|
||
|
+ const QVector<QSslEllipticCurve> qcurves = sslContext->sslConfiguration.ellipticCurves();
|
||
|
+ if (!qcurves.isEmpty()) {
|
||
|
+#ifdef OPENSSL_NO_EC
|
||
|
+ sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocket::tr("OpenSSL version with disabled elliptic curves"));
|
||
|
+ sslContext->errorCode = QSslError::UnspecifiedError;
|
||
|
+#else
|
||
|
+ // Set the curves to be used.
|
||
|
+ std::vector<int> curves;
|
||
|
+ curves.reserve(qcurves.size());
|
||
|
+ for (const auto &sslCurve : qcurves)
|
||
|
+ curves.push_back(sslCurve.id);
|
||
|
+ if (!q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_SET_CURVES, long(curves.size()), &curves[0])) {
|
||
|
+ sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
|
||
|
+ sslContext->errorCode = QSslError::UnspecifiedError;
|
||
|
+ }
|
||
|
+#endif
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+QT_END_NAMESPACE
|
||
|
diff --git a/src/network/ssl/qsslcontext_opensslpre11.cpp b/src/network/ssl/qsslcontext_opensslpre11.cpp
|
||
|
new file mode 100644
|
||
|
index 0000000..9c01c2f
|
||
|
--- /dev/null
|
||
|
+++ b/src/network/ssl/qsslcontext_opensslpre11.cpp
|
||
|
@@ -0,0 +1,354 @@
|
||
|
+/****************************************************************************
|
||
|
+**
|
||
|
+** Copyright (C) 2017 The Qt Company Ltd.
|
||
|
+** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
|
||
|
+** 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$
|
||
|
+**
|
||
|
+****************************************************************************/
|
||
|
+
|
||
|
+
|
||
|
+#include <QtNetwork/qsslsocket.h>
|
||
|
+#include <QtNetwork/qssldiffiehellmanparameters.h>
|
||
|
+
|
||
|
+#include "private/qssl_p.h"
|
||
|
+#include "private/qsslcontext_openssl_p.h"
|
||
|
+#include "private/qsslsocket_p.h"
|
||
|
+#include "private/qsslsocket_openssl_p.h"
|
||
|
+#include "private/qsslsocket_openssl_symbols_p.h"
|
||
|
+#include "private/qssldiffiehellmanparameters_p.h"
|
||
|
+
|
||
|
+QT_BEGIN_NAMESPACE
|
||
|
+
|
||
|
+// defined in qsslsocket_openssl.cpp:
|
||
|
+extern int q_X509Callback(int ok, X509_STORE_CTX *ctx);
|
||
|
+extern QString getErrorsFromOpenSsl();
|
||
|
+
|
||
|
+static inline QString msgErrorSettingEllipticCurves(const QString &why)
|
||
|
+{
|
||
|
+ return QSslSocket::tr("Error when setting the elliptic curves (%1)").arg(why);
|
||
|
+}
|
||
|
+
|
||
|
+// static
|
||
|
+void QSslContext::initSslContext(QSslContext *sslContext, QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading)
|
||
|
+{
|
||
|
+ sslContext->sslConfiguration = configuration;
|
||
|
+ sslContext->errorCode = QSslError::NoError;
|
||
|
+
|
||
|
+ bool client = (mode == QSslSocket::SslClientMode);
|
||
|
+
|
||
|
+ bool reinitialized = false;
|
||
|
+ bool unsupportedProtocol = false;
|
||
|
+init_context:
|
||
|
+ switch (sslContext->sslConfiguration.protocol()) {
|
||
|
+ case QSsl::SslV2:
|
||
|
+#ifndef OPENSSL_NO_SSL2
|
||
|
+ sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv2_client_method() : q_SSLv2_server_method());
|
||
|
+#else
|
||
|
+ // SSL 2 not supported by the system, but chosen deliberately -> error
|
||
|
+ sslContext->ctx = 0;
|
||
|
+ unsupportedProtocol = true;
|
||
|
+#endif
|
||
|
+ break;
|
||
|
+ case QSsl::SslV3:
|
||
|
+#ifndef OPENSSL_NO_SSL3_METHOD
|
||
|
+ sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv3_client_method() : q_SSLv3_server_method());
|
||
|
+#else
|
||
|
+ // SSL 3 not supported by the system, but chosen deliberately -> error
|
||
|
+ sslContext->ctx = 0;
|
||
|
+ unsupportedProtocol = true;
|
||
|
+#endif
|
||
|
+ break;
|
||
|
+ case QSsl::SecureProtocols:
|
||
|
+ // SSLv2 and SSLv3 will be disabled by SSL options
|
||
|
+ // But we need q_SSLv23_server_method() otherwise AnyProtocol will be unable to connect on Win32.
|
||
|
+ case QSsl::TlsV1SslV3:
|
||
|
+ // SSLv2 will will be disabled by SSL options
|
||
|
+ case QSsl::AnyProtocol:
|
||
|
+ default:
|
||
|
+ sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method());
|
||
|
+ break;
|
||
|
+ case QSsl::TlsV1_0:
|
||
|
+ sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_client_method() : q_TLSv1_server_method());
|
||
|
+ break;
|
||
|
+ case QSsl::TlsV1_1:
|
||
|
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
|
||
|
+ sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_1_client_method() : q_TLSv1_1_server_method());
|
||
|
+#else
|
||
|
+ // TLS 1.1 not supported by the system, but chosen deliberately -> error
|
||
|
+ sslContext->ctx = 0;
|
||
|
+ unsupportedProtocol = true;
|
||
|
+#endif
|
||
|
+ break;
|
||
|
+ case QSsl::TlsV1_2:
|
||
|
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
|
||
|
+ sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_2_client_method() : q_TLSv1_2_server_method());
|
||
|
+#else
|
||
|
+ // TLS 1.2 not supported by the system, but chosen deliberately -> error
|
||
|
+ sslContext->ctx = 0;
|
||
|
+ unsupportedProtocol = true;
|
||
|
+#endif
|
||
|
+ break;
|
||
|
+ case QSsl::TlsV1_0OrLater:
|
||
|
+ // Specific protocols will be specified via SSL options.
|
||
|
+ sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method());
|
||
|
+ break;
|
||
|
+ case QSsl::TlsV1_1OrLater:
|
||
|
+ case QSsl::TlsV1_2OrLater:
|
||
|
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
|
||
|
+ // Specific protocols will be specified via SSL options.
|
||
|
+ sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method());
|
||
|
+#else
|
||
|
+ // TLS 1.1/1.2 not supported by the system, but chosen deliberately -> error
|
||
|
+ sslContext->ctx = 0;
|
||
|
+ unsupportedProtocol = true;
|
||
|
+#endif
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!sslContext->ctx) {
|
||
|
+ // After stopping Flash 10 the SSL library loses its ciphers. Try re-adding them
|
||
|
+ // by re-initializing the library.
|
||
|
+ if (!reinitialized) {
|
||
|
+ reinitialized = true;
|
||
|
+ if (q_SSL_library_init() == 1)
|
||
|
+ goto init_context;
|
||
|
+ }
|
||
|
+
|
||
|
+ sslContext->errorStr = QSslSocket::tr("Error creating SSL context (%1)").arg(
|
||
|
+ unsupportedProtocol ? QSslSocket::tr("unsupported protocol") : QSslSocketBackendPrivate::getErrorsFromOpenSsl()
|
||
|
+ );
|
||
|
+ sslContext->errorCode = QSslError::UnspecifiedError;
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ // Enable bug workarounds.
|
||
|
+ long options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions);
|
||
|
+ q_SSL_CTX_set_options(sslContext->ctx, options);
|
||
|
+
|
||
|
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
|
||
|
+ // Tell OpenSSL to release memory early
|
||
|
+ // http://www.openssl.org/docs/ssl/SSL_CTX_set_mode.html
|
||
|
+ if (q_SSLeay() >= 0x10000000L)
|
||
|
+ q_SSL_CTX_set_mode(sslContext->ctx, SSL_MODE_RELEASE_BUFFERS);
|
||
|
+#endif
|
||
|
+
|
||
|
+ // Initialize ciphers
|
||
|
+ QByteArray cipherString;
|
||
|
+ bool first = true;
|
||
|
+ QList<QSslCipher> ciphers = sslContext->sslConfiguration.ciphers();
|
||
|
+ if (ciphers.isEmpty())
|
||
|
+ ciphers = QSslSocketPrivate::defaultCiphers();
|
||
|
+ for (const QSslCipher &cipher : qAsConst(ciphers)) {
|
||
|
+ if (first)
|
||
|
+ first = false;
|
||
|
+ else
|
||
|
+ cipherString.append(':');
|
||
|
+ cipherString.append(cipher.name().toLatin1());
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!q_SSL_CTX_set_cipher_list(sslContext->ctx, cipherString.data())) {
|
||
|
+ sslContext->errorStr = QSslSocket::tr("Invalid or empty cipher list (%1)").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
|
||
|
+ sslContext->errorCode = QSslError::UnspecifiedError;
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ const QDateTime now = QDateTime::currentDateTimeUtc();
|
||
|
+
|
||
|
+ // Add all our CAs to this store.
|
||
|
+ const auto caCertificates = sslContext->sslConfiguration.caCertificates();
|
||
|
+ for (const QSslCertificate &caCertificate : caCertificates) {
|
||
|
+ // From https://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html:
|
||
|
+ //
|
||
|
+ // If several CA certificates matching the name, key identifier, and
|
||
|
+ // serial number condition are available, only the first one will be
|
||
|
+ // examined. This may lead to unexpected results if the same CA
|
||
|
+ // certificate is available with different expiration dates. If a
|
||
|
+ // ``certificate expired'' verification error occurs, no other
|
||
|
+ // certificate will be searched. Make sure to not have expired
|
||
|
+ // certificates mixed with valid ones.
|
||
|
+ //
|
||
|
+ // See also: QSslSocketBackendPrivate::verify()
|
||
|
+ if (caCertificate.expiryDate() >= now) {
|
||
|
+ q_X509_STORE_add_cert(q_SSL_CTX_get_cert_store(sslContext->ctx), (X509 *)caCertificate.handle());
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ if (QSslSocketPrivate::s_loadRootCertsOnDemand && allowRootCertOnDemandLoading) {
|
||
|
+ // tell OpenSSL the directories where to look up the root certs on demand
|
||
|
+ const QList<QByteArray> unixDirs = QSslSocketPrivate::unixRootCertDirectories();
|
||
|
+ for (const QByteArray &unixDir : unixDirs)
|
||
|
+ q_SSL_CTX_load_verify_locations(sslContext->ctx, 0, unixDir.constData());
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!sslContext->sslConfiguration.localCertificate().isNull()) {
|
||
|
+ // Require a private key as well.
|
||
|
+ if (sslContext->sslConfiguration.privateKey().isNull()) {
|
||
|
+ sslContext->errorStr = QSslSocket::tr("Cannot provide a certificate with no key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
|
||
|
+ sslContext->errorCode = QSslError::UnspecifiedError;
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ // Load certificate
|
||
|
+ if (!q_SSL_CTX_use_certificate(sslContext->ctx, (X509 *)sslContext->sslConfiguration.localCertificate().handle())) {
|
||
|
+ sslContext->errorStr = QSslSocket::tr("Error loading local certificate, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
|
||
|
+ sslContext->errorCode = QSslError::UnspecifiedError;
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (configuration.d->privateKey.algorithm() == QSsl::Opaque) {
|
||
|
+ sslContext->pkey = reinterpret_cast<EVP_PKEY *>(configuration.d->privateKey.handle());
|
||
|
+ } else {
|
||
|
+ // Load private key
|
||
|
+ sslContext->pkey = q_EVP_PKEY_new();
|
||
|
+ // before we were using EVP_PKEY_assign_R* functions and did not use EVP_PKEY_free.
|
||
|
+ // this lead to a memory leak. Now we use the *_set1_* functions which do not
|
||
|
+ // take ownership of the RSA/DSA key instance because the QSslKey already has ownership.
|
||
|
+ if (configuration.d->privateKey.algorithm() == QSsl::Rsa)
|
||
|
+ q_EVP_PKEY_set1_RSA(sslContext->pkey, reinterpret_cast<RSA *>(configuration.d->privateKey.handle()));
|
||
|
+ else if (configuration.d->privateKey.algorithm() == QSsl::Dsa)
|
||
|
+ q_EVP_PKEY_set1_DSA(sslContext->pkey, reinterpret_cast<DSA *>(configuration.d->privateKey.handle()));
|
||
|
+#ifndef OPENSSL_NO_EC
|
||
|
+ else if (configuration.d->privateKey.algorithm() == QSsl::Ec)
|
||
|
+ q_EVP_PKEY_set1_EC_KEY(sslContext->pkey, reinterpret_cast<EC_KEY *>(configuration.d->privateKey.handle()));
|
||
|
+#endif
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!q_SSL_CTX_use_PrivateKey(sslContext->ctx, sslContext->pkey)) {
|
||
|
+ sslContext->errorStr = QSslSocket::tr("Error loading private key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
|
||
|
+ sslContext->errorCode = QSslError::UnspecifiedError;
|
||
|
+ return;
|
||
|
+ }
|
||
|
+ if (configuration.d->privateKey.algorithm() == QSsl::Opaque)
|
||
|
+ sslContext->pkey = 0; // Don't free the private key, it belongs to QSslKey
|
||
|
+
|
||
|
+ // Check if the certificate matches the private key.
|
||
|
+ if (!q_SSL_CTX_check_private_key(sslContext->ctx)) {
|
||
|
+ sslContext->errorStr = QSslSocket::tr("Private key does not certify public key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
|
||
|
+ sslContext->errorCode = QSslError::UnspecifiedError;
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ // If we have any intermediate certificates then we need to add them to our chain
|
||
|
+ bool first = true;
|
||
|
+ for (const QSslCertificate &cert : qAsConst(configuration.d->localCertificateChain)) {
|
||
|
+ if (first) {
|
||
|
+ first = false;
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+ q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0,
|
||
|
+ q_X509_dup(reinterpret_cast<X509 *>(cert.handle())));
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ // Initialize peer verification.
|
||
|
+ if (sslContext->sslConfiguration.peerVerifyMode() == QSslSocket::VerifyNone) {
|
||
|
+ q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_NONE, 0);
|
||
|
+ } else {
|
||
|
+ q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_PEER, q_X509Callback);
|
||
|
+ }
|
||
|
+
|
||
|
+ // Set verification depth.
|
||
|
+ if (sslContext->sslConfiguration.peerVerifyDepth() != 0)
|
||
|
+ q_SSL_CTX_set_verify_depth(sslContext->ctx, sslContext->sslConfiguration.peerVerifyDepth());
|
||
|
+
|
||
|
+ // set persisted session if the user set it
|
||
|
+ if (!configuration.sessionTicket().isEmpty())
|
||
|
+ sslContext->setSessionASN1(configuration.sessionTicket());
|
||
|
+
|
||
|
+ // Set temp DH params
|
||
|
+ QSslDiffieHellmanParameters dhparams = configuration.diffieHellmanParameters();
|
||
|
+
|
||
|
+ if (!dhparams.isValid()) {
|
||
|
+ sslContext->errorStr = QSslSocket::tr("Diffie-Hellman parameters are not valid");
|
||
|
+ sslContext->errorCode = QSslError::UnspecifiedError;
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!dhparams.isEmpty()) {
|
||
|
+ const QByteArray ¶ms = dhparams.d->derData;
|
||
|
+ const char *ptr = params.constData();
|
||
|
+ DH *dh = q_d2i_DHparams(NULL, reinterpret_cast<const unsigned char **>(&ptr), params.length());
|
||
|
+ if (dh == NULL)
|
||
|
+ qFatal("q_d2i_DHparams failed to convert QSslDiffieHellmanParameters to DER form");
|
||
|
+ q_SSL_CTX_set_tmp_dh(sslContext->ctx, dh);
|
||
|
+ q_DH_free(dh);
|
||
|
+ }
|
||
|
+
|
||
|
+#ifndef OPENSSL_NO_EC
|
||
|
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||
|
+ if (q_SSLeay() >= 0x10002000L) {
|
||
|
+ q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_SET_ECDH_AUTO, 1, NULL);
|
||
|
+ } else
|
||
|
+#endif
|
||
|
+ {
|
||
|
+ // Set temp ECDH params
|
||
|
+ EC_KEY *ecdh = 0;
|
||
|
+ ecdh = q_EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
|
||
|
+ q_SSL_CTX_set_tmp_ecdh(sslContext->ctx, ecdh);
|
||
|
+ q_EC_KEY_free(ecdh);
|
||
|
+ }
|
||
|
+#endif // OPENSSL_NO_EC
|
||
|
+
|
||
|
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
|
||
|
+ if (!client)
|
||
|
+ q_SSL_CTX_use_psk_identity_hint(sslContext->ctx, sslContext->sslConfiguration.preSharedKeyIdentityHint().constData());
|
||
|
+#endif // OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
|
||
|
+
|
||
|
+ const QVector<QSslEllipticCurve> qcurves = sslContext->sslConfiguration.ellipticCurves();
|
||
|
+ if (!qcurves.isEmpty()) {
|
||
|
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_EC)
|
||
|
+ // Set the curves to be used
|
||
|
+ if (q_SSLeay() >= 0x10002000L) {
|
||
|
+ // SSL_CTX_ctrl wants a non-const pointer as last argument,
|
||
|
+ // but let's avoid a copy into a temporary array
|
||
|
+ if (!q_SSL_CTX_ctrl(sslContext->ctx,
|
||
|
+ SSL_CTRL_SET_CURVES,
|
||
|
+ qcurves.size(),
|
||
|
+ const_cast<int *>(reinterpret_cast<const int *>(qcurves.data())))) {
|
||
|
+ sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
|
||
|
+ sslContext->errorCode = QSslError::UnspecifiedError;
|
||
|
+ }
|
||
|
+ } else
|
||
|
+#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_EC)
|
||
|
+ {
|
||
|
+ // specific curves requested, but not possible to set -> error
|
||
|
+ sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocket::tr("OpenSSL version too old, need at least v1.0.2"));
|
||
|
+ sslContext->errorCode = QSslError::UnspecifiedError;
|
||
|
+ }
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+QT_END_NAMESPACE
|
||
|
diff --git a/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp b/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp
|
||
|
index 90687b0..5ebad82 100644
|
||
|
--- a/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp
|
||
|
+++ b/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp
|
||
|
@@ -1,6 +1,7 @@
|
||
|
/****************************************************************************
|
||
|
**
|
||
|
** Copyright (C) 2015 Mikkel Krautz <mikkel@krautz.dk>
|
||
|
+** Copyright (C) 2016 Richard J. Moore <rich@kde.org>
|
||
|
** Contact: https://www.qt.io/licensing/
|
||
|
**
|
||
|
** This file is part of the QtNetwork module of the Qt Toolkit.
|
||
|
@@ -50,8 +51,8 @@
|
||
|
#include <QtCore/qdebug.h>
|
||
|
#endif
|
||
|
|
||
|
-// For q_BN_is_word.
|
||
|
#include <openssl/bn.h>
|
||
|
+#include <openssl/dh.h>
|
||
|
|
||
|
QT_BEGIN_NAMESPACE
|
||
|
|
||
|
@@ -62,13 +63,6 @@ static bool isSafeDH(DH *dh)
|
||
|
|
||
|
QSslSocketPrivate::ensureInitialized();
|
||
|
|
||
|
- // Mark p < 1024 bits as unsafe.
|
||
|
- if (q_BN_num_bits(dh->p) < 1024) {
|
||
|
- return false;
|
||
|
- }
|
||
|
-
|
||
|
- if (q_DH_check(dh, &status) != 1)
|
||
|
- return false;
|
||
|
|
||
|
// From https://wiki.openssl.org/index.php/Diffie-Hellman_parameters:
|
||
|
//
|
||
|
@@ -81,11 +75,39 @@ static bool isSafeDH(DH *dh)
|
||
|
// Without the test, the IETF parameters would
|
||
|
// fail validation. For details, see Diffie-Hellman
|
||
|
// Parameter Check (when g = 2, must p mod 24 == 11?).
|
||
|
+#if QT_CONFIG(opensslv11)
|
||
|
+ // Mark p < 1024 bits as unsafe.
|
||
|
+ if (q_DH_bits(dh) < 1024)
|
||
|
+ return false;
|
||
|
+
|
||
|
+ if (q_DH_check(dh, &status) != 1)
|
||
|
+ return false;
|
||
|
+
|
||
|
+ const BIGNUM *p = nullptr;
|
||
|
+ const BIGNUM *q = nullptr;
|
||
|
+ const BIGNUM *g = nullptr;
|
||
|
+ q_DH_get0_pqg(dh, &p, &q, &g);
|
||
|
+
|
||
|
+ if (q_BN_is_word(const_cast<BIGNUM *>(g), DH_GENERATOR_2)) {
|
||
|
+ long residue = q_BN_mod_word(p, 24);
|
||
|
+ if (residue == 11 || residue == 23)
|
||
|
+ status &= ~DH_NOT_SUITABLE_GENERATOR;
|
||
|
+ }
|
||
|
+
|
||
|
+#else
|
||
|
+ // Mark p < 1024 bits as unsafe.
|
||
|
+ if (q_BN_num_bits(dh->p) < 1024)
|
||
|
+ return false;
|
||
|
+
|
||
|
+ if (q_DH_check(dh, &status) != 1)
|
||
|
+ return false;
|
||
|
+
|
||
|
if (q_BN_is_word(dh->g, DH_GENERATOR_2)) {
|
||
|
long residue = q_BN_mod_word(dh->p, 24);
|
||
|
if (residue == 11 || residue == 23)
|
||
|
status &= ~DH_NOT_SUITABLE_GENERATOR;
|
||
|
}
|
||
|
+#endif
|
||
|
|
||
|
bad |= DH_CHECK_P_NOT_PRIME;
|
||
|
bad |= DH_CHECK_P_NOT_SAFE_PRIME;
|
||
|
diff --git a/src/network/ssl/qsslellipticcurve.h b/src/network/ssl/qsslellipticcurve.h
|
||
|
index 2315660..57dda19 100644
|
||
|
--- a/src/network/ssl/qsslellipticcurve.h
|
||
|
+++ b/src/network/ssl/qsslellipticcurve.h
|
||
|
@@ -80,6 +80,7 @@ private:
|
||
|
friend Q_DECL_CONSTEXPR bool operator==(QSslEllipticCurve lhs, QSslEllipticCurve rhs) Q_DECL_NOTHROW;
|
||
|
friend Q_DECL_CONSTEXPR uint qHash(QSslEllipticCurve curve, uint seed) Q_DECL_NOTHROW;
|
||
|
|
||
|
+ friend class QSslContext;
|
||
|
friend class QSslSocketPrivate;
|
||
|
friend class QSslSocketBackendPrivate;
|
||
|
};
|
||
|
diff --git a/src/network/ssl/qsslellipticcurve_openssl.cpp b/src/network/ssl/qsslellipticcurve_openssl.cpp
|
||
|
index e18197b..8cd1483 100644
|
||
|
--- a/src/network/ssl/qsslellipticcurve_openssl.cpp
|
||
|
+++ b/src/network/ssl/qsslellipticcurve_openssl.cpp
|
||
|
@@ -1,6 +1,7 @@
|
||
|
/****************************************************************************
|
||
|
**
|
||
|
** Copyright (C) 2014 Governikus GmbH & Co. KG.
|
||
|
+** Copyright (C) 2016 Richard J. Moore <rich@kde.org>
|
||
|
** Contact: https://www.qt.io/licensing/
|
||
|
**
|
||
|
** This file is part of the QtNetwork module of the Qt Toolkit.
|
||
|
@@ -78,17 +79,18 @@ QSslEllipticCurve QSslEllipticCurve::fromShortName(const QString &name)
|
||
|
QSslEllipticCurve result;
|
||
|
|
||
|
#ifndef OPENSSL_NO_EC
|
||
|
- const QByteArray curveNameLatin1 = name.toLatin1();
|
||
|
|
||
|
+ const QByteArray curveNameLatin1 = name.toLatin1();
|
||
|
int nid = q_OBJ_sn2nid(curveNameLatin1.data());
|
||
|
|
||
|
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||
|
- if (nid == 0 && q_SSLeay() >= 0x10002000L)
|
||
|
+ if (nid == 0 && QSslSocket::sslLibraryVersionNumber() >= 0x10002000L)
|
||
|
nid = q_EC_curve_nist2nid(curveNameLatin1.data());
|
||
|
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||
|
|
||
|
result.id = nid;
|
||
|
-#endif
|
||
|
+
|
||
|
+#endif // !OPENSSL_NO_EC
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
diff --git a/src/network/ssl/qsslkey_openssl.cpp b/src/network/ssl/qsslkey_openssl.cpp
|
||
|
index 2611902..2b03af9 100644
|
||
|
--- a/src/network/ssl/qsslkey_openssl.cpp
|
||
|
+++ b/src/network/ssl/qsslkey_openssl.cpp
|
||
|
@@ -1,6 +1,7 @@
|
||
|
/****************************************************************************
|
||
|
**
|
||
|
-** Copyright (C) 2016 The Qt Company Ltd.
|
||
|
+** Copyright (C) 2017 The Qt Company Ltd.
|
||
|
+** Copyright (C) 2016 Richard J. Moore <rich@kde.org>
|
||
|
** Contact: https://www.qt.io/licensing/
|
||
|
**
|
||
|
** This file is part of the QtNetwork module of the Qt Toolkit.
|
||
|
@@ -87,33 +88,32 @@ bool QSslKeyPrivate::fromEVP_PKEY(EVP_PKEY *pkey)
|
||
|
if (pkey == nullptr)
|
||
|
return false;
|
||
|
|
||
|
- if (pkey->type == EVP_PKEY_RSA) {
|
||
|
+#if QT_CONFIG(opensslv11)
|
||
|
+ const int keyType = q_EVP_PKEY_type(q_EVP_PKEY_base_id(pkey));
|
||
|
+#else
|
||
|
+ const int keyType = pkey->type;
|
||
|
+#endif
|
||
|
+ if (keyType == EVP_PKEY_RSA) {
|
||
|
isNull = false;
|
||
|
algorithm = QSsl::Rsa;
|
||
|
type = QSsl::PrivateKey;
|
||
|
|
||
|
- rsa = q_RSA_new();
|
||
|
- memcpy(rsa, q_EVP_PKEY_get1_RSA(pkey), sizeof(RSA));
|
||
|
-
|
||
|
+ rsa = q_EVP_PKEY_get1_RSA(pkey);
|
||
|
return true;
|
||
|
- }
|
||
|
- else if (pkey->type == EVP_PKEY_DSA) {
|
||
|
+ } else if (keyType == EVP_PKEY_DSA) {
|
||
|
isNull = false;
|
||
|
algorithm = QSsl::Dsa;
|
||
|
type = QSsl::PrivateKey;
|
||
|
|
||
|
- dsa = q_DSA_new();
|
||
|
- memcpy(dsa, q_EVP_PKEY_get1_DSA(pkey), sizeof(DSA));
|
||
|
-
|
||
|
+ dsa = q_EVP_PKEY_get1_DSA(pkey);
|
||
|
return true;
|
||
|
}
|
||
|
#ifndef OPENSSL_NO_EC
|
||
|
- else if (pkey->type == EVP_PKEY_EC) {
|
||
|
+ else if (keyType == EVP_PKEY_EC) {
|
||
|
isNull = false;
|
||
|
algorithm = QSsl::Ec;
|
||
|
type = QSsl::PrivateKey;
|
||
|
- ec = q_EC_KEY_dup(q_EVP_PKEY_get1_EC_KEY(pkey));
|
||
|
-
|
||
|
+ ec = q_EVP_PKEY_get1_EC_KEY(pkey);
|
||
|
return true;
|
||
|
}
|
||
|
#endif
|
||
|
@@ -181,8 +181,8 @@ int QSslKeyPrivate::length() const
|
||
|
return -1;
|
||
|
|
||
|
switch (algorithm) {
|
||
|
- case QSsl::Rsa: return q_BN_num_bits(rsa->n);
|
||
|
- case QSsl::Dsa: return q_BN_num_bits(dsa->p);
|
||
|
+ case QSsl::Rsa: return q_RSA_bits(rsa);
|
||
|
+ case QSsl::Dsa: return q_DSA_bits(dsa);
|
||
|
#ifndef OPENSSL_NO_EC
|
||
|
case QSsl::Ec: return q_EC_GROUP_get_degree(q_EC_KEY_get0_group(ec));
|
||
|
#endif
|
||
|
@@ -276,7 +276,13 @@ Qt::HANDLE QSslKeyPrivate::handle() const
|
||
|
|
||
|
static QByteArray doCrypt(QSslKeyPrivate::Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv, int enc)
|
||
|
{
|
||
|
- EVP_CIPHER_CTX ctx;
|
||
|
+#if QT_CONFIG(opensslv11)
|
||
|
+ EVP_CIPHER_CTX *ctx = q_EVP_CIPHER_CTX_new();
|
||
|
+#else
|
||
|
+ EVP_CIPHER_CTX evpCipherContext;
|
||
|
+ EVP_CIPHER_CTX *ctx = &evpCipherContext;
|
||
|
+#endif
|
||
|
+
|
||
|
const EVP_CIPHER* type = 0;
|
||
|
int i = 0, len = 0;
|
||
|
|
||
|
@@ -294,21 +300,44 @@ static QByteArray doCrypt(QSslKeyPrivate::Cipher cipher, const QByteArray &data,
|
||
|
|
||
|
QByteArray output;
|
||
|
output.resize(data.size() + EVP_MAX_BLOCK_LENGTH);
|
||
|
- q_EVP_CIPHER_CTX_init(&ctx);
|
||
|
- q_EVP_CipherInit(&ctx, type, NULL, NULL, enc);
|
||
|
- q_EVP_CIPHER_CTX_set_key_length(&ctx, key.size());
|
||
|
+
|
||
|
+#if QT_CONFIG(opensslv11)
|
||
|
+ q_EVP_CIPHER_CTX_reset(ctx);
|
||
|
+#else
|
||
|
+ q_EVP_CIPHER_CTX_init(ctx);
|
||
|
+#endif
|
||
|
+
|
||
|
+ q_EVP_CipherInit(ctx, type, NULL, NULL, enc);
|
||
|
+ q_EVP_CIPHER_CTX_set_key_length(ctx, key.size());
|
||
|
if (cipher == QSslKeyPrivate::Rc2Cbc)
|
||
|
- q_EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_SET_RC2_KEY_BITS, 8 * key.size(), NULL);
|
||
|
- q_EVP_CipherInit(&ctx, NULL,
|
||
|
+ q_EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC2_KEY_BITS, 8 * key.size(), NULL);
|
||
|
+
|
||
|
+#if QT_CONFIG(opensslv11)
|
||
|
+ // EVP_CipherInit in 1.1 resets the context thus making the calls above useless.
|
||
|
+ // We call EVP_CipherInit_ex instead.
|
||
|
+ q_EVP_CipherInit_ex(ctx, nullptr, nullptr,
|
||
|
+ reinterpret_cast<const unsigned char *>(key.constData()),
|
||
|
+ reinterpret_cast<const unsigned char *>(iv.constData()),
|
||
|
+ enc);
|
||
|
+#else
|
||
|
+ q_EVP_CipherInit(ctx, NULL,
|
||
|
reinterpret_cast<const unsigned char *>(key.constData()),
|
||
|
reinterpret_cast<const unsigned char *>(iv.constData()), enc);
|
||
|
- q_EVP_CipherUpdate(&ctx,
|
||
|
+#endif // opensslv11
|
||
|
+
|
||
|
+ q_EVP_CipherUpdate(ctx,
|
||
|
reinterpret_cast<unsigned char *>(output.data()), &len,
|
||
|
reinterpret_cast<const unsigned char *>(data.constData()), data.size());
|
||
|
- q_EVP_CipherFinal(&ctx,
|
||
|
+ q_EVP_CipherFinal(ctx,
|
||
|
reinterpret_cast<unsigned char *>(output.data()) + len, &i);
|
||
|
len += i;
|
||
|
- q_EVP_CIPHER_CTX_cleanup(&ctx);
|
||
|
+
|
||
|
+#if QT_CONFIG(opensslv11)
|
||
|
+ q_EVP_CIPHER_CTX_reset(ctx);
|
||
|
+ q_EVP_CIPHER_CTX_free(ctx);
|
||
|
+#else
|
||
|
+ q_EVP_CIPHER_CTX_cleanup(ctx);
|
||
|
+#endif
|
||
|
|
||
|
return output.left(len);
|
||
|
}
|
||
|
diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp
|
||
|
index ab82cdc..c838e01 100644
|
||
|
--- a/src/network/ssl/qsslsocket_openssl.cpp
|
||
|
+++ b/src/network/ssl/qsslsocket_openssl.cpp
|
||
|
@@ -1,6 +1,6 @@
|
||
|
/****************************************************************************
|
||
|
**
|
||
|
-** Copyright (C) 2016 The Qt Company Ltd.
|
||
|
+** Copyright (C) 2017 The Qt Company Ltd.
|
||
|
** Copyright (C) 2014 Governikus GmbH & Co. KG
|
||
|
** Contact: https://www.qt.io/licensing/
|
||
|
**
|
||
|
@@ -97,70 +97,6 @@ bool QSslSocketPrivate::s_loadRootCertsOnDemand = false;
|
||
|
int QSslSocketBackendPrivate::s_indexForSSLExtraData = -1;
|
||
|
#endif
|
||
|
|
||
|
-/* \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:
|
||
|
- inline 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 *));
|
||
|
- }
|
||
|
- inline ~QOpenSslLocks()
|
||
|
- {
|
||
|
- QMutexLocker locker(&locksLocker);
|
||
|
- for (int i = 0; i < q_CRYPTO_num_locks(); ++i)
|
||
|
- delete locks[i];
|
||
|
- delete [] locks;
|
||
|
-
|
||
|
- QSslSocketPrivate::deinitialize();
|
||
|
- }
|
||
|
- inline 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)
|
||
|
-
|
||
|
QString QSslSocketBackendPrivate::getErrorsFromOpenSsl()
|
||
|
{
|
||
|
QString errorString;
|
||
|
@@ -175,20 +111,6 @@ QString QSslSocketBackendPrivate::getErrorsFromOpenSsl()
|
||
|
}
|
||
|
|
||
|
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();
|
||
|
-}
|
||
|
|
||
|
#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
|
||
|
static unsigned int q_ssl_psk_client_callback(SSL *ssl,
|
||
|
@@ -227,7 +149,7 @@ QSslSocketBackendPrivate::~QSslSocketBackendPrivate()
|
||
|
destroySslContext();
|
||
|
}
|
||
|
|
||
|
-QSslCipher QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(SSL_CIPHER *cipher)
|
||
|
+QSslCipher QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(const SSL_CIPHER *cipher)
|
||
|
{
|
||
|
QSslCipher ciph;
|
||
|
|
||
|
@@ -283,6 +205,7 @@ struct QSslErrorList
|
||
|
QMutex mutex;
|
||
|
QVector<QSslErrorEntry> errors;
|
||
|
};
|
||
|
+
|
||
|
Q_GLOBAL_STATIC(QSslErrorList, _q_sslErrorList)
|
||
|
|
||
|
int q_X509Callback(int ok, X509_STORE_CTX *ctx)
|
||
|
@@ -312,7 +235,7 @@ int q_X509Callback(int ok, X509_STORE_CTX *ctx)
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
- // Always return OK to allow verification to continue. We're handle the
|
||
|
+ // Always return OK to allow verification to continue. We handle the
|
||
|
// errors gracefully after collecting all errors, after verification has
|
||
|
// completed.
|
||
|
return 1;
|
||
|
@@ -397,7 +320,7 @@ bool QSslSocketBackendPrivate::initSslContext()
|
||
|
if (configuration.protocol != QSsl::SslV2 &&
|
||
|
configuration.protocol != QSsl::SslV3 &&
|
||
|
configuration.protocol != QSsl::UnknownProtocol &&
|
||
|
- mode == QSslSocket::SslClientMode && q_SSLeay() >= 0x00090806fL) {
|
||
|
+ mode == QSslSocket::SslClientMode && QSslSocket::sslLibraryVersionNumber() >= 0x00090806fL) {
|
||
|
// Set server hostname on TLS extension. RFC4366 section 3.1 requires it in ACE format.
|
||
|
QString tlsHostName = verificationPeerName.isEmpty() ? q->peerName() : verificationPeerName;
|
||
|
if (tlsHostName.isEmpty())
|
||
|
@@ -438,13 +361,13 @@ bool QSslSocketBackendPrivate::initSslContext()
|
||
|
|
||
|
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
|
||
|
// Save a pointer to this object into the SSL structure.
|
||
|
- if (q_SSLeay() >= 0x10001000L)
|
||
|
+ if (QSslSocket::sslLibraryVersionNumber() >= 0x10001000L)
|
||
|
q_SSL_set_ex_data(ssl, s_indexForSSLExtraData, this);
|
||
|
#endif
|
||
|
|
||
|
#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
|
||
|
// Set the client callback for PSK
|
||
|
- if (q_SSLeay() >= 0x10001000L) {
|
||
|
+ if (QSslSocket::sslLibraryVersionNumber() >= 0x10001000L) {
|
||
|
if (mode == QSslSocket::SslClientMode)
|
||
|
q_SSL_set_psk_client_callback(ssl, &q_ssl_psk_client_callback);
|
||
|
else if (mode == QSslSocket::SslServerMode)
|
||
|
@@ -466,16 +389,6 @@ void QSslSocketBackendPrivate::destroySslContext()
|
||
|
|
||
|
/*!
|
||
|
\internal
|
||
|
-*/
|
||
|
-void QSslSocketPrivate::deinitialize()
|
||
|
-{
|
||
|
- q_CRYPTO_set_id_callback(0);
|
||
|
- q_CRYPTO_set_locking_callback(0);
|
||
|
- q_ERR_free_strings();
|
||
|
-}
|
||
|
-
|
||
|
-/*!
|
||
|
- \internal
|
||
|
|
||
|
Does the minimum amount of initialization to determine whether SSL
|
||
|
is supported or not.
|
||
|
@@ -486,91 +399,6 @@ bool QSslSocketPrivate::supportsSsl()
|
||
|
return ensureLibraryLoaded();
|
||
|
}
|
||
|
|
||
|
-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) {
|
||
|
- s_libraryLoaded = true;
|
||
|
-
|
||
|
- // 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();
|
||
|
-
|
||
|
-#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;
|
||
|
- }
|
||
|
- }
|
||
|
- 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_WIN)
|
||
|
- HINSTANCE hLib = LoadLibraryW(L"Crypt32");
|
||
|
- if (hLib) {
|
||
|
- ptrCertOpenSystemStoreW = (PtrCertOpenSystemStoreW)GetProcAddress(hLib, "CertOpenSystemStoreW");
|
||
|
- ptrCertFindCertificateInStore = (PtrCertFindCertificateInStore)GetProcAddress(hLib, "CertFindCertificateInStore");
|
||
|
- ptrCertCloseStore = (PtrCertCloseStore)GetProcAddress(hLib, "CertCloseStore");
|
||
|
- if (!ptrCertOpenSystemStoreW || !ptrCertFindCertificateInStore || !ptrCertCloseStore)
|
||
|
- qCWarning(lcSsl, "could not resolve symbols in crypt32 library"); // should never happen
|
||
|
- } else {
|
||
|
- qCWarning(lcSsl, "could not load crypt32 library"); // should never happen
|
||
|
- }
|
||
|
-#elif defined(Q_OS_QNX)
|
||
|
- s_loadRootCertsOnDemand = true;
|
||
|
-#elif defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
|
||
|
- // 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.
|
||
|
- if ((QSysInfo::windowsVersion() & QSysInfo::WV_NT_based) >= QSysInfo::WV_6_0)
|
||
|
- s_loadRootCertsOnDemand = true;
|
||
|
-#endif
|
||
|
-}
|
||
|
|
||
|
/*!
|
||
|
\internal
|
||
|
@@ -587,26 +415,6 @@ void QSslSocketPrivate::ensureInitialized()
|
||
|
ensureCiphersAndCertsLoaded();
|
||
|
}
|
||
|
|
||
|
-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);
|
||
|
-}
|
||
|
-
|
||
|
long QSslSocketPrivate::sslLibraryBuildVersionNumber()
|
||
|
{
|
||
|
return OPENSSL_VERSION_NUMBER;
|
||
|
@@ -628,7 +436,11 @@ QString QSslSocketPrivate::sslLibraryBuildVersionString()
|
||
|
*/
|
||
|
void QSslSocketPrivate::resetDefaultCiphers()
|
||
|
{
|
||
|
+#if QT_CONFIG(opensslv11)
|
||
|
+ SSL_CTX *myCtx = q_SSL_CTX_new(q_TLS_client_method());
|
||
|
+#else
|
||
|
SSL_CTX *myCtx = q_SSL_CTX_new(q_SSLv23_client_method());
|
||
|
+#endif
|
||
|
SSL *mySsl = q_SSL_new(myCtx);
|
||
|
|
||
|
QList<QSslCipher> ciphers;
|
||
|
@@ -664,7 +476,7 @@ void QSslSocketPrivate::resetDefaultEllipticCurves()
|
||
|
QVector<QSslEllipticCurve> curves;
|
||
|
|
||
|
#ifndef OPENSSL_NO_EC
|
||
|
- const size_t curveCount = q_EC_get_builtin_curves(NULL, 0);
|
||
|
+ const size_t curveCount = q_EC_get_builtin_curves(nullptr, 0);
|
||
|
|
||
|
QVarLengthArray<EC_builtin_curve> builtinCurves(static_cast<int>(curveCount));
|
||
|
|
||
|
@@ -698,13 +510,14 @@ QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates()
|
||
|
if (ptrCertOpenSystemStoreW && ptrCertFindCertificateInStore && ptrCertCloseStore) {
|
||
|
HCERTSTORE hSystemStore;
|
||
|
hSystemStore = ptrCertOpenSystemStoreW(0, L"ROOT");
|
||
|
- if(hSystemStore) {
|
||
|
- PCCERT_CONTEXT pc = NULL;
|
||
|
- while(1) {
|
||
|
- pc = ptrCertFindCertificateInStore( hSystemStore, X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, pc);
|
||
|
- if(!pc)
|
||
|
+ if (hSystemStore) {
|
||
|
+ PCCERT_CONTEXT pc = nullptr;
|
||
|
+ while (1) {
|
||
|
+ pc = ptrCertFindCertificateInStore(hSystemStore, X509_ASN_ENCODING, 0, CERT_FIND_ANY, nullptr, pc);
|
||
|
+ if (!pc)
|
||
|
break;
|
||
|
- QByteArray der((const char *)(pc->pbCertEncoded), static_cast<int>(pc->cbCertEncoded));
|
||
|
+ QByteArray der(reinterpret_cast<const char *>(pc->pbCertEncoded),
|
||
|
+ static_cast<int>(pc->cbCertEncoded));
|
||
|
QSslCertificate cert(der, QSsl::Der);
|
||
|
systemCerts.append(cert);
|
||
|
}
|
||
|
@@ -1502,14 +1315,8 @@ QSslCipher QSslSocketBackendPrivate::sessionCipher() const
|
||
|
{
|
||
|
if (!ssl)
|
||
|
return QSslCipher();
|
||
|
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
|
||
|
- // FIXME This is fairly evil, but needed to keep source level compatibility
|
||
|
- // with the OpenSSL 0.9.x implementation at maximum -- some other functions
|
||
|
- // don't take a const SSL_CIPHER* when they should
|
||
|
- SSL_CIPHER *sessionCipher = const_cast<SSL_CIPHER *>(q_SSL_get_current_cipher(ssl));
|
||
|
-#else
|
||
|
- SSL_CIPHER *sessionCipher = q_SSL_get_current_cipher(ssl);
|
||
|
-#endif
|
||
|
+
|
||
|
+ const SSL_CIPHER *sessionCipher = q_SSL_get_current_cipher(ssl);
|
||
|
return sessionCipher ? QSslCipher_from_SSL_CIPHER(sessionCipher) : QSslCipher();
|
||
|
}
|
||
|
|
||
|
@@ -1535,112 +1342,6 @@ QSsl::SslProtocol QSslSocketBackendPrivate::sessionProtocol() const
|
||
|
return QSsl::UnknownProtocol;
|
||
|
}
|
||
|
|
||
|
-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();
|
||
|
- }
|
||
|
-}
|
||
|
-
|
||
|
QList<QSslCertificate> QSslSocketBackendPrivate::STACKOFX509_to_QSslCertificates(STACK_OF(X509) *x509)
|
||
|
{
|
||
|
ensureInitialized();
|
||
|
@@ -1694,12 +1395,12 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> &
|
||
|
QMutexLocker sslErrorListMutexLocker(&_q_sslErrorList()->mutex);
|
||
|
|
||
|
// Register a custom callback to get all verification errors.
|
||
|
- X509_STORE_set_verify_cb_func(certStore, q_X509Callback);
|
||
|
+ q_X509_STORE_set_verify_cb(certStore, q_X509Callback);
|
||
|
|
||
|
// Build the chain of intermediate certificates
|
||
|
STACK_OF(X509) *intermediates = 0;
|
||
|
if (certificateChain.length() > 1) {
|
||
|
- intermediates = (STACK_OF(X509) *) q_sk_new_null();
|
||
|
+ intermediates = (STACK_OF(X509) *) q_OPENSSL_sk_new_null();
|
||
|
|
||
|
if (!intermediates) {
|
||
|
q_X509_STORE_free(certStore);
|
||
|
@@ -1713,11 +1414,8 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> &
|
||
|
first = false;
|
||
|
continue;
|
||
|
}
|
||
|
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
|
||
|
- q_sk_push( (_STACK *)intermediates, reinterpret_cast<X509 *>(cert.handle()));
|
||
|
-#else
|
||
|
- q_sk_push( (STACK *)intermediates, reinterpret_cast<char *>(cert.handle()));
|
||
|
-#endif
|
||
|
+
|
||
|
+ q_OPENSSL_sk_push((OPENSSL_STACK *)intermediates, reinterpret_cast<X509 *>(cert.handle()));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@@ -1741,11 +1439,7 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> &
|
||
|
(void) q_X509_verify_cert(storeContext);
|
||
|
|
||
|
q_X509_STORE_CTX_free(storeContext);
|
||
|
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
|
||
|
- q_sk_free( (_STACK *) intermediates);
|
||
|
-#else
|
||
|
- q_sk_free( (STACK *) intermediates);
|
||
|
-#endif
|
||
|
+ q_OPENSSL_sk_free((OPENSSL_STACK *)intermediates);
|
||
|
|
||
|
// Now process the errors
|
||
|
const auto errorList = std::move(_q_sslErrorList()->errors);
|
||
|
@@ -1819,7 +1513,8 @@ bool QSslSocketBackendPrivate::importPkcs12(QIODevice *device,
|
||
|
// Convert to Qt types
|
||
|
if (!key->d->fromEVP_PKEY(pkey)) {
|
||
|
qCWarning(lcSsl, "Unable to convert private key");
|
||
|
- q_sk_pop_free(reinterpret_cast<STACK *>(ca), reinterpret_cast<void(*)(void*)>(q_sk_free));
|
||
|
+ q_OPENSSL_sk_pop_free(reinterpret_cast<OPENSSL_STACK *>(ca),
|
||
|
+ reinterpret_cast<void (*)(void *)>(q_OPENSSL_sk_free));
|
||
|
q_X509_free(x509);
|
||
|
q_EVP_PKEY_free(pkey);
|
||
|
q_PKCS12_free(p12);
|
||
|
@@ -1834,7 +1529,11 @@ bool QSslSocketBackendPrivate::importPkcs12(QIODevice *device,
|
||
|
*caCertificates = QSslSocketBackendPrivate::STACKOFX509_to_QSslCertificates(ca);
|
||
|
|
||
|
// Clean up
|
||
|
- q_sk_pop_free(reinterpret_cast<STACK *>(ca), reinterpret_cast<void(*)(void*)>(q_sk_free));
|
||
|
+ // TODO: verify ASAP, in the past we had sk_pop_free with q_OPENSSL_sk_free
|
||
|
+ // which seems to be blatantly wrong and even crashes with 1.1.
|
||
|
+ q_OPENSSL_sk_pop_free(reinterpret_cast<OPENSSL_STACK *>(ca),
|
||
|
+ reinterpret_cast<void (*)(void *)>(q_X509_free));
|
||
|
+
|
||
|
q_X509_free(x509);
|
||
|
q_EVP_PKEY_free(pkey);
|
||
|
q_PKCS12_free(p12);
|
||
|
diff --git a/src/network/ssl/qsslsocket_openssl11.cpp b/src/network/ssl/qsslsocket_openssl11.cpp
|
||
|
new file mode 100644
|
||
|
index 0000000..b6d1894
|
||
|
--- /dev/null
|
||
|
+++ b/src/network/ssl/qsslsocket_openssl11.cpp
|
||
|
@@ -0,0 +1,285 @@
|
||
|
+/****************************************************************************
|
||
|
+**
|
||
|
+** Copyright (C) 2017 The Qt Company Ltd.
|
||
|
+** Copyright (C) 2014 Governikus GmbH & Co. KG
|
||
|
+** Copyright (C) 2016 Richard J. Moore <rich@kde.org>
|
||
|
+** 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/qfile.h>
|
||
|
+#include <QtCore/qmutex.h>
|
||
|
+#include <QtCore/qlibrary.h>
|
||
|
+
|
||
|
+QT_BEGIN_NAMESPACE
|
||
|
+
|
||
|
+Q_GLOBAL_STATIC_WITH_ARGS(QMutex, qt_opensslInitMutex, (QMutex::Recursive))
|
||
|
+
|
||
|
+/*!
|
||
|
+ \internal
|
||
|
+*/
|
||
|
+void QSslSocketPrivate::deinitialize()
|
||
|
+{
|
||
|
+ // This function exists only for compatibility with the pre-11 code,
|
||
|
+ // where deinitialize() actually does some cleanup. To be discarded
|
||
|
+ // once we retire < 1.1.
|
||
|
+}
|
||
|
+
|
||
|
+bool QSslSocketPrivate::ensureLibraryLoaded()
|
||
|
+{
|
||
|
+ if (!q_resolveOpenSslSymbols())
|
||
|
+ return false;
|
||
|
+
|
||
|
+ const QMutexLocker locker(qt_opensslInitMutex);
|
||
|
+
|
||
|
+ if (!s_libraryLoaded) {
|
||
|
+ s_libraryLoaded = true;
|
||
|
+
|
||
|
+ // Initialize OpenSSL.
|
||
|
+ if (q_OPENSSL_init_ssl(0, nullptr) != 1)
|
||
|
+ return false;
|
||
|
+ q_SSL_load_error_strings();
|
||
|
+ q_OpenSSL_add_all_algorithms();
|
||
|
+
|
||
|
+ QSslSocketBackendPrivate::s_indexForSSLExtraData
|
||
|
+ = q_CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, 0L, nullptr, nullptr,
|
||
|
+ nullptr, nullptr);
|
||
|
+
|
||
|
+ // Initialize OpenSSL's random seed.
|
||
|
+ if (!q_RAND_status()) {
|
||
|
+ qWarning("Random number generator not seeded, disabling SSL support");
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ return true;
|
||
|
+}
|
||
|
+
|
||
|
+void QSslSocketPrivate::ensureCiphersAndCertsLoaded()
|
||
|
+{
|
||
|
+ const QMutexLocker locker(qt_opensslInitMutex);
|
||
|
+
|
||
|
+ 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_WIN)
|
||
|
+ HINSTANCE hLib = LoadLibraryW(L"Crypt32");
|
||
|
+ if (hLib) {
|
||
|
+ ptrCertOpenSystemStoreW = (PtrCertOpenSystemStoreW)GetProcAddress(hLib, "CertOpenSystemStoreW");
|
||
|
+ ptrCertFindCertificateInStore = (PtrCertFindCertificateInStore)GetProcAddress(hLib, "CertFindCertificateInStore");
|
||
|
+ ptrCertCloseStore = (PtrCertCloseStore)GetProcAddress(hLib, "CertCloseStore");
|
||
|
+ if (!ptrCertOpenSystemStoreW || !ptrCertFindCertificateInStore || !ptrCertCloseStore)
|
||
|
+ qCWarning(lcSsl, "could not resolve symbols in crypt32 library"); // should never happen
|
||
|
+ } else {
|
||
|
+ qCWarning(lcSsl, "could not load crypt32 library"); // should never happen
|
||
|
+ }
|
||
|
+#elif defined(Q_OS_QNX)
|
||
|
+ s_loadRootCertsOnDemand = true;
|
||
|
+#elif defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
|
||
|
+ // 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.
|
||
|
+ if ((QSysInfo::windowsVersion() & QSysInfo::WV_NT_based) >= QSysInfo::WV_6_0)
|
||
|
+ s_loadRootCertsOnDemand = true;
|
||
|
+#endif
|
||
|
+}
|
||
|
+
|
||
|
+long QSslSocketPrivate::sslLibraryVersionNumber()
|
||
|
+{
|
||
|
+ if (!supportsSsl())
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ return q_OpenSSL_version_num();
|
||
|
+}
|
||
|
+
|
||
|
+QString QSslSocketPrivate::sslLibraryVersionString()
|
||
|
+{
|
||
|
+ if (!supportsSsl())
|
||
|
+ return QString();
|
||
|
+
|
||
|
+ const char *versionString = q_OpenSSL_version(OPENSSL_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_session_reused(ssl))
|
||
|
+ configuration.peerSessionShared = true;
|
||
|
+
|
||
|
+#ifdef QT_DECRYPT_SSL_TRAFFIC
|
||
|
+ if (q_SSL_get_session(ssl)) {
|
||
|
+ size_t master_key_len = q_SSL_SESSION_get_master_key(q_SSL_get_session(ssl), 0, 0);
|
||
|
+ size_t client_random_len = q_SSL_get_client_random(ssl, 0, 0);
|
||
|
+ QByteArray masterKey(int(master_key_len), 0); // Will not overflow
|
||
|
+ QByteArray clientRandom(int(client_random_len), 0); // Will not overflow
|
||
|
+
|
||
|
+ q_SSL_SESSION_get_master_key(q_SSL_get_session(ssl),
|
||
|
+ reinterpret_cast<unsigned char*>(masterKey.data()),
|
||
|
+ masterKey.size());
|
||
|
+ q_SSL_get_client_random(ssl, reinterpret_cast<unsigned char *>(clientRandom.data()),
|
||
|
+ clientRandom.size());
|
||
|
+
|
||
|
+ 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 !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;
|
||
|
+
|
||
|
+ 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 ...
|
||
|
+ 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 // !defined(OPENSSL_NO_NEXTPROTONEG)
|
||
|
+
|
||
|
+ if (mode == QSslSocket::SslClientMode) {
|
||
|
+ EVP_PKEY *key;
|
||
|
+ if (q_SSL_get_server_tmp_key(ssl, &key))
|
||
|
+ configuration.ephemeralServerKey = QSslKey(key, QSsl::PublicKey);
|
||
|
+ }
|
||
|
+
|
||
|
+ connectionEncrypted = true;
|
||
|
+ emit q->encrypted();
|
||
|
+ if (autoStartHandshake && pendingClose) {
|
||
|
+ pendingClose = false;
|
||
|
+ q->disconnectFromHost();
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+QT_END_NAMESPACE
|
||
|
diff --git a/src/network/ssl/qsslsocket_openssl11_symbols_p.h b/src/network/ssl/qsslsocket_openssl11_symbols_p.h
|
||
|
new file mode 100644
|
||
|
index 0000000..2980b3d
|
||
|
--- /dev/null
|
||
|
+++ b/src/network/ssl/qsslsocket_openssl11_symbols_p.h
|
||
|
@@ -0,0 +1,132 @@
|
||
|
+/****************************************************************************
|
||
|
+**
|
||
|
+** Copyright (C) 2017 The Qt Company Ltd.
|
||
|
+** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
|
||
|
+** Copyright (C) 2016 Richard J. Moore <rich@kde.org>
|
||
|
+** 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.
|
||
|
+**
|
||
|
+****************************************************************************/
|
||
|
+
|
||
|
+#ifndef QSSLSOCKET_OPENSSL11_SYMBOLS_P_H
|
||
|
+#define QSSLSOCKET_OPENSSL11_SYMBOLS_P_H
|
||
|
+
|
||
|
+//
|
||
|
+// W A R N I N G
|
||
|
+// -------------
|
||
|
+//
|
||
|
+// This file is not part of the Qt API. It exists purely as an
|
||
|
+// implementation detail. This header file may change from version to
|
||
|
+// version without notice, or even be removed.
|
||
|
+//
|
||
|
+// We mean it.
|
||
|
+//
|
||
|
+
|
||
|
+// Note: this file does not have QT_BEGIN_NAMESPACE/QT_END_NAMESPACE, it's done
|
||
|
+// in qsslsocket_openssl_symbols_p.h.
|
||
|
+
|
||
|
+#ifndef QSSLSOCKET_OPENSSL_SYMBOLS_P_H
|
||
|
+#error "You are not supposed to use this header file, include qsslsocket_openssl_symbols_p.h instead"
|
||
|
+#endif
|
||
|
+
|
||
|
+const unsigned char * q_ASN1_STRING_get0_data(const ASN1_STRING *x);
|
||
|
+
|
||
|
+Q_AUTOTEST_EXPORT BIO *q_BIO_new(const BIO_METHOD *a);
|
||
|
+Q_AUTOTEST_EXPORT const BIO_METHOD *q_BIO_s_mem();
|
||
|
+
|
||
|
+int q_DSA_bits(DSA *a);
|
||
|
+int q_EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *c);
|
||
|
+int q_EVP_PKEY_base_id(EVP_PKEY *a);
|
||
|
+int q_RSA_bits(RSA *a);
|
||
|
+int q_OPENSSL_sk_num(OPENSSL_STACK *a);
|
||
|
+void q_OPENSSL_sk_pop_free(OPENSSL_STACK *a, void (*b)(void *));
|
||
|
+OPENSSL_STACK *q_OPENSSL_sk_new_null();
|
||
|
+void q_OPENSSL_sk_push(OPENSSL_STACK *st, void *data);
|
||
|
+void q_OPENSSL_sk_free(OPENSSL_STACK *a);
|
||
|
+void * q_OPENSSL_sk_value(OPENSSL_STACK *a, int b);
|
||
|
+int q_SSL_session_reused(SSL *a);
|
||
|
+unsigned long q_SSL_CTX_set_options(SSL_CTX *ctx, unsigned long op);
|
||
|
+int q_OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings);
|
||
|
+size_t q_SSL_get_client_random(SSL *a, unsigned char *out, size_t outlen);
|
||
|
+size_t q_SSL_SESSION_get_master_key(const SSL_SESSION *session, unsigned char *out, size_t outlen);
|
||
|
+int q_CRYPTO_get_ex_new_index(int class_index, long argl, void *argp, CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
|
||
|
+const SSL_METHOD *q_TLS_method();
|
||
|
+const SSL_METHOD *q_TLS_client_method();
|
||
|
+const SSL_METHOD *q_TLS_server_method();
|
||
|
+ASN1_TIME *q_X509_getm_notBefore(X509 *a);
|
||
|
+ASN1_TIME *q_X509_getm_notAfter(X509 *a);
|
||
|
+
|
||
|
+long q_X509_get_version(X509 *a);
|
||
|
+EVP_PKEY *q_X509_get_pubkey(X509 *a);
|
||
|
+void q_X509_STORE_set_verify_cb(X509_STORE *ctx, X509_STORE_CTX_verify_cb verify_cb);
|
||
|
+STACK_OF(X509) *q_X509_STORE_CTX_get0_chain(X509_STORE_CTX *ctx);
|
||
|
+void q_DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g);
|
||
|
+int q_DH_bits(DH *dh);
|
||
|
+
|
||
|
+# define q_SSL_load_error_strings() q_OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS \
|
||
|
+ | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL)
|
||
|
+
|
||
|
+#define q_SKM_sk_num(type, st) ((int (*)(const STACK_OF(type) *))q_OPENSSL_sk_num)(st)
|
||
|
+#define q_SKM_sk_value(type, st,i) ((type * (*)(const STACK_OF(type) *, int))q_OPENSSL_sk_value)(st, i)
|
||
|
+
|
||
|
+#define q_OPENSSL_add_all_algorithms_conf() q_OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \
|
||
|
+ | OPENSSL_INIT_ADD_ALL_DIGESTS \
|
||
|
+ | OPENSSL_INIT_LOAD_CONFIG, NULL)
|
||
|
+#define q_OPENSSL_add_all_algorithms_noconf() q_OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \
|
||
|
+ | OPENSSL_INIT_ADD_ALL_DIGESTS, NULL)
|
||
|
+
|
||
|
+int q_OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings);
|
||
|
+void q_CRYPTO_free(void *str, const char *file, int line);
|
||
|
+
|
||
|
+long q_OpenSSL_version_num();
|
||
|
+const char *q_OpenSSL_version(int type);
|
||
|
+
|
||
|
+unsigned long q_SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *session);
|
||
|
+
|
||
|
+#endif
|
||
|
diff --git a/src/network/ssl/qsslsocket_openssl_p.h b/src/network/ssl/qsslsocket_openssl_p.h
|
||
|
index b2adb3e..7f9e884 100644
|
||
|
--- a/src/network/ssl/qsslsocket_openssl_p.h
|
||
|
+++ b/src/network/ssl/qsslsocket_openssl_p.h
|
||
|
@@ -1,6 +1,6 @@
|
||
|
/****************************************************************************
|
||
|
**
|
||
|
-** Copyright (C) 2016 The Qt Company Ltd.
|
||
|
+** Copyright (C) 2017 The Qt Company Ltd.
|
||
|
** Contact: https://www.qt.io/licensing/
|
||
|
**
|
||
|
** This file is part of the QtNetwork module of the Qt Toolkit.
|
||
|
@@ -98,8 +98,8 @@
|
||
|
#include <openssl/crypto.h>
|
||
|
#include <openssl/tls1.h>
|
||
|
|
||
|
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
|
||
|
-typedef _STACK STACK;
|
||
|
+#if QT_CONFIG(opensslv11)
|
||
|
+#include <openssl/dh.h>
|
||
|
#endif
|
||
|
|
||
|
QT_BEGIN_NAMESPACE
|
||
|
@@ -151,7 +151,7 @@ public:
|
||
|
#endif
|
||
|
|
||
|
Q_AUTOTEST_EXPORT static long setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions);
|
||
|
- static QSslCipher QSslCipher_from_SSL_CIPHER(SSL_CIPHER *cipher);
|
||
|
+ static QSslCipher QSslCipher_from_SSL_CIPHER(const SSL_CIPHER *cipher);
|
||
|
static QList<QSslCertificate> STACKOFX509_to_QSslCertificates(STACK_OF(X509) *x509);
|
||
|
static QList<QSslError> verify(const QList<QSslCertificate> &certificateChain, const QString &hostName);
|
||
|
static QString getErrorsFromOpenSsl();
|
||
|
diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp
|
||
|
index c344a94..0ef8bf6 100644
|
||
|
--- a/src/network/ssl/qsslsocket_openssl_symbols.cpp
|
||
|
+++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp
|
||
|
@@ -1,7 +1,8 @@
|
||
|
/****************************************************************************
|
||
|
**
|
||
|
-** Copyright (C) 2016 The Qt Company Ltd.
|
||
|
+** Copyright (C) 2017 The Qt Company Ltd.
|
||
|
** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
|
||
|
+** Copyright (C) 2016 Richard J. Moore <rich@kde.org>
|
||
|
** Contact: https://www.qt.io/licensing/
|
||
|
**
|
||
|
** This file is part of the QtNetwork module of the Qt Toolkit.
|
||
|
@@ -136,49 +137,195 @@ void qsslSocketCannotResolveSymbolWarning(const char *functionName)
|
||
|
|
||
|
#endif // QT_LINKED_OPENSSL
|
||
|
|
||
|
+#if QT_CONFIG(opensslv11)
|
||
|
+
|
||
|
+// Below are the functions first introduced in version 1.1:
|
||
|
+
|
||
|
+DEFINEFUNC(const unsigned char *, ASN1_STRING_get0_data, const ASN1_STRING *a, a, return 0, return)
|
||
|
+DEFINEFUNC2(int, OPENSSL_init_ssl, uint64_t opts, opts, const OPENSSL_INIT_SETTINGS *settings, settings, return 0, return)
|
||
|
+DEFINEFUNC2(int, OPENSSL_init_crypto, uint64_t opts, opts, const OPENSSL_INIT_SETTINGS *settings, settings, return 0, return)
|
||
|
+DEFINEFUNC(BIO *, BIO_new, const BIO_METHOD *a, a, return 0, return)
|
||
|
+DEFINEFUNC(const BIO_METHOD *, BIO_s_mem, void, DUMMYARG, return 0, return)
|
||
|
+DEFINEFUNC2(int, BN_is_word, BIGNUM *a, a, BN_ULONG w, w, return 0, return)
|
||
|
+DEFINEFUNC(int, EVP_CIPHER_CTX_reset, EVP_CIPHER_CTX *c, c, return 0, return)
|
||
|
+DEFINEFUNC(int, EVP_PKEY_base_id, EVP_PKEY *a, a, return NID_undef, return)
|
||
|
+DEFINEFUNC(int, RSA_bits, RSA *a, a, return 0, return)
|
||
|
+DEFINEFUNC(int, DSA_bits, DSA *a, a, return 0, return)
|
||
|
+DEFINEFUNC(int, OPENSSL_sk_num, OPENSSL_STACK *a, a, return -1, return)
|
||
|
+DEFINEFUNC2(void, OPENSSL_sk_pop_free, OPENSSL_STACK *a, a, void (*b)(void*), b, return, DUMMYARG)
|
||
|
+DEFINEFUNC(OPENSSL_STACK *, OPENSSL_sk_new_null, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
+DEFINEFUNC2(void, OPENSSL_sk_push, OPENSSL_STACK *a, a, void *b, b, return, DUMMYARG)
|
||
|
+DEFINEFUNC(void, OPENSSL_sk_free, OPENSSL_STACK *a, a, return, DUMMYARG)
|
||
|
+DEFINEFUNC2(void *, OPENSSL_sk_value, OPENSSL_STACK *a, a, int b, b, return 0, return)
|
||
|
+DEFINEFUNC(int, SSL_session_reused, SSL *a, a, return 0, return)
|
||
|
+DEFINEFUNC2(unsigned long, SSL_CTX_set_options, SSL_CTX *ctx, ctx, unsigned long op, op, return 0, return)
|
||
|
+DEFINEFUNC3(size_t, SSL_get_client_random, SSL *a, a, unsigned char *out, out, size_t outlen, outlen, return 0, return)
|
||
|
+DEFINEFUNC3(size_t, SSL_SESSION_get_master_key, const SSL_SESSION *ses, ses, unsigned char *out, out, size_t outlen, outlen, return 0, return)
|
||
|
+DEFINEFUNC6(int, CRYPTO_get_ex_new_index, int class_index, class_index, long argl, argl, void *argp, argp, CRYPTO_EX_new *new_func, new_func, CRYPTO_EX_dup *dup_func, dup_func, CRYPTO_EX_free *free_func, free_func, return -1, return)
|
||
|
+
|
||
|
+DEFINEFUNC(const SSL_METHOD *, TLS_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
+DEFINEFUNC(const SSL_METHOD *, TLS_client_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
+DEFINEFUNC(const SSL_METHOD *, TLS_server_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
+DEFINEFUNC(ASN1_TIME *, X509_getm_notBefore, X509 *a, a, return 0, return)
|
||
|
+DEFINEFUNC(ASN1_TIME *, X509_getm_notAfter, X509 *a, a, return 0, return)
|
||
|
+DEFINEFUNC(long, X509_get_version, X509 *a, a, return -1, return)
|
||
|
+DEFINEFUNC(EVP_PKEY *, X509_get_pubkey, X509 *a, a, return 0, return)
|
||
|
+DEFINEFUNC2(void, X509_STORE_set_verify_cb, X509_STORE *a, a, X509_STORE_CTX_verify_cb verify_cb, verify_cb, return, DUMMYARG)
|
||
|
+DEFINEFUNC(STACK_OF(X509) *, X509_STORE_CTX_get0_chain, X509_STORE_CTX *a, a, return 0, return)
|
||
|
+DEFINEFUNC3(void, CRYPTO_free, void *str, str, const char *file, file, int line, line, return, DUMMYARG)
|
||
|
+DEFINEFUNC(long, OpenSSL_version_num, void, DUMMYARG, return 0, return)
|
||
|
+DEFINEFUNC(const char *, OpenSSL_version, int a, a, return 0, return)
|
||
|
+DEFINEFUNC(unsigned long, SSL_SESSION_get_ticket_lifetime_hint, const SSL_SESSION *session, session, return 0, return)
|
||
|
+DEFINEFUNC4(void, DH_get0_pqg, const DH *dh, dh, const BIGNUM **p, p, const BIGNUM **q, q, const BIGNUM **g, g, return, DUMMYARG)
|
||
|
+DEFINEFUNC(int, DH_bits, DH *dh, dh, return 0, return)
|
||
|
+
|
||
|
+#else // QT_CONFIG(opensslv11)
|
||
|
+
|
||
|
+// Functions below are either deprecated or removed in OpenSSL >= 1.1:
|
||
|
+
|
||
|
+DEFINEFUNC(unsigned char *, ASN1_STRING_data, ASN1_STRING *a, a, return 0, return)
|
||
|
+
|
||
|
#ifdef SSLEAY_MACROS
|
||
|
DEFINEFUNC3(void *, ASN1_dup, i2d_of_void *a, a, d2i_of_void *b, b, char *c, c, return 0, return)
|
||
|
#endif
|
||
|
+DEFINEFUNC2(BIO *, BIO_new_file, const char *filename, filename, const char *mode, mode, return 0, return)
|
||
|
+DEFINEFUNC(void, ERR_clear_error, DUMMYARG, DUMMYARG, return, DUMMYARG)
|
||
|
+DEFINEFUNC(BIO *, BIO_new, BIO_METHOD *a, a, return 0, return)
|
||
|
+DEFINEFUNC(BIO_METHOD *, BIO_s_mem, void, DUMMYARG, return 0, return)
|
||
|
+DEFINEFUNC(int, CRYPTO_num_locks, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
+DEFINEFUNC(void, CRYPTO_set_locking_callback, void (*a)(int, int, const char *, int), a, return, DUMMYARG)
|
||
|
+DEFINEFUNC(void, CRYPTO_set_id_callback, unsigned long (*a)(), a, return, DUMMYARG)
|
||
|
+DEFINEFUNC(void, CRYPTO_free, void *a, a, return, DUMMYARG)
|
||
|
+DEFINEFUNC(unsigned long, ERR_peek_last_error, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
+DEFINEFUNC(void, ERR_free_strings, void, DUMMYARG, return, DUMMYARG)
|
||
|
+DEFINEFUNC(void, EVP_CIPHER_CTX_cleanup, EVP_CIPHER_CTX *a, a, return, DUMMYARG)
|
||
|
+DEFINEFUNC(void, EVP_CIPHER_CTX_init, EVP_CIPHER_CTX *a, a, return, DUMMYARG)
|
||
|
+
|
||
|
+#ifdef SSLEAY_MACROS
|
||
|
+DEFINEFUNC6(void *, PEM_ASN1_read_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return 0, return)
|
||
|
+DEFINEFUNC6(void *, PEM_ASN1_write_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return 0, return)
|
||
|
+#endif // SSLEAY_MACROS
|
||
|
+
|
||
|
+DEFINEFUNC(int, sk_num, STACK *a, a, return -1, return)
|
||
|
+DEFINEFUNC2(void, sk_pop_free, STACK *a, a, void (*b)(void*), b, return, DUMMYARG)
|
||
|
+
|
||
|
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
|
||
|
+DEFINEFUNC(_STACK *, sk_new_null, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
+DEFINEFUNC2(void, sk_push, _STACK *a, a, void *b, b, return, DUMMYARG)
|
||
|
+DEFINEFUNC(void, sk_free, _STACK *a, a, return, DUMMYARG)
|
||
|
+DEFINEFUNC2(void *, sk_value, STACK *a, a, int b, b, return 0, return)
|
||
|
+#else
|
||
|
+DEFINEFUNC(STACK *, sk_new_null, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
+DEFINEFUNC2(void, sk_push, STACK *a, a, char *b, b, return, DUMMYARG)
|
||
|
+DEFINEFUNC(void, sk_free, STACK *a, a, return, DUMMYARG)
|
||
|
+DEFINEFUNC2(char *, sk_value, STACK *a, a, int b, b, return 0, return)
|
||
|
+#endif // OPENSSL_VERSION_NUMBER >= 0x10000000L
|
||
|
+
|
||
|
+DEFINEFUNC(int, SSL_library_init, void, DUMMYARG, return -1, return)
|
||
|
+DEFINEFUNC(void, SSL_load_error_strings, void, DUMMYARG, return, DUMMYARG)
|
||
|
+
|
||
|
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
|
||
|
+DEFINEFUNC5(int, SSL_get_ex_new_index, long argl, argl, void *argp, argp, CRYPTO_EX_new *new_func, new_func, CRYPTO_EX_dup *dup_func, dup_func, CRYPTO_EX_free *free_func, free_func, return -1, return)
|
||
|
+#endif // OPENSSL_VERSION_NUMBER >= 0x10001000L
|
||
|
+
|
||
|
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
|
||
|
+#ifndef OPENSSL_NO_SSL2
|
||
|
+DEFINEFUNC(const SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
+#endif
|
||
|
+#ifndef OPENSSL_NO_SSL3_METHOD
|
||
|
+DEFINEFUNC(const SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
+#endif
|
||
|
+DEFINEFUNC(const SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
+DEFINEFUNC(const SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
|
||
|
+DEFINEFUNC(const SSL_METHOD *, TLSv1_1_client_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
+DEFINEFUNC(const SSL_METHOD *, TLSv1_2_client_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
+#endif
|
||
|
+#ifndef OPENSSL_NO_SSL2
|
||
|
+DEFINEFUNC(const SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
+#endif
|
||
|
+#ifndef OPENSSL_NO_SSL3_METHOD
|
||
|
+DEFINEFUNC(const SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
+#endif
|
||
|
+DEFINEFUNC(const SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
+DEFINEFUNC(const SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
|
||
|
+DEFINEFUNC(const SSL_METHOD *, TLSv1_1_server_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
+DEFINEFUNC(const SSL_METHOD *, TLSv1_2_server_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
+#endif
|
||
|
+#else
|
||
|
+#ifndef OPENSSL_NO_SSL2
|
||
|
+DEFINEFUNC(SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
+#endif
|
||
|
+#ifndef OPENSSL_NO_SSL3_METHOD
|
||
|
+DEFINEFUNC(SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
+#endif
|
||
|
+DEFINEFUNC(SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
+DEFINEFUNC(SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
+#ifndef OPENSSL_NO_SSL2
|
||
|
+DEFINEFUNC(SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
+#endif
|
||
|
+#ifndef OPENSSL_NO_SSL3_METHOD
|
||
|
+DEFINEFUNC(SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
+#endif
|
||
|
+DEFINEFUNC(SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
+DEFINEFUNC(SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
+#endif
|
||
|
+
|
||
|
+DEFINEFUNC(STACK_OF(X509) *, X509_STORE_CTX_get_chain, X509_STORE_CTX *a, a, return 0, return)
|
||
|
+
|
||
|
+#ifdef SSLEAY_MACROS
|
||
|
+DEFINEFUNC2(int, i2d_DSAPrivateKey, const DSA *a, a, unsigned char **b, b, return -1, return)
|
||
|
+DEFINEFUNC2(int, i2d_RSAPrivateKey, const RSA *a, a, unsigned char **b, b, return -1, return)
|
||
|
+#ifndef OPENSSL_NO_EC
|
||
|
+DEFINEFUNC2(int, i2d_ECPrivateKey, const EC_KEY *a, a, unsigned char **b, b, return -1, return)
|
||
|
+#endif
|
||
|
+DEFINEFUNC3(RSA *, d2i_RSAPrivateKey, RSA **a, a, unsigned char **b, b, long c, c, return 0, return)
|
||
|
+DEFINEFUNC3(DSA *, d2i_DSAPrivateKey, DSA **a, a, unsigned char **b, b, long c, c, return 0, return)
|
||
|
+#ifndef OPENSSL_NO_EC
|
||
|
+DEFINEFUNC3(EC_KEY *, d2i_ECPrivateKey, EC_KEY **a, a, unsigned char **b, b, long c, c, return 0, return)
|
||
|
+#endif
|
||
|
+#endif
|
||
|
+DEFINEFUNC(char *, CONF_get1_default_config_file, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
+DEFINEFUNC(void, OPENSSL_add_all_algorithms_noconf, void, DUMMYARG, return, DUMMYARG)
|
||
|
+DEFINEFUNC(void, OPENSSL_add_all_algorithms_conf, void, DUMMYARG, return, DUMMYARG)
|
||
|
+DEFINEFUNC(long, SSLeay, void, DUMMYARG, return 0, return)
|
||
|
+DEFINEFUNC(const char *, SSLeay_version, int a, a, return 0, return)
|
||
|
+
|
||
|
+#endif // QT_CONFIG(opensslv11)
|
||
|
+
|
||
|
DEFINEFUNC(long, ASN1_INTEGER_get, ASN1_INTEGER *a, a, return 0, return)
|
||
|
-DEFINEFUNC(unsigned char *, ASN1_STRING_data, ASN1_STRING *a, a, return 0, return)
|
||
|
DEFINEFUNC(int, ASN1_STRING_length, ASN1_STRING *a, a, return 0, return)
|
||
|
-DEFINEFUNC2(int, ASN1_STRING_to_UTF8, unsigned char **a, a, ASN1_STRING *b, b, return 0, return);
|
||
|
+DEFINEFUNC2(int, ASN1_STRING_to_UTF8, unsigned char **a, a, ASN1_STRING *b, b, return 0, return)
|
||
|
DEFINEFUNC4(long, BIO_ctrl, BIO *a, a, int b, b, long c, c, void *d, d, return -1, return)
|
||
|
DEFINEFUNC(int, BIO_free, BIO *a, a, return 0, return)
|
||
|
-DEFINEFUNC(BIO *, BIO_new, BIO_METHOD *a, a, return 0, return)
|
||
|
DEFINEFUNC2(BIO *, BIO_new_mem_buf, void *a, a, int b, b, return 0, return)
|
||
|
DEFINEFUNC3(int, BIO_read, BIO *a, a, void *b, b, int c, c, return -1, return)
|
||
|
-DEFINEFUNC(BIO_METHOD *, BIO_s_mem, void, DUMMYARG, return 0, return)
|
||
|
+
|
||
|
DEFINEFUNC3(int, BIO_write, BIO *a, a, const void *b, b, int c, c, return -1, return)
|
||
|
DEFINEFUNC(int, BN_num_bits, const BIGNUM *a, a, return 0, return)
|
||
|
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||
|
-DEFINEFUNC2(int, BN_is_word, BIGNUM *a, a, BN_ULONG w, w, return 0, return)
|
||
|
-#endif
|
||
|
DEFINEFUNC2(BN_ULONG, BN_mod_word, const BIGNUM *a, a, BN_ULONG w, w, return static_cast<BN_ULONG>(-1), return)
|
||
|
#ifndef OPENSSL_NO_EC
|
||
|
DEFINEFUNC(const EC_GROUP*, EC_KEY_get0_group, const EC_KEY* k, k, return 0, return)
|
||
|
DEFINEFUNC(int, EC_GROUP_get_degree, const EC_GROUP* g, g, return 0, return)
|
||
|
#endif
|
||
|
-DEFINEFUNC(int, CRYPTO_num_locks, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
-DEFINEFUNC(void, CRYPTO_set_locking_callback, void (*a)(int, int, const char *, int), a, return, DUMMYARG)
|
||
|
-DEFINEFUNC(void, CRYPTO_set_id_callback, unsigned long (*a)(), a, return, DUMMYARG)
|
||
|
-DEFINEFUNC(void, CRYPTO_free, void *a, a, return, DUMMYARG)
|
||
|
DEFINEFUNC(DSA *, DSA_new, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
DEFINEFUNC(void, DSA_free, DSA *a, a, return, DUMMYARG)
|
||
|
DEFINEFUNC3(X509 *, d2i_X509, X509 **a, a, const unsigned char **b, b, long c, c, return 0, return)
|
||
|
DEFINEFUNC2(char *, ERR_error_string, unsigned long a, a, char *b, b, return 0, return)
|
||
|
DEFINEFUNC(unsigned long, ERR_get_error, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
-DEFINEFUNC(void, ERR_free_strings, void, DUMMYARG, return, DUMMYARG)
|
||
|
-DEFINEFUNC(void, EVP_CIPHER_CTX_cleanup, EVP_CIPHER_CTX *a, a, return, DUMMYARG)
|
||
|
-DEFINEFUNC(void, EVP_CIPHER_CTX_init, EVP_CIPHER_CTX *a, a, return, DUMMYARG)
|
||
|
-DEFINEFUNC4(int, EVP_CIPHER_CTX_ctrl, EVP_CIPHER_CTX *ctx, ctx, int type, type, int arg, arg, void *ptr, ptr, return 0, return);
|
||
|
+DEFINEFUNC(EVP_CIPHER_CTX *, EVP_CIPHER_CTX_new, void, DUMMYARG, return 0, return)
|
||
|
+DEFINEFUNC(void, EVP_CIPHER_CTX_free, EVP_CIPHER_CTX *a, a, return, DUMMYARG)
|
||
|
+DEFINEFUNC4(int, EVP_CIPHER_CTX_ctrl, EVP_CIPHER_CTX *ctx, ctx, int type, type, int arg, arg, void *ptr, ptr, return 0, return)
|
||
|
DEFINEFUNC2(int, EVP_CIPHER_CTX_set_key_length, EVP_CIPHER_CTX *ctx, ctx, int keylen, keylen, return 0, return)
|
||
|
-DEFINEFUNC5(int, EVP_CipherInit, EVP_CIPHER_CTX *ctx, ctx, const EVP_CIPHER *type, type, const unsigned char *key, key, const unsigned char *iv, iv, int enc, enc, return 0, return);
|
||
|
-DEFINEFUNC5(int, EVP_CipherUpdate, EVP_CIPHER_CTX *ctx, ctx, unsigned char *out, out, int *outl, outl, const unsigned char *in, in, int inl, inl, return 0, return);
|
||
|
-DEFINEFUNC3(int, EVP_CipherFinal, EVP_CIPHER_CTX *ctx, ctx, unsigned char *out, out, int *outl, outl, return 0, return);
|
||
|
+DEFINEFUNC5(int, EVP_CipherInit, EVP_CIPHER_CTX *ctx, ctx, const EVP_CIPHER *type, type, const unsigned char *key, key, const unsigned char *iv, iv, int enc, enc, return 0, return)
|
||
|
+DEFINEFUNC6(int, EVP_CipherInit_ex, EVP_CIPHER_CTX *ctx, ctx, const EVP_CIPHER *cipher, cipher, ENGINE *impl, impl, const unsigned char *key, key, const unsigned char *iv, iv, int enc, enc, return 0, return)
|
||
|
+DEFINEFUNC5(int, EVP_CipherUpdate, EVP_CIPHER_CTX *ctx, ctx, unsigned char *out, out, int *outl, outl, const unsigned char *in, in, int inl, inl, return 0, return)
|
||
|
+DEFINEFUNC3(int, EVP_CipherFinal, EVP_CIPHER_CTX *ctx, ctx, unsigned char *out, out, int *outl, outl, return 0, return)
|
||
|
DEFINEFUNC(const EVP_CIPHER *, EVP_des_cbc, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
DEFINEFUNC(const EVP_CIPHER *, EVP_des_ede3_cbc, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
DEFINEFUNC(const EVP_CIPHER *, EVP_rc2_cbc, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
+DEFINEFUNC(const EVP_MD *, EVP_sha1, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
DEFINEFUNC3(int, EVP_PKEY_assign, EVP_PKEY *a, a, int b, b, char *c, c, return -1, return)
|
||
|
DEFINEFUNC2(int, EVP_PKEY_set1_RSA, EVP_PKEY *a, a, RSA *b, b, return -1, return)
|
||
|
DEFINEFUNC2(int, EVP_PKEY_set1_DSA, EVP_PKEY *a, a, DSA *b, b, return -1, return)
|
||
|
@@ -202,10 +349,8 @@ DEFINEFUNC3(int, i2t_ASN1_OBJECT, char *a, a, int b, b, ASN1_OBJECT *c, c, retur
|
||
|
DEFINEFUNC4(int, OBJ_obj2txt, char *a, a, int b, b, ASN1_OBJECT *c, c, int d, d, return -1, return)
|
||
|
|
||
|
DEFINEFUNC(int, OBJ_obj2nid, const ASN1_OBJECT *a, a, return NID_undef, return)
|
||
|
-#ifdef SSLEAY_MACROS
|
||
|
-DEFINEFUNC6(void *, PEM_ASN1_read_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return 0, return)
|
||
|
-DEFINEFUNC6(void *, PEM_ASN1_write_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return 0, return)
|
||
|
-#else
|
||
|
+
|
||
|
+#ifndef SSLEAY_MACROS
|
||
|
DEFINEFUNC4(EVP_PKEY *, PEM_read_bio_PrivateKey, BIO *a, a, EVP_PKEY **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
|
||
|
DEFINEFUNC4(DSA *, PEM_read_bio_DSAPrivateKey, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
|
||
|
DEFINEFUNC4(RSA *, PEM_read_bio_RSAPrivateKey, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
|
||
|
@@ -218,7 +363,7 @@ DEFINEFUNC7(int, PEM_write_bio_RSAPrivateKey, BIO *a, a, RSA *b, b, const EVP_CI
|
||
|
#ifndef OPENSSL_NO_EC
|
||
|
DEFINEFUNC7(int, PEM_write_bio_ECPrivateKey, BIO *a, a, EC_KEY *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return)
|
||
|
#endif
|
||
|
-#endif
|
||
|
+#endif // !SSLEAY_MACROS
|
||
|
DEFINEFUNC4(EVP_PKEY *, PEM_read_bio_PUBKEY, BIO *a, a, EVP_PKEY **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
|
||
|
DEFINEFUNC4(DSA *, PEM_read_bio_DSA_PUBKEY, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
|
||
|
DEFINEFUNC4(RSA *, PEM_read_bio_RSA_PUBKEY, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
|
||
|
@@ -234,23 +379,10 @@ DEFINEFUNC2(void, RAND_seed, const void *a, a, int b, b, return, DUMMYARG)
|
||
|
DEFINEFUNC(int, RAND_status, void, DUMMYARG, return -1, return)
|
||
|
DEFINEFUNC(RSA *, RSA_new, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
DEFINEFUNC(void, RSA_free, RSA *a, a, return, DUMMYARG)
|
||
|
-DEFINEFUNC(int, sk_num, STACK *a, a, return -1, return)
|
||
|
-DEFINEFUNC2(void, sk_pop_free, STACK *a, a, void (*b)(void*), b, return, DUMMYARG)
|
||
|
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
|
||
|
-DEFINEFUNC(_STACK *, sk_new_null, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
-DEFINEFUNC2(void, sk_push, _STACK *a, a, void *b, b, return, DUMMYARG)
|
||
|
-DEFINEFUNC(void, sk_free, _STACK *a, a, return, DUMMYARG)
|
||
|
-DEFINEFUNC2(void *, sk_value, STACK *a, a, int b, b, return 0, return)
|
||
|
-#else
|
||
|
-DEFINEFUNC(STACK *, sk_new_null, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
-DEFINEFUNC2(void, sk_push, STACK *a, a, char *b, b, return, DUMMYARG)
|
||
|
-DEFINEFUNC(void, sk_free, STACK *a, a, return, DUMMYARG)
|
||
|
-DEFINEFUNC2(char *, sk_value, STACK *a, a, int b, b, return 0, return)
|
||
|
-#endif
|
||
|
DEFINEFUNC(int, SSL_accept, SSL *a, a, return -1, return)
|
||
|
DEFINEFUNC(int, SSL_clear, SSL *a, a, return -1, return)
|
||
|
-DEFINEFUNC3(char *, SSL_CIPHER_description, SSL_CIPHER *a, a, char *b, b, int c, c, return 0, return)
|
||
|
-DEFINEFUNC2(int, SSL_CIPHER_get_bits, SSL_CIPHER *a, a, int *b, b, return 0, return)
|
||
|
+DEFINEFUNC3(char *, SSL_CIPHER_description, const SSL_CIPHER *a, a, char *b, b, int c, c, return 0, return)
|
||
|
+DEFINEFUNC2(int, SSL_CIPHER_get_bits, const SSL_CIPHER *a, a, int *b, b, return 0, return)
|
||
|
DEFINEFUNC(int, SSL_connect, SSL *a, a, return -1, return)
|
||
|
DEFINEFUNC(int, SSL_CTX_check_private_key, const SSL_CTX *a, a, return -1, return)
|
||
|
DEFINEFUNC4(long, SSL_CTX_ctrl, SSL_CTX *a, a, int b, b, long c, c, void *d, d, return -1, return)
|
||
|
@@ -287,8 +419,6 @@ DEFINEFUNC(long, SSL_get_verify_result, const SSL *a, a, return -1, return)
|
||
|
#else
|
||
|
DEFINEFUNC(long, SSL_get_verify_result, SSL *a, a, return -1, return)
|
||
|
#endif
|
||
|
-DEFINEFUNC(int, SSL_library_init, void, DUMMYARG, return -1, return)
|
||
|
-DEFINEFUNC(void, SSL_load_error_strings, void, DUMMYARG, return, DUMMYARG)
|
||
|
DEFINEFUNC(SSL *, SSL_new, SSL_CTX *a, a, return 0, return)
|
||
|
DEFINEFUNC4(long, SSL_ctrl, SSL *a, a, int cmd, cmd, long larg, larg, void *parg, parg, return -1, return)
|
||
|
DEFINEFUNC3(int, SSL_read, SSL *a, a, void *b, b, int c, c, return -1, return)
|
||
|
@@ -301,7 +431,6 @@ DEFINEFUNC(void, SSL_SESSION_free, SSL_SESSION *ses, ses, return, DUMMYARG)
|
||
|
DEFINEFUNC(SSL_SESSION*, SSL_get1_session, SSL *ssl, ssl, return 0, return)
|
||
|
DEFINEFUNC(SSL_SESSION*, SSL_get_session, const SSL *ssl, ssl, return 0, return)
|
||
|
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
|
||
|
-DEFINEFUNC5(int, SSL_get_ex_new_index, long argl, argl, void *argp, argp, CRYPTO_EX_new *new_func, new_func, CRYPTO_EX_dup *dup_func, dup_func, CRYPTO_EX_free *free_func, free_func, return -1, return)
|
||
|
DEFINEFUNC3(int, SSL_set_ex_data, SSL *ssl, ssl, int idx, idx, void *arg, arg, return 0, return)
|
||
|
DEFINEFUNC2(void *, SSL_get_ex_data, const SSL *ssl, ssl, int idx, idx, return NULL, return)
|
||
|
#endif
|
||
|
@@ -310,51 +439,9 @@ DEFINEFUNC2(void, SSL_set_psk_client_callback, SSL* ssl, ssl, q_psk_client_callb
|
||
|
DEFINEFUNC2(void, SSL_set_psk_server_callback, SSL* ssl, ssl, q_psk_server_callback_t callback, callback, return, DUMMYARG)
|
||
|
DEFINEFUNC2(int, SSL_CTX_use_psk_identity_hint, SSL_CTX* ctx, ctx, const char *hint, hint, return 0, return)
|
||
|
#endif
|
||
|
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
|
||
|
-#ifndef OPENSSL_NO_SSL2
|
||
|
-DEFINEFUNC(const SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
-#endif
|
||
|
-#ifndef OPENSSL_NO_SSL3_METHOD
|
||
|
-DEFINEFUNC(const SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
-#endif
|
||
|
-DEFINEFUNC(const SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
-DEFINEFUNC(const SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
|
||
|
-DEFINEFUNC(const SSL_METHOD *, TLSv1_1_client_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
-DEFINEFUNC(const SSL_METHOD *, TLSv1_2_client_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
-#endif
|
||
|
-#ifndef OPENSSL_NO_SSL2
|
||
|
-DEFINEFUNC(const SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
-#endif
|
||
|
-#ifndef OPENSSL_NO_SSL3_METHOD
|
||
|
-DEFINEFUNC(const SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
-#endif
|
||
|
-DEFINEFUNC(const SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
-DEFINEFUNC(const SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
|
||
|
-DEFINEFUNC(const SSL_METHOD *, TLSv1_1_server_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
-DEFINEFUNC(const SSL_METHOD *, TLSv1_2_server_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
-#endif
|
||
|
-#else
|
||
|
-#ifndef OPENSSL_NO_SSL2
|
||
|
-DEFINEFUNC(SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
-#endif
|
||
|
-#ifndef OPENSSL_NO_SSL3_METHOD
|
||
|
-DEFINEFUNC(SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
-#endif
|
||
|
-DEFINEFUNC(SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
-DEFINEFUNC(SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
-#ifndef OPENSSL_NO_SSL2
|
||
|
-DEFINEFUNC(SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
-#endif
|
||
|
-#ifndef OPENSSL_NO_SSL3_METHOD
|
||
|
-DEFINEFUNC(SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
-#endif
|
||
|
-DEFINEFUNC(SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
-DEFINEFUNC(SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
-#endif
|
||
|
DEFINEFUNC3(int, SSL_write, SSL *a, a, const void *b, b, int c, c, return -1, return)
|
||
|
DEFINEFUNC2(int, X509_cmp, X509 *a, a, X509 *b, b, return -1, return)
|
||
|
+DEFINEFUNC4(int, X509_digest, const X509 *x509, x509, const EVP_MD *type, type, unsigned char *md, md, unsigned int *len, len, return -1, return)
|
||
|
#ifndef SSLEAY_MACROS
|
||
|
DEFINEFUNC(X509 *, X509_dup, X509 *a, a, return 0, return)
|
||
|
#endif
|
||
|
@@ -378,6 +465,7 @@ DEFINEFUNC2(int, ASN1_STRING_print, BIO *a, a, ASN1_STRING *b, b, return 0, retu
|
||
|
DEFINEFUNC2(int, X509_check_issued, X509 *a, a, X509 *b, b, return -1, return)
|
||
|
DEFINEFUNC(X509_NAME *, X509_get_issuer_name, X509 *a, a, return 0, return)
|
||
|
DEFINEFUNC(X509_NAME *, X509_get_subject_name, X509 *a, a, return 0, return)
|
||
|
+DEFINEFUNC(ASN1_INTEGER *, X509_get_serialNumber, X509 *a, a, return 0, return)
|
||
|
DEFINEFUNC(int, X509_verify_cert, X509_STORE_CTX *a, a, return -1, return)
|
||
|
DEFINEFUNC(int, X509_NAME_entry_count, X509_NAME *a, a, return 0, return)
|
||
|
DEFINEFUNC2(X509_NAME_ENTRY *, X509_NAME_get_entry, X509_NAME *a, a, int b, b, return 0, return)
|
||
|
@@ -393,25 +481,8 @@ DEFINEFUNC2(int, X509_STORE_CTX_set_purpose, X509_STORE_CTX *a, a, int b, b, ret
|
||
|
DEFINEFUNC(int, X509_STORE_CTX_get_error, X509_STORE_CTX *a, a, return -1, return)
|
||
|
DEFINEFUNC(int, X509_STORE_CTX_get_error_depth, X509_STORE_CTX *a, a, return -1, return)
|
||
|
DEFINEFUNC(X509 *, X509_STORE_CTX_get_current_cert, X509_STORE_CTX *a, a, return 0, return)
|
||
|
-DEFINEFUNC(STACK_OF(X509) *, X509_STORE_CTX_get_chain, X509_STORE_CTX *a, a, return 0, return)
|
||
|
DEFINEFUNC(X509_STORE_CTX *, X509_STORE_CTX_new, DUMMYARG, DUMMYARG, return 0, return)
|
||
|
-#ifdef SSLEAY_MACROS
|
||
|
-DEFINEFUNC2(int, i2d_DSAPrivateKey, const DSA *a, a, unsigned char **b, b, return -1, return)
|
||
|
-DEFINEFUNC2(int, i2d_RSAPrivateKey, const RSA *a, a, unsigned char **b, b, return -1, return)
|
||
|
-#ifndef OPENSSL_NO_EC
|
||
|
-DEFINEFUNC2(int, i2d_ECPrivateKey, const EC_KEY *a, a, unsigned char **b, b, return -1, return)
|
||
|
-#endif
|
||
|
-DEFINEFUNC3(RSA *, d2i_RSAPrivateKey, RSA **a, a, unsigned char **b, b, long c, c, return 0, return)
|
||
|
-DEFINEFUNC3(DSA *, d2i_DSAPrivateKey, DSA **a, a, unsigned char **b, b, long c, c, return 0, return)
|
||
|
-#ifndef OPENSSL_NO_EC
|
||
|
-DEFINEFUNC3(EC_KEY *, d2i_ECPrivateKey, EC_KEY **a, a, unsigned char **b, b, long c, c, return 0, return)
|
||
|
-#endif
|
||
|
-#endif
|
||
|
-DEFINEFUNC(void, OPENSSL_add_all_algorithms_noconf, void, DUMMYARG, return, DUMMYARG)
|
||
|
-DEFINEFUNC(void, OPENSSL_add_all_algorithms_conf, void, DUMMYARG, return, DUMMYARG)
|
||
|
DEFINEFUNC3(int, SSL_CTX_load_verify_locations, SSL_CTX *ctx, ctx, const char *CAfile, CAfile, const char *CApath, CApath, return 0, return)
|
||
|
-DEFINEFUNC(long, SSLeay, void, DUMMYARG, return 0, return)
|
||
|
-DEFINEFUNC(const char *, SSLeay_version, int a, a, return 0, return)
|
||
|
DEFINEFUNC2(int, i2d_SSL_SESSION, SSL_SESSION *in, in, unsigned char **pp, pp, return 0, return)
|
||
|
DEFINEFUNC3(SSL_SESSION *, d2i_SSL_SESSION, SSL_SESSION **a, a, const unsigned char **pp, pp, long length, length, return 0, return)
|
||
|
#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG)
|
||
|
@@ -694,8 +765,8 @@ static QPair<QLibrary*, QLibrary*> loadOpenSsl()
|
||
|
#ifndef Q_OS_DARWIN
|
||
|
// second attempt: find the development files libssl.so and libcrypto.so
|
||
|
//
|
||
|
- // disabled on OS X/iOS:
|
||
|
- // OS X's /usr/lib/libssl.dylib, /usr/lib/libcrypto.dylib will be picked up in the third
|
||
|
+ // disabled on macOS/iOS:
|
||
|
+ // macOS's /usr/lib/libssl.dylib, /usr/lib/libcrypto.dylib will be picked up in the third
|
||
|
// attempt, _after_ <bundle>/Contents/Frameworks has been searched.
|
||
|
// iOS does not ship a system libssl.dylib, libcrypto.dylib in the first place.
|
||
|
libssl->setFileNameAndVersion(QLatin1String("ssl"), -1);
|
||
|
@@ -754,8 +825,12 @@ bool q_resolveOpenSslSymbols()
|
||
|
static bool symbolsResolved = false;
|
||
|
static bool triedToResolveSymbols = false;
|
||
|
#ifndef QT_NO_THREAD
|
||
|
+#if QT_CONFIG(opensslv11)
|
||
|
+ QMutexLocker locker(QMutexPool::globalInstanceGet((void *)&q_OPENSSL_init_ssl));
|
||
|
+#else
|
||
|
QMutexLocker locker(QMutexPool::globalInstanceGet((void *)&q_SSL_library_init));
|
||
|
#endif
|
||
|
+#endif
|
||
|
if (symbolsResolved)
|
||
|
return true;
|
||
|
if (triedToResolveSymbols)
|
||
|
@@ -771,11 +846,145 @@ bool q_resolveOpenSslSymbols()
|
||
|
// failed to load them
|
||
|
return false;
|
||
|
|
||
|
+#if QT_CONFIG(opensslv11)
|
||
|
+
|
||
|
+ RESOLVEFUNC(OPENSSL_init_ssl)
|
||
|
+ RESOLVEFUNC(OPENSSL_init_crypto)
|
||
|
+ RESOLVEFUNC(ASN1_STRING_get0_data)
|
||
|
+ RESOLVEFUNC(EVP_CIPHER_CTX_reset)
|
||
|
+ RESOLVEFUNC(EVP_PKEY_base_id)
|
||
|
+ RESOLVEFUNC(RSA_bits)
|
||
|
+ RESOLVEFUNC(OPENSSL_sk_new_null)
|
||
|
+ RESOLVEFUNC(OPENSSL_sk_push)
|
||
|
+ RESOLVEFUNC(OPENSSL_sk_free)
|
||
|
+ RESOLVEFUNC(OPENSSL_sk_num)
|
||
|
+ RESOLVEFUNC(OPENSSL_sk_pop_free)
|
||
|
+ RESOLVEFUNC(OPENSSL_sk_value)
|
||
|
+ RESOLVEFUNC(DH_get0_pqg)
|
||
|
+ RESOLVEFUNC(SSL_CTX_set_options)
|
||
|
+ RESOLVEFUNC(SSL_get_client_random)
|
||
|
+ RESOLVEFUNC(SSL_SESSION_get_master_key)
|
||
|
+ RESOLVEFUNC(SSL_session_reused)
|
||
|
+ RESOLVEFUNC(SSL_get_session)
|
||
|
+ RESOLVEFUNC(CRYPTO_get_ex_new_index)
|
||
|
+ RESOLVEFUNC(TLS_method)
|
||
|
+ RESOLVEFUNC(TLS_client_method)
|
||
|
+ RESOLVEFUNC(TLS_server_method)
|
||
|
+ RESOLVEFUNC(X509_STORE_CTX_get0_chain)
|
||
|
+ RESOLVEFUNC(X509_getm_notBefore)
|
||
|
+ RESOLVEFUNC(X509_getm_notAfter)
|
||
|
+ RESOLVEFUNC(X509_get_version)
|
||
|
+ RESOLVEFUNC(X509_get_pubkey)
|
||
|
+ RESOLVEFUNC(X509_STORE_set_verify_cb)
|
||
|
+ RESOLVEFUNC(CRYPTO_free)
|
||
|
+ RESOLVEFUNC(OpenSSL_version_num)
|
||
|
+ RESOLVEFUNC(OpenSSL_version)
|
||
|
+ if (!_q_OpenSSL_version) {
|
||
|
+ // Apparently, we were built with OpenSSL 1.1 enabled but are now using
|
||
|
+ // a wrong library.
|
||
|
+ delete libs.first;
|
||
|
+ delete libs.second;
|
||
|
+ qCWarning(lcSsl, "Incompatible version of OpenSSL");
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+
|
||
|
+ RESOLVEFUNC(SSL_SESSION_get_ticket_lifetime_hint)
|
||
|
+ RESOLVEFUNC(DH_bits)
|
||
|
+ RESOLVEFUNC(DSA_bits)
|
||
|
+
|
||
|
+#else // !opensslv11
|
||
|
+
|
||
|
+ RESOLVEFUNC(ASN1_STRING_data)
|
||
|
+
|
||
|
#ifdef SSLEAY_MACROS
|
||
|
RESOLVEFUNC(ASN1_dup)
|
||
|
+#endif // SSLEAY_MACROS
|
||
|
+ RESOLVEFUNC(BIO_new_file)
|
||
|
+ RESOLVEFUNC(ERR_clear_error)
|
||
|
+ RESOLVEFUNC(CRYPTO_free)
|
||
|
+ RESOLVEFUNC(CRYPTO_num_locks)
|
||
|
+ RESOLVEFUNC(CRYPTO_set_id_callback)
|
||
|
+ RESOLVEFUNC(CRYPTO_set_locking_callback)
|
||
|
+ RESOLVEFUNC(ERR_peek_last_error)
|
||
|
+ RESOLVEFUNC(ERR_free_strings)
|
||
|
+ RESOLVEFUNC(EVP_CIPHER_CTX_cleanup)
|
||
|
+ RESOLVEFUNC(EVP_CIPHER_CTX_init)
|
||
|
+
|
||
|
+#ifdef SSLEAY_MACROS // ### verify
|
||
|
+ RESOLVEFUNC(PEM_ASN1_read_bio)
|
||
|
+#endif // SSLEAY_MACROS
|
||
|
+
|
||
|
+ RESOLVEFUNC(sk_new_null)
|
||
|
+ RESOLVEFUNC(sk_push)
|
||
|
+ RESOLVEFUNC(sk_free)
|
||
|
+ RESOLVEFUNC(sk_num)
|
||
|
+ RESOLVEFUNC(sk_pop_free)
|
||
|
+ RESOLVEFUNC(sk_value)
|
||
|
+ RESOLVEFUNC(SSL_library_init)
|
||
|
+ RESOLVEFUNC(SSL_load_error_strings)
|
||
|
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
|
||
|
+ RESOLVEFUNC(SSL_get_ex_new_index)
|
||
|
+#endif
|
||
|
+#ifndef OPENSSL_NO_SSL2
|
||
|
+ RESOLVEFUNC(SSLv2_client_method)
|
||
|
#endif
|
||
|
+#ifndef OPENSSL_NO_SSL3_METHOD
|
||
|
+ RESOLVEFUNC(SSLv3_client_method)
|
||
|
+#endif
|
||
|
+ RESOLVEFUNC(SSLv23_client_method)
|
||
|
+ RESOLVEFUNC(TLSv1_client_method)
|
||
|
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
|
||
|
+ RESOLVEFUNC(TLSv1_1_client_method)
|
||
|
+ RESOLVEFUNC(TLSv1_2_client_method)
|
||
|
+#endif
|
||
|
+#ifndef OPENSSL_NO_SSL2
|
||
|
+ RESOLVEFUNC(SSLv2_server_method)
|
||
|
+#endif
|
||
|
+#ifndef OPENSSL_NO_SSL3_METHOD
|
||
|
+ RESOLVEFUNC(SSLv3_server_method)
|
||
|
+#endif
|
||
|
+ RESOLVEFUNC(SSLv23_server_method)
|
||
|
+ RESOLVEFUNC(TLSv1_server_method)
|
||
|
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
|
||
|
+ RESOLVEFUNC(TLSv1_1_server_method)
|
||
|
+ RESOLVEFUNC(TLSv1_2_server_method)
|
||
|
+#endif
|
||
|
+ RESOLVEFUNC(X509_STORE_CTX_get_chain)
|
||
|
+#ifdef SSLEAY_MACROS
|
||
|
+ RESOLVEFUNC(i2d_DSAPrivateKey)
|
||
|
+ RESOLVEFUNC(i2d_RSAPrivateKey)
|
||
|
+ RESOLVEFUNC(d2i_DSAPrivateKey)
|
||
|
+ RESOLVEFUNC(d2i_RSAPrivateKey)
|
||
|
+#endif
|
||
|
+ RESOLVEFUNC(CONF_get1_default_config_file)
|
||
|
+ RESOLVEFUNC(OPENSSL_add_all_algorithms_noconf)
|
||
|
+ RESOLVEFUNC(OPENSSL_add_all_algorithms_conf)
|
||
|
+ RESOLVEFUNC(SSLeay)
|
||
|
+
|
||
|
+ if (!_q_SSLeay || q_SSLeay() >= 0x10100000L) {
|
||
|
+ // OpenSSL 1.1 has deprecated and removed SSLeay. We consider a failure to
|
||
|
+ // resolve this symbol as a failure to resolve symbols.
|
||
|
+ // The right operand of '||' above is ... a bit of paranoia.
|
||
|
+ delete libs.first;
|
||
|
+ delete libs.second;
|
||
|
+ qCWarning(lcSsl, "Incompatible version of OpenSSL");
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+
|
||
|
+
|
||
|
+ RESOLVEFUNC(SSLeay_version)
|
||
|
+
|
||
|
+#ifndef OPENSSL_NO_EC
|
||
|
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||
|
+ if (q_SSLeay() >= 0x10002000L)
|
||
|
+ RESOLVEFUNC(EC_curve_nist2nid)
|
||
|
+#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||
|
+#endif // OPENSSL_NO_EC
|
||
|
+
|
||
|
+
|
||
|
+#endif // !opensslv11
|
||
|
+
|
||
|
RESOLVEFUNC(ASN1_INTEGER_get)
|
||
|
- RESOLVEFUNC(ASN1_STRING_data)
|
||
|
RESOLVEFUNC(ASN1_STRING_length)
|
||
|
RESOLVEFUNC(ASN1_STRING_to_UTF8)
|
||
|
RESOLVEFUNC(BIO_ctrl)
|
||
|
@@ -794,25 +1003,22 @@ bool q_resolveOpenSslSymbols()
|
||
|
RESOLVEFUNC(BN_is_word)
|
||
|
#endif
|
||
|
RESOLVEFUNC(BN_mod_word)
|
||
|
- RESOLVEFUNC(CRYPTO_free)
|
||
|
- RESOLVEFUNC(CRYPTO_num_locks)
|
||
|
- RESOLVEFUNC(CRYPTO_set_id_callback)
|
||
|
- RESOLVEFUNC(CRYPTO_set_locking_callback)
|
||
|
RESOLVEFUNC(DSA_new)
|
||
|
RESOLVEFUNC(DSA_free)
|
||
|
RESOLVEFUNC(ERR_error_string)
|
||
|
RESOLVEFUNC(ERR_get_error)
|
||
|
- RESOLVEFUNC(ERR_free_strings)
|
||
|
- RESOLVEFUNC(EVP_CIPHER_CTX_cleanup)
|
||
|
- RESOLVEFUNC(EVP_CIPHER_CTX_init)
|
||
|
+ RESOLVEFUNC(EVP_CIPHER_CTX_new)
|
||
|
+ RESOLVEFUNC(EVP_CIPHER_CTX_free)
|
||
|
RESOLVEFUNC(EVP_CIPHER_CTX_ctrl)
|
||
|
RESOLVEFUNC(EVP_CIPHER_CTX_set_key_length)
|
||
|
RESOLVEFUNC(EVP_CipherInit)
|
||
|
+ RESOLVEFUNC(EVP_CipherInit_ex)
|
||
|
RESOLVEFUNC(EVP_CipherUpdate)
|
||
|
RESOLVEFUNC(EVP_CipherFinal)
|
||
|
RESOLVEFUNC(EVP_des_cbc)
|
||
|
RESOLVEFUNC(EVP_des_ede3_cbc)
|
||
|
RESOLVEFUNC(EVP_rc2_cbc)
|
||
|
+ RESOLVEFUNC(EVP_sha1)
|
||
|
RESOLVEFUNC(EVP_PKEY_assign)
|
||
|
RESOLVEFUNC(EVP_PKEY_set1_RSA)
|
||
|
RESOLVEFUNC(EVP_PKEY_set1_DSA)
|
||
|
@@ -834,9 +1040,8 @@ bool q_resolveOpenSslSymbols()
|
||
|
RESOLVEFUNC(i2t_ASN1_OBJECT)
|
||
|
RESOLVEFUNC(OBJ_obj2txt)
|
||
|
RESOLVEFUNC(OBJ_obj2nid)
|
||
|
-#ifdef SSLEAY_MACROS // ### verify
|
||
|
- RESOLVEFUNC(PEM_ASN1_read_bio)
|
||
|
-#else
|
||
|
+
|
||
|
+#ifndef SSLEAY_MACROS
|
||
|
RESOLVEFUNC(PEM_read_bio_PrivateKey)
|
||
|
RESOLVEFUNC(PEM_read_bio_DSAPrivateKey)
|
||
|
RESOLVEFUNC(PEM_read_bio_RSAPrivateKey)
|
||
|
@@ -849,7 +1054,8 @@ bool q_resolveOpenSslSymbols()
|
||
|
#ifndef OPENSSL_NO_EC
|
||
|
RESOLVEFUNC(PEM_write_bio_ECPrivateKey)
|
||
|
#endif
|
||
|
-#endif
|
||
|
+#endif // !SSLEAY_MACROS
|
||
|
+
|
||
|
RESOLVEFUNC(PEM_read_bio_PUBKEY)
|
||
|
RESOLVEFUNC(PEM_read_bio_DSA_PUBKEY)
|
||
|
RESOLVEFUNC(PEM_read_bio_RSA_PUBKEY)
|
||
|
@@ -865,12 +1071,6 @@ bool q_resolveOpenSslSymbols()
|
||
|
RESOLVEFUNC(RAND_status)
|
||
|
RESOLVEFUNC(RSA_new)
|
||
|
RESOLVEFUNC(RSA_free)
|
||
|
- RESOLVEFUNC(sk_new_null)
|
||
|
- RESOLVEFUNC(sk_push)
|
||
|
- RESOLVEFUNC(sk_free)
|
||
|
- RESOLVEFUNC(sk_num)
|
||
|
- RESOLVEFUNC(sk_pop_free)
|
||
|
- RESOLVEFUNC(sk_value)
|
||
|
RESOLVEFUNC(SSL_CIPHER_description)
|
||
|
RESOLVEFUNC(SSL_CIPHER_get_bits)
|
||
|
RESOLVEFUNC(SSL_CTX_check_private_key)
|
||
|
@@ -898,8 +1098,6 @@ bool q_resolveOpenSslSymbols()
|
||
|
RESOLVEFUNC(SSL_get_peer_cert_chain)
|
||
|
RESOLVEFUNC(SSL_get_peer_certificate)
|
||
|
RESOLVEFUNC(SSL_get_verify_result)
|
||
|
- RESOLVEFUNC(SSL_library_init)
|
||
|
- RESOLVEFUNC(SSL_load_error_strings)
|
||
|
RESOLVEFUNC(SSL_new)
|
||
|
RESOLVEFUNC(SSL_ctrl)
|
||
|
RESOLVEFUNC(SSL_read)
|
||
|
@@ -912,7 +1110,6 @@ bool q_resolveOpenSslSymbols()
|
||
|
RESOLVEFUNC(SSL_get1_session)
|
||
|
RESOLVEFUNC(SSL_get_session)
|
||
|
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
|
||
|
- RESOLVEFUNC(SSL_get_ex_new_index)
|
||
|
RESOLVEFUNC(SSL_set_ex_data)
|
||
|
RESOLVEFUNC(SSL_get_ex_data)
|
||
|
#endif
|
||
|
@@ -922,30 +1119,6 @@ bool q_resolveOpenSslSymbols()
|
||
|
RESOLVEFUNC(SSL_CTX_use_psk_identity_hint)
|
||
|
#endif
|
||
|
RESOLVEFUNC(SSL_write)
|
||
|
-#ifndef OPENSSL_NO_SSL2
|
||
|
- RESOLVEFUNC(SSLv2_client_method)
|
||
|
-#endif
|
||
|
-#ifndef OPENSSL_NO_SSL3_METHOD
|
||
|
- RESOLVEFUNC(SSLv3_client_method)
|
||
|
-#endif
|
||
|
- RESOLVEFUNC(SSLv23_client_method)
|
||
|
- RESOLVEFUNC(TLSv1_client_method)
|
||
|
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
|
||
|
- RESOLVEFUNC(TLSv1_1_client_method)
|
||
|
- RESOLVEFUNC(TLSv1_2_client_method)
|
||
|
-#endif
|
||
|
-#ifndef OPENSSL_NO_SSL2
|
||
|
- RESOLVEFUNC(SSLv2_server_method)
|
||
|
-#endif
|
||
|
-#ifndef OPENSSL_NO_SSL3_METHOD
|
||
|
- RESOLVEFUNC(SSLv3_server_method)
|
||
|
-#endif
|
||
|
- RESOLVEFUNC(SSLv23_server_method)
|
||
|
- RESOLVEFUNC(TLSv1_server_method)
|
||
|
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
|
||
|
- RESOLVEFUNC(TLSv1_1_server_method)
|
||
|
- RESOLVEFUNC(TLSv1_2_server_method)
|
||
|
-#endif
|
||
|
RESOLVEFUNC(X509_NAME_entry_count)
|
||
|
RESOLVEFUNC(X509_NAME_get_entry)
|
||
|
RESOLVEFUNC(X509_NAME_ENTRY_get_data)
|
||
|
@@ -961,12 +1134,12 @@ bool q_resolveOpenSslSymbols()
|
||
|
RESOLVEFUNC(X509_STORE_CTX_get_error)
|
||
|
RESOLVEFUNC(X509_STORE_CTX_get_error_depth)
|
||
|
RESOLVEFUNC(X509_STORE_CTX_get_current_cert)
|
||
|
- RESOLVEFUNC(X509_STORE_CTX_get_chain)
|
||
|
RESOLVEFUNC(X509_cmp)
|
||
|
#ifndef SSLEAY_MACROS
|
||
|
RESOLVEFUNC(X509_dup)
|
||
|
#endif
|
||
|
RESOLVEFUNC(X509_print)
|
||
|
+ RESOLVEFUNC(X509_digest)
|
||
|
RESOLVEFUNC(X509_EXTENSION_get_object)
|
||
|
RESOLVEFUNC(X509_free)
|
||
|
RESOLVEFUNC(X509_get_ext)
|
||
|
@@ -982,20 +1155,11 @@ bool q_resolveOpenSslSymbols()
|
||
|
RESOLVEFUNC(X509_check_issued)
|
||
|
RESOLVEFUNC(X509_get_issuer_name)
|
||
|
RESOLVEFUNC(X509_get_subject_name)
|
||
|
+ RESOLVEFUNC(X509_get_serialNumber)
|
||
|
RESOLVEFUNC(X509_verify_cert)
|
||
|
RESOLVEFUNC(d2i_X509)
|
||
|
RESOLVEFUNC(i2d_X509)
|
||
|
-#ifdef SSLEAY_MACROS
|
||
|
- RESOLVEFUNC(i2d_DSAPrivateKey)
|
||
|
- RESOLVEFUNC(i2d_RSAPrivateKey)
|
||
|
- RESOLVEFUNC(d2i_DSAPrivateKey)
|
||
|
- RESOLVEFUNC(d2i_RSAPrivateKey)
|
||
|
-#endif
|
||
|
- RESOLVEFUNC(OPENSSL_add_all_algorithms_noconf)
|
||
|
- RESOLVEFUNC(OPENSSL_add_all_algorithms_conf)
|
||
|
RESOLVEFUNC(SSL_CTX_load_verify_locations)
|
||
|
- RESOLVEFUNC(SSLeay)
|
||
|
- RESOLVEFUNC(SSLeay_version)
|
||
|
RESOLVEFUNC(i2d_SSL_SESSION)
|
||
|
RESOLVEFUNC(d2i_SSL_SESSION)
|
||
|
#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG)
|
||
|
@@ -1019,27 +1183,14 @@ bool q_resolveOpenSslSymbols()
|
||
|
RESOLVEFUNC(EC_KEY_new_by_curve_name)
|
||
|
RESOLVEFUNC(EC_KEY_free)
|
||
|
RESOLVEFUNC(EC_get_builtin_curves)
|
||
|
-#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||
|
- if (q_SSLeay() >= 0x10002000L)
|
||
|
- RESOLVEFUNC(EC_curve_nist2nid)
|
||
|
-#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||
|
#endif // OPENSSL_NO_EC
|
||
|
RESOLVEFUNC(PKCS12_parse)
|
||
|
RESOLVEFUNC(d2i_PKCS12_bio)
|
||
|
RESOLVEFUNC(PKCS12_free)
|
||
|
|
||
|
+ symbolsResolved = true;
|
||
|
delete libs.first;
|
||
|
delete libs.second;
|
||
|
- if (!_q_SSLeay || q_SSLeay() >= 0x10100000L) {
|
||
|
- // OpenSSL 1.1 deprecated and removed SSLeay. We consider a failure to
|
||
|
- // resolve this symbol as a failure to resolve symbols.
|
||
|
- // The right operand of '||' above ... a bit of paranoia.
|
||
|
- qCWarning(lcSsl, "Incompatible version of OpenSSL");
|
||
|
- return false;
|
||
|
- }
|
||
|
-
|
||
|
- symbolsResolved = true;
|
||
|
-
|
||
|
return true;
|
||
|
}
|
||
|
#endif // QT_CONFIG(library)
|
||
|
diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h
|
||
|
index b35a895..796bf2d 100644
|
||
|
--- a/src/network/ssl/qsslsocket_openssl_symbols_p.h
|
||
|
+++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h
|
||
|
@@ -1,6 +1,6 @@
|
||
|
/****************************************************************************
|
||
|
**
|
||
|
-** Copyright (C) 2016 The Qt Company Ltd.
|
||
|
+** Copyright (C) 2017 The Qt Company Ltd.
|
||
|
** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
|
||
|
** Contact: https://www.qt.io/licensing/
|
||
|
**
|
||
|
@@ -56,6 +56,7 @@
|
||
|
#ifndef QSSLSOCKET_OPENSSL_SYMBOLS_P_H
|
||
|
#define QSSLSOCKET_OPENSSL_SYMBOLS_P_H
|
||
|
|
||
|
+
|
||
|
//
|
||
|
// W A R N I N G
|
||
|
// -------------
|
||
|
@@ -215,17 +216,20 @@ QT_BEGIN_NAMESPACE
|
||
|
|
||
|
#endif // !defined QT_LINKED_OPENSSL
|
||
|
|
||
|
+#if QT_CONFIG(opensslv11)
|
||
|
+#include "qsslsocket_openssl11_symbols_p.h"
|
||
|
+#else
|
||
|
+#include "qsslsocket_opensslpre11_symbols_p.h"
|
||
|
+#endif // QT_CONFIG
|
||
|
+
|
||
|
bool q_resolveOpenSslSymbols();
|
||
|
long q_ASN1_INTEGER_get(ASN1_INTEGER *a);
|
||
|
-unsigned char * q_ASN1_STRING_data(ASN1_STRING *a);
|
||
|
int q_ASN1_STRING_length(ASN1_STRING *a);
|
||
|
int q_ASN1_STRING_to_UTF8(unsigned char **a, ASN1_STRING *b);
|
||
|
long q_BIO_ctrl(BIO *a, int b, long c, void *d);
|
||
|
Q_AUTOTEST_EXPORT int q_BIO_free(BIO *a);
|
||
|
-Q_AUTOTEST_EXPORT BIO *q_BIO_new(BIO_METHOD *a);
|
||
|
BIO *q_BIO_new_mem_buf(void *a, int b);
|
||
|
int q_BIO_read(BIO *a, void *b, int c);
|
||
|
-Q_AUTOTEST_EXPORT BIO_METHOD *q_BIO_s_mem();
|
||
|
Q_AUTOTEST_EXPORT int q_BIO_write(BIO *a, const void *b, int c);
|
||
|
int q_BN_num_bits(const BIGNUM *a);
|
||
|
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||
|
@@ -247,26 +251,23 @@ BN_ULONG q_BN_mod_word(const BIGNUM *a, BN_ULONG w);
|
||
|
const EC_GROUP* q_EC_KEY_get0_group(const EC_KEY* k);
|
||
|
int q_EC_GROUP_get_degree(const EC_GROUP* g);
|
||
|
#endif
|
||
|
-int q_CRYPTO_num_locks();
|
||
|
-void q_CRYPTO_set_locking_callback(void (*a)(int, int, const char *, int));
|
||
|
-void q_CRYPTO_set_id_callback(unsigned long (*a)());
|
||
|
-void q_CRYPTO_free(void *a);
|
||
|
DSA *q_DSA_new();
|
||
|
void q_DSA_free(DSA *a);
|
||
|
X509 *q_d2i_X509(X509 **a, const unsigned char **b, long c);
|
||
|
char *q_ERR_error_string(unsigned long a, char *b);
|
||
|
unsigned long q_ERR_get_error();
|
||
|
-void q_ERR_free_strings();
|
||
|
-void q_EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a);
|
||
|
-void q_EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *a);
|
||
|
+EVP_CIPHER_CTX *q_EVP_CIPHER_CTX_new();
|
||
|
+void q_EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *a);
|
||
|
int q_EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr);
|
||
|
int q_EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen);
|
||
|
int q_EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, const unsigned char *key, const unsigned char *iv, int enc);
|
||
|
+int q_EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *impl, const unsigned char *key, const unsigned char *iv, int enc);
|
||
|
int q_EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl);
|
||
|
int q_EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
|
||
|
const EVP_CIPHER *q_EVP_des_cbc();
|
||
|
const EVP_CIPHER *q_EVP_des_ede3_cbc();
|
||
|
const EVP_CIPHER *q_EVP_rc2_cbc();
|
||
|
+const EVP_MD *q_EVP_sha1();
|
||
|
int q_EVP_PKEY_assign(EVP_PKEY *a, int b, char *c);
|
||
|
Q_AUTOTEST_EXPORT int q_EVP_PKEY_set1_RSA(EVP_PKEY *a, RSA *b);
|
||
|
int q_EVP_PKEY_set1_DSA(EVP_PKEY *a, DSA *b);
|
||
|
@@ -310,7 +311,7 @@ int q_PEM_write_bio_RSAPrivateKey(BIO *a, RSA *b, const EVP_CIPHER *c, unsigned
|
||
|
int q_PEM_write_bio_ECPrivateKey(BIO *a, EC_KEY *b, const EVP_CIPHER *c, unsigned char *d,
|
||
|
int e, pem_password_cb *f, void *g);
|
||
|
#endif
|
||
|
-#endif
|
||
|
+#endif // SSLEAY_MACROS
|
||
|
Q_AUTOTEST_EXPORT EVP_PKEY *q_PEM_read_bio_PUBKEY(BIO *a, EVP_PKEY **b, pem_password_cb *c, void *d);
|
||
|
DSA *q_PEM_read_bio_DSA_PUBKEY(BIO *a, DSA **b, pem_password_cb *c, void *d);
|
||
|
RSA *q_PEM_read_bio_RSA_PUBKEY(BIO *a, RSA **b, pem_password_cb *c, void *d);
|
||
|
@@ -326,23 +327,10 @@ void q_RAND_seed(const void *a, int b);
|
||
|
int q_RAND_status();
|
||
|
RSA *q_RSA_new();
|
||
|
void q_RSA_free(RSA *a);
|
||
|
-int q_sk_num(STACK *a);
|
||
|
-void q_sk_pop_free(STACK *a, void (*b)(void *));
|
||
|
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
|
||
|
-_STACK *q_sk_new_null();
|
||
|
-void q_sk_push(_STACK *st, void *data);
|
||
|
-void q_sk_free(_STACK *a);
|
||
|
-void * q_sk_value(STACK *a, int b);
|
||
|
-#else
|
||
|
-STACK *q_sk_new_null();
|
||
|
-void q_sk_push(STACK *st, char *data);
|
||
|
-void q_sk_free(STACK *a);
|
||
|
-char * q_sk_value(STACK *a, int b);
|
||
|
-#endif
|
||
|
int q_SSL_accept(SSL *a);
|
||
|
int q_SSL_clear(SSL *a);
|
||
|
-char *q_SSL_CIPHER_description(SSL_CIPHER *a, char *b, int c);
|
||
|
-int q_SSL_CIPHER_get_bits(SSL_CIPHER *a, int *b);
|
||
|
+char *q_SSL_CIPHER_description(const SSL_CIPHER *a, char *b, int c);
|
||
|
+int q_SSL_CIPHER_get_bits(const SSL_CIPHER *a, int *b);
|
||
|
int q_SSL_connect(SSL *a);
|
||
|
int q_SSL_CTX_check_private_key(const SSL_CTX *a);
|
||
|
long q_SSL_CTX_ctrl(SSL_CTX *a, int b, long c, void *d);
|
||
|
@@ -374,8 +362,6 @@ int q_SSL_get_error(SSL *a, int b);
|
||
|
STACK_OF(X509) *q_SSL_get_peer_cert_chain(SSL *a);
|
||
|
X509 *q_SSL_get_peer_certificate(SSL *a);
|
||
|
long q_SSL_get_verify_result(const SSL *a);
|
||
|
-int q_SSL_library_init();
|
||
|
-void q_SSL_load_error_strings();
|
||
|
SSL *q_SSL_new(SSL_CTX *a);
|
||
|
long q_SSL_ctrl(SSL *ssl,int cmd, long larg, void *parg);
|
||
|
int q_SSL_read(SSL *a, void *b, int c);
|
||
|
@@ -388,7 +374,6 @@ void q_SSL_SESSION_free(SSL_SESSION *ses);
|
||
|
SSL_SESSION *q_SSL_get1_session(SSL *ssl);
|
||
|
SSL_SESSION *q_SSL_get_session(const SSL *ssl);
|
||
|
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
|
||
|
-int q_SSL_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
|
||
|
int q_SSL_set_ex_data(SSL *ssl, int idx, void *arg);
|
||
|
void *q_SSL_get_ex_data(const SSL *ssl, int idx);
|
||
|
#endif
|
||
|
@@ -399,49 +384,6 @@ typedef unsigned int (*q_psk_server_callback_t)(SSL *ssl, const char *identity,
|
||
|
void q_SSL_set_psk_server_callback(SSL *ssl, q_psk_server_callback_t callback);
|
||
|
int q_SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *hint);
|
||
|
#endif // OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
|
||
|
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
|
||
|
-#ifndef OPENSSL_NO_SSL2
|
||
|
-const SSL_METHOD *q_SSLv2_client_method();
|
||
|
-#endif
|
||
|
-#ifndef OPENSSL_NO_SSL3_METHOD
|
||
|
-const SSL_METHOD *q_SSLv3_client_method();
|
||
|
-#endif
|
||
|
-const SSL_METHOD *q_SSLv23_client_method();
|
||
|
-const SSL_METHOD *q_TLSv1_client_method();
|
||
|
-const SSL_METHOD *q_TLSv1_1_client_method();
|
||
|
-const SSL_METHOD *q_TLSv1_2_client_method();
|
||
|
-#ifndef OPENSSL_NO_SSL2
|
||
|
-const SSL_METHOD *q_SSLv2_server_method();
|
||
|
-#endif
|
||
|
-#ifndef OPENSSL_NO_SSL3_METHOD
|
||
|
-const SSL_METHOD *q_SSLv3_server_method();
|
||
|
-#endif
|
||
|
-const SSL_METHOD *q_SSLv23_server_method();
|
||
|
-const SSL_METHOD *q_TLSv1_server_method();
|
||
|
-const SSL_METHOD *q_TLSv1_1_server_method();
|
||
|
-const SSL_METHOD *q_TLSv1_2_server_method();
|
||
|
-#else
|
||
|
-#ifndef OPENSSL_NO_SSL2
|
||
|
-SSL_METHOD *q_SSLv2_client_method();
|
||
|
-#endif
|
||
|
-#ifndef OPENSSL_NO_SSL3_METHOD
|
||
|
-SSL_METHOD *q_SSLv3_client_method();
|
||
|
-#endif
|
||
|
-SSL_METHOD *q_SSLv23_client_method();
|
||
|
-SSL_METHOD *q_TLSv1_client_method();
|
||
|
-SSL_METHOD *q_TLSv1_1_client_method();
|
||
|
-SSL_METHOD *q_TLSv1_2_client_method();
|
||
|
-#ifndef OPENSSL_NO_SSL2
|
||
|
-SSL_METHOD *q_SSLv2_server_method();
|
||
|
-#endif
|
||
|
-#ifndef OPENSSL_NO_SSL3_METHOD
|
||
|
-SSL_METHOD *q_SSLv3_server_method();
|
||
|
-#endif
|
||
|
-SSL_METHOD *q_SSLv23_server_method();
|
||
|
-SSL_METHOD *q_TLSv1_server_method();
|
||
|
-SSL_METHOD *q_TLSv1_1_server_method();
|
||
|
-SSL_METHOD *q_TLSv1_2_server_method();
|
||
|
-#endif
|
||
|
int q_SSL_write(SSL *a, const void *b, int c);
|
||
|
int q_X509_cmp(X509 *a, X509 *b);
|
||
|
#ifdef SSLEAY_MACROS
|
||
|
@@ -452,6 +394,7 @@ void *q_ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, char *x);
|
||
|
X509 *q_X509_dup(X509 *a);
|
||
|
#endif
|
||
|
void q_X509_print(BIO *a, X509*b);
|
||
|
+int q_X509_digest(const X509 *x509, const EVP_MD *type, unsigned char *md, unsigned int *len);
|
||
|
ASN1_OBJECT *q_X509_EXTENSION_get_object(X509_EXTENSION *a);
|
||
|
void q_X509_free(X509 *a);
|
||
|
X509_EXTENSION *q_X509_get_ext(X509 *a, int b);
|
||
|
@@ -471,6 +414,7 @@ int q_ASN1_STRING_print(BIO *a, ASN1_STRING *b);
|
||
|
int q_X509_check_issued(X509 *a, X509 *b);
|
||
|
X509_NAME *q_X509_get_issuer_name(X509 *a);
|
||
|
X509_NAME *q_X509_get_subject_name(X509 *a);
|
||
|
+ASN1_INTEGER *q_X509_get_serialNumber(X509 *a);
|
||
|
int q_X509_verify_cert(X509_STORE_CTX *ctx);
|
||
|
int q_X509_NAME_entry_count(X509_NAME *a);
|
||
|
X509_NAME_ENTRY *q_X509_NAME_get_entry(X509_NAME *a,int b);
|
||
|
@@ -488,7 +432,6 @@ int q_X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose);
|
||
|
int q_X509_STORE_CTX_get_error(X509_STORE_CTX *ctx);
|
||
|
int q_X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx);
|
||
|
X509 *q_X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx);
|
||
|
-STACK_OF(X509) *q_X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx);
|
||
|
|
||
|
// Diffie-Hellman support
|
||
|
DH *q_DH_new();
|
||
|
@@ -522,34 +465,9 @@ int q_PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert,
|
||
|
PKCS12 *q_d2i_PKCS12_bio(BIO *bio, PKCS12 **pkcs12);
|
||
|
void q_PKCS12_free(PKCS12 *pkcs12);
|
||
|
|
||
|
-
|
||
|
#define q_BIO_get_mem_data(b, pp) (int)q_BIO_ctrl(b,BIO_CTRL_INFO,0,(char *)pp)
|
||
|
#define q_BIO_pending(b) (int)q_BIO_ctrl(b,BIO_CTRL_PENDING,0,NULL)
|
||
|
-#ifdef SSLEAY_MACROS
|
||
|
-int q_i2d_DSAPrivateKey(const DSA *a, unsigned char **pp);
|
||
|
-int q_i2d_RSAPrivateKey(const RSA *a, unsigned char **pp);
|
||
|
-RSA *q_d2i_RSAPrivateKey(RSA **a, unsigned char **pp, long length);
|
||
|
-DSA *q_d2i_DSAPrivateKey(DSA **a, unsigned char **pp, long length);
|
||
|
-#define q_PEM_read_bio_RSAPrivateKey(bp, x, cb, u) \
|
||
|
- (RSA *)q_PEM_ASN1_read_bio( \
|
||
|
- (void *(*)(void**, const unsigned char**, long int))q_d2i_RSAPrivateKey, PEM_STRING_RSA, bp, (void **)x, cb, u)
|
||
|
-#define q_PEM_read_bio_DSAPrivateKey(bp, x, cb, u) \
|
||
|
- (DSA *)q_PEM_ASN1_read_bio( \
|
||
|
- (void *(*)(void**, const unsigned char**, long int))q_d2i_DSAPrivateKey, PEM_STRING_DSA, bp, (void **)x, cb, u)
|
||
|
-#define q_PEM_write_bio_RSAPrivateKey(bp,x,enc,kstr,klen,cb,u) \
|
||
|
- PEM_ASN1_write_bio((int (*)(void*, unsigned char**))q_i2d_RSAPrivateKey,PEM_STRING_RSA,\
|
||
|
- bp,(char *)x,enc,kstr,klen,cb,u)
|
||
|
-#define q_PEM_write_bio_DSAPrivateKey(bp,x,enc,kstr,klen,cb,u) \
|
||
|
- PEM_ASN1_write_bio((int (*)(void*, unsigned char**))q_i2d_DSAPrivateKey,PEM_STRING_DSA,\
|
||
|
- bp,(char *)x,enc,kstr,klen,cb,u)
|
||
|
-#define q_PEM_read_bio_DHparams(bp, dh, cb, u) \
|
||
|
- (DH *)q_PEM_ASN1_read_bio( \
|
||
|
- (void *(*)(void**, const unsigned char**, long int))q_d2i_DHparams, PEM_STRING_DHPARAMS, bp, (void **)x, cb, u)
|
||
|
-#endif
|
||
|
-#define q_SSL_CTX_set_options(ctx,op) q_SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,(op),NULL)
|
||
|
#define q_SSL_CTX_set_mode(ctx,op) q_SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,(op),NULL)
|
||
|
-#define q_SKM_sk_num(type, st) ((int (*)(const STACK_OF(type) *))q_sk_num)(st)
|
||
|
-#define q_SKM_sk_value(type, st,i) ((type * (*)(const STACK_OF(type) *, int))q_sk_value)(st, i)
|
||
|
#define q_sk_GENERAL_NAME_num(st) q_SKM_sk_num(GENERAL_NAME, (st))
|
||
|
#define q_sk_GENERAL_NAME_value(st, i) q_SKM_sk_value(GENERAL_NAME, (st), (i))
|
||
|
#define q_sk_X509_num(st) q_SKM_sk_num(X509, (st))
|
||
|
@@ -558,18 +476,12 @@ DSA *q_d2i_DSAPrivateKey(DSA **a, unsigned char **pp, long length);
|
||
|
#define q_sk_SSL_CIPHER_value(st, i) q_SKM_sk_value(SSL_CIPHER, (st), (i))
|
||
|
#define q_SSL_CTX_add_extra_chain_cert(ctx,x509) \
|
||
|
q_SSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,(char *)x509)
|
||
|
-#define q_X509_get_notAfter(x) X509_get_notAfter(x)
|
||
|
-#define q_X509_get_notBefore(x) X509_get_notBefore(x)
|
||
|
#define q_EVP_PKEY_assign_RSA(pkey,rsa) q_EVP_PKEY_assign((pkey),EVP_PKEY_RSA,\
|
||
|
(char *)(rsa))
|
||
|
#define q_EVP_PKEY_assign_DSA(pkey,dsa) q_EVP_PKEY_assign((pkey),EVP_PKEY_DSA,\
|
||
|
(char *)(dsa))
|
||
|
#define q_OpenSSL_add_all_algorithms() q_OPENSSL_add_all_algorithms_conf()
|
||
|
-void q_OPENSSL_add_all_algorithms_noconf();
|
||
|
-void q_OPENSSL_add_all_algorithms_conf();
|
||
|
int q_SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, const char *CApath);
|
||
|
-long q_SSLeay();
|
||
|
-const char *q_SSLeay_version(int type);
|
||
|
int q_i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp);
|
||
|
SSL_SESSION *q_d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, long length);
|
||
|
|
||
|
diff --git a/src/network/ssl/qsslsocket_opensslpre11.cpp b/src/network/ssl/qsslsocket_opensslpre11.cpp
|
||
|
new file mode 100644
|
||
|
index 0000000..e51888c
|
||
|
--- /dev/null
|
||
|
+++ b/src/network/ssl/qsslsocket_opensslpre11.cpp
|
||
|
@@ -0,0 +1,424 @@
|
||
|
+/****************************************************************************
|
||
|
+**
|
||
|
+** 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>
|
||
|
+#include <QtCore/qlibrary.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();
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
+/*!
|
||
|
+ \internal
|
||
|
+*/
|
||
|
+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) {
|
||
|
+ s_libraryLoaded = true;
|
||
|
+
|
||
|
+ // 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;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ 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_WIN)
|
||
|
+ HINSTANCE hLib = LoadLibraryW(L"Crypt32");
|
||
|
+ if (hLib) {
|
||
|
+ ptrCertOpenSystemStoreW = (PtrCertOpenSystemStoreW)GetProcAddress(hLib, "CertOpenSystemStoreW");
|
||
|
+ ptrCertFindCertificateInStore = (PtrCertFindCertificateInStore)GetProcAddress(hLib, "CertFindCertificateInStore");
|
||
|
+ ptrCertCloseStore = (PtrCertCloseStore)GetProcAddress(hLib, "CertCloseStore");
|
||
|
+ if (!ptrCertOpenSystemStoreW || !ptrCertFindCertificateInStore || !ptrCertCloseStore)
|
||
|
+ qCWarning(lcSsl, "could not resolve symbols in crypt32 library"); // should never happen
|
||
|
+ } else {
|
||
|
+ qCWarning(lcSsl, "could not load crypt32 library"); // should never happen
|
||
|
+ }
|
||
|
+#elif 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.
|
||
|
+ if ((QSysInfo::windowsVersion() & QSysInfo::WV_NT_based) >= QSysInfo::WV_6_0)
|
||
|
+ 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
|
||
|
diff --git a/src/network/ssl/ssl.pri b/src/network/ssl/ssl.pri
|
||
|
index 52ce2ee..949ebc3 100644
|
||
|
--- a/src/network/ssl/ssl.pri
|
||
|
+++ b/src/network/ssl/ssl.pri
|
||
|
@@ -60,13 +60,25 @@ qtConfig(ssl) {
|
||
|
HEADERS += ssl/qsslcontext_openssl_p.h \
|
||
|
ssl/qsslsocket_openssl_p.h \
|
||
|
ssl/qsslsocket_openssl_symbols_p.h
|
||
|
- SOURCES += ssl/qsslcertificate_openssl.cpp \
|
||
|
- ssl/qsslcontext_openssl.cpp \
|
||
|
+ SOURCES += ssl/qsslsocket_openssl_symbols.cpp \
|
||
|
ssl/qssldiffiehellmanparameters_openssl.cpp \
|
||
|
+ ssl/qsslcertificate_openssl.cpp \
|
||
|
ssl/qsslellipticcurve_openssl.cpp \
|
||
|
ssl/qsslkey_openssl.cpp \
|
||
|
ssl/qsslsocket_openssl.cpp \
|
||
|
- ssl/qsslsocket_openssl_symbols.cpp
|
||
|
+ ssl/qsslcontext_openssl.cpp
|
||
|
+
|
||
|
+ qtConfig(opensslv11) {
|
||
|
+ HEADERS += ssl/qsslsocket_openssl11_symbols_p.h
|
||
|
+ SOURCES += ssl/qsslsocket_openssl11.cpp \
|
||
|
+ ssl/qsslcontext_openssl11.cpp
|
||
|
+
|
||
|
+ QMAKE_CXXFLAGS += -DOPENSSL_API_COMPAT=0x10100000L
|
||
|
+ } else {
|
||
|
+ HEADERS += ssl/qsslsocket_opensslpre11_symbols_p.h
|
||
|
+ SOURCES += ssl/qsslsocket_opensslpre11.cpp \
|
||
|
+ ssl/qsslcontext_opensslpre11.cpp
|
||
|
+ }
|
||
|
|
||
|
darwin:SOURCES += ssl/qsslsocket_mac_shared.cpp
|
||
|
|