QSslSocket: OpenSSL 1.1 backend
This patch-set implements a new QSslSocket backend based on OpenSSL 1.1. 1. General. The code in this patch was organized to achieve these (somewhat contradicting) objectives: - keep the new code free of #if-ery, as far as possible; - make it easy to clean away dead code when we're eventually able to retire out-dated OpenSSL versions; - reduce the amount of code duplication. If changes in some file/component were insignificant (~5 one-liners per file), we still use pp-checks like: #if QT_CONFIG(opensslv11) ... #else ... #endif - the logic is simple and it's still easy to clean the code if we remove the legacy back-end. Where it saved #if-ery, we also introduced 'forward-compatible' macros implementing equivalents of 1.1 functions using older OpenSSL. In case some class contains a lot of version-specific ifdefs (particularly where nested #if-ery was complex) we choose to split code into: "pre11" h/cpp files, "shared" h/cpp files (they preserve their original names, e.g qsslsocket_openssl.cpp) and "11" h/cpp files. If in future we remove the legacy back-end, "pre11" should be removed; "shared" and "11" parts - merged. 2. Configuration. We introduced a new feature 'opensslv11' which complements the pre-existing 'openssl' and 'openssl-linked' features. The 'opensslv11' feature is enabled by a simple test which either compiles successfully or ends in a compilation error, depending on a value of the OPENSSL_VERSION_NUMBER constant. If the feature was enabled, we also append an additional compilation flag -DOPENSSL_API_COMPAT=0x10100000L to make sure our new code does not contain deprecated structures, function calls, macro-invocations from OpenSSL < 1.1. Change-Id: I2064efbe9685def5d2bb2233a66f7581954fb74a Reviewed-by: André Klitzing <aklitzing@gmail.com> Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
This commit is contained in:
parent
10de063ff1
commit
cfbe03a6e0
48
config.tests/unix/openssl11/openssl.cpp
Normal file
48
config.tests/unix/openssl11/openssl.cpp
Normal file
@ -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()
|
||||
{
|
||||
}
|
2
config.tests/unix/openssl11/openssl.pro
Normal file
2
config.tests/unix/openssl11/openssl.pro
Normal file
@ -0,0 +1,2 @@
|
||||
SOURCES = openssl.cpp
|
||||
CONFIG -= x11 qt
|
@ -105,6 +105,12 @@
|
||||
"type": "compile",
|
||||
"test": "unix/sctp",
|
||||
"use": "network"
|
||||
},
|
||||
"openssl11": {
|
||||
"label": "OpenSSL v. 1.1 support",
|
||||
"type": "compile",
|
||||
"test": "unix/openssl11",
|
||||
"use": "network"
|
||||
}
|
||||
},
|
||||
|
||||
@ -172,6 +178,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,
|
||||
|
@ -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);
|
||||
Q_ASSERT(pkey);
|
||||
|
||||
if (q_EVP_PKEY_type(pkey->type) == EVP_PKEY_RSA) {
|
||||
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 (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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
277
src/network/ssl/qsslcontext_openssl11.cpp
Normal file
277
src/network/ssl/qsslcontext_openssl11.cpp
Normal file
@ -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
|
354
src/network/ssl/qsslcontext_opensslpre11.cpp
Normal file
354
src/network/ssl/qsslcontext_opensslpre11.cpp
Normal file
@ -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
|
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
@ -84,33 +85,30 @@ void QSslKeyPrivate::clear(bool deep)
|
||||
|
||||
bool QSslKeyPrivate::fromEVP_PKEY(EVP_PKEY *pkey)
|
||||
{
|
||||
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
|
||||
@ -178,8 +176,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
|
||||
@ -273,7 +271,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;
|
||||
|
||||
@ -291,21 +295,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);
|
||||
}
|
||||
|
@ -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,
|
||||
@ -212,48 +134,6 @@ static unsigned int q_ssl_psk_server_callback(SSL *ssl,
|
||||
#endif
|
||||
} // 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_OPENSSL_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();
|
||||
}
|
||||
|
||||
QSslSocketBackendPrivate::QSslSocketBackendPrivate()
|
||||
: ssl(0),
|
||||
readBio(0),
|
||||
@ -269,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;
|
||||
|
||||
@ -310,7 +190,8 @@ QSslCipher QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(SSL_CIPHER *ciph
|
||||
}
|
||||
|
||||
// static
|
||||
inline QSslErrorEntry QSslErrorEntry::fromStoreContext(X509_STORE_CTX *ctx) {
|
||||
inline QSslErrorEntry QSslErrorEntry::fromStoreContext(X509_STORE_CTX *ctx)
|
||||
{
|
||||
return {
|
||||
q_X509_STORE_CTX_get_error(ctx),
|
||||
q_X509_STORE_CTX_get_error_depth(ctx)
|
||||
@ -324,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)
|
||||
@ -353,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;
|
||||
@ -438,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())
|
||||
@ -479,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)
|
||||
@ -505,16 +387,6 @@ void QSslSocketBackendPrivate::destroySslContext()
|
||||
sslContextPointer.clear();
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
void QSslSocketPrivate::deinitialize()
|
||||
{
|
||||
q_CRYPTO_set_id_callback(0);
|
||||
q_CRYPTO_set_locking_callback(0);
|
||||
q_ERR_free_strings();
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
|
||||
@ -527,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_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_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
|
||||
@ -628,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;
|
||||
@ -669,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;
|
||||
@ -705,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));
|
||||
|
||||
@ -739,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);
|
||||
}
|
||||
@ -1543,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();
|
||||
}
|
||||
|
||||
@ -1576,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();
|
||||
@ -1735,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);
|
||||
@ -1754,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()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1782,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);
|
||||
@ -1860,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);
|
||||
@ -1875,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);
|
||||
|
285
src/network/ssl/qsslsocket_openssl11.cpp
Normal file
285
src/network/ssl/qsslsocket_openssl11.cpp
Normal file
@ -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
|
132
src/network/ssl/qsslsocket_openssl11_symbols_p.h
Normal file
132
src/network/ssl/qsslsocket_openssl11_symbols_p.h
Normal file
@ -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
|
@ -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();
|
||||
|
@ -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,110 +137,78 @@ 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
|
||||
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);
|
||||
DEFINEFUNC4(long, BIO_ctrl, BIO *a, a, int b, b, long c, c, void *d, d, return -1, return)
|
||||
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(void, OPENSSL_free, void *ptr, ptr, return, DUMMYARG)
|
||||
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(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)
|
||||
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);
|
||||
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)
|
||||
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)
|
||||
#ifndef OPENSSL_NO_EC
|
||||
DEFINEFUNC2(int, EVP_PKEY_set1_EC_KEY, EVP_PKEY *a, a, EC_KEY *b, b, return -1, return)
|
||||
#endif
|
||||
DEFINEFUNC(void, EVP_PKEY_free, EVP_PKEY *a, a, return, DUMMYARG)
|
||||
DEFINEFUNC(DSA *, EVP_PKEY_get1_DSA, EVP_PKEY *a, a, return 0, return)
|
||||
DEFINEFUNC(RSA *, EVP_PKEY_get1_RSA, EVP_PKEY *a, a, return 0, return)
|
||||
#ifndef OPENSSL_NO_EC
|
||||
DEFINEFUNC(EC_KEY *, EVP_PKEY_get1_EC_KEY, EVP_PKEY *a, a, return 0, return)
|
||||
#endif
|
||||
DEFINEFUNC(EVP_PKEY *, EVP_PKEY_new, DUMMYARG, DUMMYARG, return 0, return)
|
||||
DEFINEFUNC(int, EVP_PKEY_type, int a, a, return NID_undef, return)
|
||||
DEFINEFUNC2(int, i2d_X509, X509 *a, a, unsigned char **b, b, return -1, return)
|
||||
DEFINEFUNC(const char *, OBJ_nid2sn, int a, a, return 0, return)
|
||||
DEFINEFUNC(const char *, OBJ_nid2ln, int a, a, return 0, return)
|
||||
DEFINEFUNC(int, OBJ_sn2nid, const char *s, s, return 0, return)
|
||||
DEFINEFUNC(int, OBJ_ln2nid, const char *s, s, return 0, return)
|
||||
DEFINEFUNC3(int, i2t_ASN1_OBJECT, char *a, a, int b, b, ASN1_OBJECT *c, c, return -1, return)
|
||||
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
|
||||
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)
|
||||
#ifndef OPENSSL_NO_EC
|
||||
DEFINEFUNC4(EC_KEY *, PEM_read_bio_ECPrivateKey, BIO *a, a, EC_KEY **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
|
||||
#endif
|
||||
DEFINEFUNC4(DH *, PEM_read_bio_DHparams, BIO *a, a, DH **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
|
||||
DEFINEFUNC7(int, PEM_write_bio_DSAPrivateKey, BIO *a, a, DSA *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)
|
||||
DEFINEFUNC7(int, PEM_write_bio_RSAPrivateKey, BIO *a, a, RSA *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)
|
||||
#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
|
||||
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)
|
||||
#ifndef OPENSSL_NO_EC
|
||||
DEFINEFUNC4(EC_KEY *, PEM_read_bio_EC_PUBKEY, BIO *a, a, EC_KEY **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
|
||||
#endif
|
||||
DEFINEFUNC2(int, PEM_write_bio_DSA_PUBKEY, BIO *a, a, DSA *b, b, return 0, return)
|
||||
DEFINEFUNC2(int, PEM_write_bio_RSA_PUBKEY, BIO *a, a, RSA *b, b, return 0, return)
|
||||
#ifndef OPENSSL_NO_EC
|
||||
DEFINEFUNC2(int, PEM_write_bio_EC_PUBKEY, BIO *a, a, EC_KEY *b, b, return 0, return)
|
||||
#endif
|
||||
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)
|
||||
#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)
|
||||
@ -250,70 +219,15 @@ 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)
|
||||
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)
|
||||
DEFINEFUNC(void, SSL_CTX_free, SSL_CTX *a, a, return, DUMMYARG)
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
|
||||
DEFINEFUNC(SSL_CTX *, SSL_CTX_new, const SSL_METHOD *a, a, return 0, return)
|
||||
#else
|
||||
DEFINEFUNC(SSL_CTX *, SSL_CTX_new, SSL_METHOD *a, a, return 0, return)
|
||||
#endif
|
||||
DEFINEFUNC2(int, SSL_CTX_set_cipher_list, SSL_CTX *a, a, const char *b, b, return -1, return)
|
||||
DEFINEFUNC(int, SSL_CTX_set_default_verify_paths, SSL_CTX *a, a, return -1, return)
|
||||
DEFINEFUNC3(void, SSL_CTX_set_verify, SSL_CTX *a, a, int b, b, int (*c)(int, X509_STORE_CTX *), c, return, DUMMYARG)
|
||||
DEFINEFUNC2(void, SSL_CTX_set_verify_depth, SSL_CTX *a, a, int b, b, return, DUMMYARG)
|
||||
DEFINEFUNC2(int, SSL_CTX_use_certificate, SSL_CTX *a, a, X509 *b, b, return -1, return)
|
||||
DEFINEFUNC3(int, SSL_CTX_use_certificate_file, SSL_CTX *a, a, const char *b, b, int c, c, return -1, return)
|
||||
DEFINEFUNC2(int, SSL_CTX_use_PrivateKey, SSL_CTX *a, a, EVP_PKEY *b, b, return -1, return)
|
||||
DEFINEFUNC2(int, SSL_CTX_use_RSAPrivateKey, SSL_CTX *a, a, RSA *b, b, return -1, return)
|
||||
DEFINEFUNC3(int, SSL_CTX_use_PrivateKey_file, SSL_CTX *a, a, const char *b, b, int c, c, return -1, return)
|
||||
DEFINEFUNC(X509_STORE *, SSL_CTX_get_cert_store, const SSL_CTX *a, a, return 0, return)
|
||||
DEFINEFUNC(void, SSL_free, SSL *a, a, return, DUMMYARG)
|
||||
DEFINEFUNC(STACK_OF(SSL_CIPHER) *, SSL_get_ciphers, const SSL *a, a, return 0, return)
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
|
||||
DEFINEFUNC(const SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return 0, return)
|
||||
#else
|
||||
DEFINEFUNC(SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return 0, return)
|
||||
#endif
|
||||
DEFINEFUNC(int, SSL_version, const SSL *a, a, return 0, return)
|
||||
DEFINEFUNC2(int, SSL_get_error, SSL *a, a, int b, b, return -1, return)
|
||||
DEFINEFUNC(STACK_OF(X509) *, SSL_get_peer_cert_chain, SSL *a, a, return 0, return)
|
||||
DEFINEFUNC(X509 *, SSL_get_peer_certificate, SSL *a, a, return 0, return)
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
|
||||
// 0.9.8 broke SC and BC by changing this function's signature.
|
||||
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
|
||||
#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)
|
||||
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)
|
||||
DEFINEFUNC3(void, SSL_set_bio, SSL *a, a, BIO *b, b, BIO *c, c, return, DUMMYARG)
|
||||
DEFINEFUNC(void, SSL_set_accept_state, SSL *a, a, return, DUMMYARG)
|
||||
DEFINEFUNC(void, SSL_set_connect_state, SSL *a, a, return, DUMMYARG)
|
||||
DEFINEFUNC(int, SSL_shutdown, SSL *a, a, return -1, return)
|
||||
DEFINEFUNC2(int, SSL_set_session, SSL* to, to, SSL_SESSION *session, session, return -1, return)
|
||||
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
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
|
||||
DEFINEFUNC2(void, SSL_set_psk_client_callback, SSL* ssl, ssl, q_psk_client_callback_t callback, callback, return, DUMMYARG)
|
||||
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
|
||||
#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)
|
||||
@ -357,8 +271,177 @@ DEFINEFUNC(SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return 0, retu
|
||||
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(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)
|
||||
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)
|
||||
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)
|
||||
|
||||
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)
|
||||
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(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(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)
|
||||
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)
|
||||
#ifndef OPENSSL_NO_EC
|
||||
DEFINEFUNC2(int, EVP_PKEY_set1_EC_KEY, EVP_PKEY *a, a, EC_KEY *b, b, return -1, return)
|
||||
#endif
|
||||
DEFINEFUNC(void, EVP_PKEY_free, EVP_PKEY *a, a, return, DUMMYARG)
|
||||
DEFINEFUNC(DSA *, EVP_PKEY_get1_DSA, EVP_PKEY *a, a, return 0, return)
|
||||
DEFINEFUNC(RSA *, EVP_PKEY_get1_RSA, EVP_PKEY *a, a, return 0, return)
|
||||
#ifndef OPENSSL_NO_EC
|
||||
DEFINEFUNC(EC_KEY *, EVP_PKEY_get1_EC_KEY, EVP_PKEY *a, a, return 0, return)
|
||||
#endif
|
||||
DEFINEFUNC(EVP_PKEY *, EVP_PKEY_new, DUMMYARG, DUMMYARG, return 0, return)
|
||||
DEFINEFUNC(int, EVP_PKEY_type, int a, a, return NID_undef, return)
|
||||
DEFINEFUNC2(int, i2d_X509, X509 *a, a, unsigned char **b, b, return -1, return)
|
||||
DEFINEFUNC(const char *, OBJ_nid2sn, int a, a, return 0, return)
|
||||
DEFINEFUNC(const char *, OBJ_nid2ln, int a, a, return 0, return)
|
||||
DEFINEFUNC(int, OBJ_sn2nid, const char *s, s, return 0, return)
|
||||
DEFINEFUNC(int, OBJ_ln2nid, const char *s, s, return 0, return)
|
||||
DEFINEFUNC3(int, i2t_ASN1_OBJECT, char *a, a, int b, b, ASN1_OBJECT *c, c, return -1, return)
|
||||
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)
|
||||
|
||||
#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)
|
||||
#ifndef OPENSSL_NO_EC
|
||||
DEFINEFUNC4(EC_KEY *, PEM_read_bio_ECPrivateKey, BIO *a, a, EC_KEY **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
|
||||
#endif
|
||||
DEFINEFUNC4(DH *, PEM_read_bio_DHparams, BIO *a, a, DH **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
|
||||
DEFINEFUNC7(int, PEM_write_bio_DSAPrivateKey, BIO *a, a, DSA *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)
|
||||
DEFINEFUNC7(int, PEM_write_bio_RSAPrivateKey, BIO *a, a, RSA *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)
|
||||
#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 // !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)
|
||||
#ifndef OPENSSL_NO_EC
|
||||
DEFINEFUNC4(EC_KEY *, PEM_read_bio_EC_PUBKEY, BIO *a, a, EC_KEY **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
|
||||
#endif
|
||||
DEFINEFUNC2(int, PEM_write_bio_DSA_PUBKEY, BIO *a, a, DSA *b, b, return 0, return)
|
||||
DEFINEFUNC2(int, PEM_write_bio_RSA_PUBKEY, BIO *a, a, RSA *b, b, return 0, return)
|
||||
#ifndef OPENSSL_NO_EC
|
||||
DEFINEFUNC2(int, PEM_write_bio_EC_PUBKEY, BIO *a, a, EC_KEY *b, b, return 0, return)
|
||||
#endif
|
||||
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, SSL_accept, SSL *a, a, return -1, return)
|
||||
DEFINEFUNC(int, SSL_clear, SSL *a, a, return -1, 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)
|
||||
DEFINEFUNC(void, SSL_CTX_free, SSL_CTX *a, a, return, DUMMYARG)
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
|
||||
DEFINEFUNC(SSL_CTX *, SSL_CTX_new, const SSL_METHOD *a, a, return 0, return)
|
||||
#else
|
||||
DEFINEFUNC(SSL_CTX *, SSL_CTX_new, SSL_METHOD *a, a, return 0, return)
|
||||
#endif
|
||||
DEFINEFUNC2(int, SSL_CTX_set_cipher_list, SSL_CTX *a, a, const char *b, b, return -1, return)
|
||||
DEFINEFUNC(int, SSL_CTX_set_default_verify_paths, SSL_CTX *a, a, return -1, return)
|
||||
DEFINEFUNC3(void, SSL_CTX_set_verify, SSL_CTX *a, a, int b, b, int (*c)(int, X509_STORE_CTX *), c, return, DUMMYARG)
|
||||
DEFINEFUNC2(void, SSL_CTX_set_verify_depth, SSL_CTX *a, a, int b, b, return, DUMMYARG)
|
||||
DEFINEFUNC2(int, SSL_CTX_use_certificate, SSL_CTX *a, a, X509 *b, b, return -1, return)
|
||||
DEFINEFUNC3(int, SSL_CTX_use_certificate_file, SSL_CTX *a, a, const char *b, b, int c, c, return -1, return)
|
||||
DEFINEFUNC2(int, SSL_CTX_use_PrivateKey, SSL_CTX *a, a, EVP_PKEY *b, b, return -1, return)
|
||||
DEFINEFUNC2(int, SSL_CTX_use_RSAPrivateKey, SSL_CTX *a, a, RSA *b, b, return -1, return)
|
||||
DEFINEFUNC3(int, SSL_CTX_use_PrivateKey_file, SSL_CTX *a, a, const char *b, b, int c, c, return -1, return)
|
||||
DEFINEFUNC(X509_STORE *, SSL_CTX_get_cert_store, const SSL_CTX *a, a, return 0, return)
|
||||
DEFINEFUNC(void, SSL_free, SSL *a, a, return, DUMMYARG)
|
||||
DEFINEFUNC(STACK_OF(SSL_CIPHER) *, SSL_get_ciphers, const SSL *a, a, return 0, return)
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
|
||||
DEFINEFUNC(const SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return 0, return)
|
||||
#else
|
||||
DEFINEFUNC(SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return 0, return)
|
||||
#endif
|
||||
DEFINEFUNC(int, SSL_version, const SSL *a, a, return 0, return)
|
||||
DEFINEFUNC2(int, SSL_get_error, SSL *a, a, int b, b, return -1, return)
|
||||
DEFINEFUNC(STACK_OF(X509) *, SSL_get_peer_cert_chain, SSL *a, a, return 0, return)
|
||||
DEFINEFUNC(X509 *, SSL_get_peer_certificate, SSL *a, a, return 0, return)
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
|
||||
// 0.9.8 broke SC and BC by changing this function's signature.
|
||||
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(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)
|
||||
DEFINEFUNC3(void, SSL_set_bio, SSL *a, a, BIO *b, b, BIO *c, c, return, DUMMYARG)
|
||||
DEFINEFUNC(void, SSL_set_accept_state, SSL *a, a, return, DUMMYARG)
|
||||
DEFINEFUNC(void, SSL_set_connect_state, SSL *a, a, return, DUMMYARG)
|
||||
DEFINEFUNC(int, SSL_shutdown, SSL *a, a, return -1, return)
|
||||
DEFINEFUNC2(int, SSL_set_session, SSL* to, to, SSL_SESSION *session, session, return -1, return)
|
||||
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
|
||||
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
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
|
||||
DEFINEFUNC2(void, SSL_set_psk_client_callback, SSL* ssl, ssl, q_psk_client_callback_t callback, callback, return, DUMMYARG)
|
||||
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
|
||||
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
|
||||
@ -382,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)
|
||||
@ -397,26 +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(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)
|
||||
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)
|
||||
@ -699,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);
|
||||
@ -759,7 +825,11 @@ 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;
|
||||
@ -776,17 +846,148 @@ 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)
|
||||
RESOLVEFUNC(BIO_new_file)
|
||||
RESOLVEFUNC(ERR_clear_error)
|
||||
RESOLVEFUNC(OPENSSL_free)
|
||||
RESOLVEFUNC(BIO_free)
|
||||
RESOLVEFUNC(BIO_new)
|
||||
RESOLVEFUNC(BIO_new_mem_buf)
|
||||
@ -802,26 +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_peek_last_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)
|
||||
@ -843,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)
|
||||
@ -858,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)
|
||||
@ -874,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)
|
||||
@ -907,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)
|
||||
@ -921,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
|
||||
@ -931,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)
|
||||
@ -970,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)
|
||||
@ -991,21 +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(CONF_get1_default_config_file)
|
||||
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)
|
||||
@ -1029,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)
|
||||
|
@ -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,20 +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);
|
||||
BIO *q_BIO_new_file(const char *filename, const char *mode);
|
||||
void q_ERR_clear_error();
|
||||
void q_OPENSSL_free(void *ptr);
|
||||
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
|
||||
@ -250,27 +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();
|
||||
unsigned long q_ERR_peek_last_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);
|
||||
@ -314,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);
|
||||
@ -330,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);
|
||||
@ -378,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);
|
||||
@ -392,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
|
||||
@ -403,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
|
||||
@ -456,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);
|
||||
@ -475,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);
|
||||
@ -492,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();
|
||||
@ -526,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))
|
||||
@ -562,19 +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()
|
||||
char *q_CONF_get1_default_config_file();
|
||||
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);
|
||||
|
||||
|
424
src/network/ssl/qsslsocket_opensslpre11.cpp
Normal file
424
src/network/ssl/qsslsocket_opensslpre11.cpp
Normal file
@ -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
|
230
src/network/ssl/qsslsocket_opensslpre11_symbols_p.h
Normal file
230
src/network/ssl/qsslsocket_opensslpre11_symbols_p.h
Normal file
@ -0,0 +1,230 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2017 The Qt Company Ltd.
|
||||
** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
|
||||
** 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_OPENSSLPRE11_SYMBOLS_P_H
|
||||
#define QSSLSOCKET_OPENSSLPRE11_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
|
||||
|
||||
unsigned char * q_ASN1_STRING_data(ASN1_STRING *a);
|
||||
BIO *q_BIO_new_file(const char *filename, const char *mode);
|
||||
void q_ERR_clear_error();
|
||||
Q_AUTOTEST_EXPORT BIO *q_BIO_new(BIO_METHOD *a);
|
||||
Q_AUTOTEST_EXPORT BIO_METHOD *q_BIO_s_mem();
|
||||
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);
|
||||
unsigned long q_ERR_peek_last_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);
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
|
||||
typedef _STACK STACK;
|
||||
#endif
|
||||
|
||||
// The typedef we use to make our pre 1.1 code look more like 1.1 (less ifdefs).
|
||||
typedef STACK OPENSSL_STACK;
|
||||
|
||||
// We resolve q_sk_ functions, but use q_OPENSSL_sk_ macros in code to reduce
|
||||
// the amount of #ifdefs.
|
||||
int q_sk_num(STACK *a);
|
||||
#define q_OPENSSL_sk_num(a) q_sk_num(a)
|
||||
void q_sk_pop_free(STACK *a, void (*b)(void *));
|
||||
#define q_OPENSSL_sk_pop_free(a, b) q_sk_pop_free(a, b)
|
||||
STACK *q_sk_new_null();
|
||||
#define q_OPENSSL_sk_new_null() q_sk_new_null()
|
||||
|
||||
void q_sk_free(STACK *a);
|
||||
|
||||
// Just a name alias (not a function call expression) since in code we take an
|
||||
// address of this:
|
||||
#define q_OPENSSL_sk_free q_sk_free
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
|
||||
void *q_sk_value(STACK *a, int b);
|
||||
void q_sk_push(STACK *st, void *data);
|
||||
#else
|
||||
char *q_sk_value(STACK *a, int b);
|
||||
void q_sk_push(STACK *st, char *data);
|
||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10000000L
|
||||
|
||||
#define q_OPENSSL_sk_value(a, b) q_sk_value(a, b)
|
||||
#define q_OPENSSL_sk_push(st, data) q_sk_push(st, data)
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
|
||||
SSL_CTX *q_SSL_CTX_new(const SSL_METHOD *a);
|
||||
#else
|
||||
SSL_CTX *q_SSL_CTX_new(SSL_METHOD *a);
|
||||
#endif
|
||||
|
||||
int q_SSL_library_init();
|
||||
void q_SSL_load_error_strings();
|
||||
|
||||
#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);
|
||||
#endif
|
||||
|
||||
#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
|
||||
|
||||
STACK_OF(X509) *q_X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx);
|
||||
|
||||
#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 // SSLEAY_MACROS
|
||||
|
||||
#define q_SSL_CTX_set_options(ctx,op) q_SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,(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_X509_getm_notAfter(x) X509_get_notAfter(x)
|
||||
#define q_X509_getm_notBefore(x) X509_get_notBefore(x)
|
||||
|
||||
// "Forward compatibility" with OpenSSL 1.1 (to save on #if-ery elsewhere):
|
||||
#define q_X509_get_version(x509) q_ASN1_INTEGER_get((x509)->cert_info->version)
|
||||
#define q_ASN1_STRING_get0_data(x) q_ASN1_STRING_data(x)
|
||||
#define q_EVP_PKEY_base_id(pkey) ((pkey)->type)
|
||||
#define q_X509_get_pubkey(x509) q_X509_PUBKEY_get((x509)->cert_info->key)
|
||||
#define q_SSL_SESSION_get_ticket_lifetime_hint(s) ((s)->tlsext_tick_lifetime_hint)
|
||||
#define q_RSA_bits(rsa) q_BN_num_bits((rsa)->n)
|
||||
#define q_DSA_bits(dsa) q_BN_num_bits((dsa)->p)
|
||||
#define q_X509_STORE_set_verify_cb(s,c) X509_STORE_set_verify_cb_func((s),(c))
|
||||
|
||||
char *q_CONF_get1_default_config_file();
|
||||
void q_OPENSSL_add_all_algorithms_noconf();
|
||||
void q_OPENSSL_add_all_algorithms_conf();
|
||||
|
||||
long q_SSLeay();
|
||||
const char *q_SSLeay_version(int type);
|
||||
|
||||
|
||||
#endif // QSSLSOCKET_OPENSSL_PRE11_SYMBOLS_P_H
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user