QSslSocket - remove old OpenSSL backend (< 1.1)

OpenSSL 1.0.2 will stop receiving all support at the end
of 2019. Qt 5.15 is our next LTS thus makes sense remove
OpenSSL 1.0.2 support there. This also allows us quite
a significant cleanup of an old heavily if-defed code
and all 'pre11' suffixed source files.

[ChangeLog][QtNetwork][SSL] Removed OpenSSL 1.0.x support, now 1.1.x is required

Change-Id: I70c70c56cbd8aeff793afe793335696d1b1b7408
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
Timur Pocheptsov 2019-09-27 13:04:54 +02:00
parent 7a13a09116
commit 1a878e65c2
22 changed files with 916 additions and 2570 deletions

View File

@ -61,11 +61,11 @@
"export": "openssl",
"test": {
"tail": [
"#if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER-0 < 0x10000000L",
"# error OpenSSL >= 1.0.0 is required",
"#if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER-0 < 0x10100000L",
"# error OpenSSL >= 1.1.0 is required",
"#endif",
"#if OPENSSL_VERSION_NUMBER-0 >= 0x10002000L && !defined(OPENSSL_NO_EC) && !defined(SSL_CTRL_SET_CURVES)",
"# error OpenSSL was reported as >= 1.0.2 but is missing required features, possibly it's libressl which is unsupported",
"#if !defined(OPENSSL_NO_EC) && !defined(SSL_CTRL_SET_CURVES)",
"# error OpenSSL was reported as >= 1.1.0 but is missing required features, possibly it's libressl which is unsupported",
"#endif"
]
},
@ -185,19 +185,6 @@
},
"use": "network"
},
"openssl11": {
"label": "OpenSSL 1.1 support",
"type": "compile",
"test": {
"include": "openssl/opensslv.h",
"tail": [
"#if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER-0 < 0x10100000L",
"# error OpenSSL >= 1.1 is required",
"#endif"
]
},
"use": "openssl"
},
"dtls": {
"label": "DTLS support in OpenSSL",
"type": "compile",
@ -335,7 +322,7 @@
},
"opensslv11": {
"label": "OpenSSL 1.1",
"condition": "features.openssl && tests.openssl11",
"condition": "features.openssl",
"output": [ "publicFeature" ]
},
"sctp": {

View File

@ -156,8 +156,6 @@ void delete_connection(SSL *ssl)
q_SSL_free(ssl);
}
#if QT_CONFIG(opensslv11)
void delete_BIO_ADDR(BIO_ADDR *bio)
{
// A deleter for QSharedPointer<BIO_ADDR>
@ -172,8 +170,6 @@ void delete_bio_method(BIO_METHOD *method)
q_BIO_meth_free(method);
}
#endif // openssl 1.1
// The 'deleter' for QScopedPointer<BIO>.
struct bio_deleter
{
@ -411,10 +407,6 @@ extern "C" long q_dgram_ctrl(BIO *bio, int cmd, long num, void *ptr)
auto dtls = static_cast<dtlsopenssl::DtlsState *>(q_BIO_get_app_data(bio));
Q_ASSERT(dtls);
#if !QT_CONFIG(opensslv11)
Q_UNUSED(num)
#endif
switch (cmd) {
// Let's start from the most generic ones, in the order in which they are
// documented (as BIO_ctrl):
@ -578,11 +570,9 @@ extern "C" long q_dgram_ctrl(BIO *bio, int cmd, long num, void *ptr)
// so that OpenSSL does not start suddenly fragmenting the first
// client hello (which will result in DTLSv1_listen rejecting it).
return 0;
#if QT_CONFIG(opensslv11)
case BIO_CTRL_DGRAM_SET_PEEK_MODE:
dtls->peeking = num;
return 1;
#endif
default:;
#if QT_DTLS_VERBOSE
qWarning() << "Unexpected cmd (" << cmd << ")";
@ -594,15 +584,11 @@ extern "C" long q_dgram_ctrl(BIO *bio, int cmd, long num, void *ptr)
extern "C" int q_dgram_create(BIO *bio)
{
#if QT_CONFIG(opensslv11)
q_BIO_set_init(bio, 1);
#else
bio->init = 1;
#endif
// With a custom BIO you'd normally allocate some implementation-specific
// data and append it to this new BIO: bio->ptr = ... (pre 1.0.2) or
// BIO_set_data (1.1). We don't need it and thus q_dgram_destroy below
// is a noop.
// data and append it to this new BIO using BIO_set_data. We don't need
// it and thus q_dgram_destroy below is a noop.
return 1;
}
@ -614,39 +600,6 @@ extern "C" int q_dgram_destroy(BIO *bio)
const char * const qdtlsMethodName = "qdtlsbio";
#if !QT_CONFIG(opensslv11)
/*
typedef struct bio_method_st {
int type;
const char *name;
int (*bwrite) (BIO *, const char *, int);
int (*bread) (BIO *, char *, int);
int (*bputs) (BIO *, const char *);
int (*bgets) (BIO *, char *, int);
long (*ctrl) (BIO *, int, long, void *);
int (*create) (BIO *);
int (*destroy) (BIO *);
long (*callback_ctrl) (BIO *, int, bio_info_cb *);
} BIO_METHOD;
*/
bio_method_st qdtlsCustomBioMethod =
{
BIO_TYPE_DGRAM,
qdtlsMethodName,
q_dgram_write,
q_dgram_read,
q_dgram_puts,
nullptr,
q_dgram_ctrl,
q_dgram_create,
q_dgram_destroy,
nullptr
};
#endif // openssl < 1.1
} // namespace dtlsbio
namespace dtlsopenssl
@ -777,7 +730,6 @@ bool DtlsState::initBIO(QDtlsBasePrivate *dtlsBase)
Q_ASSERT(dtlsBase);
Q_ASSERT(tlsContext.data() && tlsConnection.data());
#if QT_CONFIG(opensslv11)
BioMethod customMethod(q_BIO_meth_new(BIO_TYPE_DGRAM, dtlsbio::qdtlsMethodName),
dtlsutil::delete_bio_method);
if (!customMethod.data()) {
@ -793,9 +745,6 @@ bool DtlsState::initBIO(QDtlsBasePrivate *dtlsBase)
q_BIO_meth_set_write(biom, dtlsbio::q_dgram_write);
q_BIO_meth_set_puts(biom, dtlsbio::q_dgram_puts);
q_BIO_meth_set_ctrl(biom, dtlsbio::q_dgram_ctrl);
#else
BIO_METHOD *biom = &dtlsbio::qdtlsCustomBioMethod;
#endif // openssl 1.1
QScopedPointer<BIO, dtlsutil::bio_deleter> newBio(q_BIO_new(biom));
BIO *bio = newBio.data();
@ -808,9 +757,7 @@ bool DtlsState::initBIO(QDtlsBasePrivate *dtlsBase)
q_SSL_set_bio(tlsConnection.data(), bio, bio);
newBio.take();
#if QT_CONFIG(opensslv11)
bioMethod.swap(customMethod);
#endif // openssl 1.1
return true;
}
@ -869,7 +816,6 @@ bool QDtlsClientVerifierOpenSSL::verifyClient(QUdpSocket *socket, const QByteArr
dtls.hashAlgorithm = hashAlgorithm;
Q_ASSERT(dtls.tlsConnection.data());
#if QT_CONFIG(opensslv11)
QSharedPointer<BIO_ADDR> peer(q_BIO_ADDR_new(), dtlsutil::delete_BIO_ADDR);
if (!peer.data()) {
setDtlsError(QDtlsError::TlsInitializationError,
@ -883,10 +829,7 @@ bool QDtlsClientVerifierOpenSSL::verifyClient(QUdpSocket *socket, const QByteArr
setDtlsError(QDtlsError::TlsFatalError, QSslSocketBackendPrivate::getErrorsFromOpenSsl());
return false;
}
#else
qt_sockaddr peer;
const int ret = q_DTLSv1_listen(dtls.tlsConnection.data(), &peer);
#endif
if (ret > 0) {
verifiedClientHello = dgram;
return true;
@ -953,7 +896,6 @@ bool QDtlsPrivateOpenSSL::startHandshake(QUdpSocket *socket, const QByteArray &d
// surprise DTLS/OpenSSL (such a message would be disregarded as
// 'stale or future' in SSL_accept otherwise):
int result = 0;
#if QT_CONFIG(opensslv11)
QSharedPointer<BIO_ADDR> peer(q_BIO_ADDR_new(), dtlsutil::delete_BIO_ADDR);
if (!peer.data()) {
setDtlsError(QDtlsError::TlsInitializationError,
@ -967,10 +909,7 @@ bool QDtlsPrivateOpenSSL::startHandshake(QUdpSocket *socket, const QByteArray &d
dtls.writeSuppressed = true;
result = q_DTLSv1_listen(dtls.tlsConnection.data(), peer.data());
dtls.writeSuppressed = false;
#else
qt_sockaddr peer;
result = q_DTLSv1_listen(dtls.tlsConnection.data(), &peer);
#endif
if (result <= 0) {
setDtlsError(QDtlsError::TlsFatalError,
QDtls::tr("Cannot start the handshake, verified client hello expected"));

View File

@ -84,9 +84,8 @@ namespace dtlsopenssl
class DtlsState
{
public:
// Note, bioMethod, if allocated (i.e. OpenSSL version >= 1.1) _must_
// outlive BIOs it was used to create. Thus the order of declarations
// here matters.
// Note, bioMethod _must_ outlive BIOs it was used to create. Thus
// the order of declarations here matters.
using BioMethod = QSharedPointer<BIO_METHOD>;
BioMethod bioMethod;

View File

@ -3,6 +3,7 @@
** 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.
@ -39,21 +40,49 @@
**
****************************************************************************/
#include <QtNetwork/qsslsocket.h>
#include <QtNetwork/qssldiffiehellmanparameters.h>
#include "private/qssl_p.h"
#include "private/qsslsocket_p.h"
#include "private/qsslcontext_openssl_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();
#if QT_CONFIG(dtls)
// defined in qdtls_openssl.cpp:
namespace dtlscallbacks
{
extern "C" int q_X509DtlsCallback(int ok, X509_STORE_CTX *ctx);
extern "C" int q_generate_cookie_callback(SSL *ssl, unsigned char *dst,
unsigned *cookieLength);
extern "C" int q_verify_cookie_callback(SSL *ssl, const unsigned char *cookie,
unsigned cookieLength);
}
#endif // dtls
// Defined in qsslsocket.cpp
QList<QSslCipher> q_getDefaultDtlsCiphers();
static inline QString msgErrorSettingBackendConfig(const QString &why)
{
return QSslSocket::tr("Error when setting the OpenSSL configuration (%1)").arg(why);
}
static inline QString msgErrorSettingEllipticCurves(const QString &why)
{
return QSslSocket::tr("Error when setting the elliptic curves (%1)").arg(why);
}
QSslContext::QSslContext()
: ctx(nullptr),
pkey(nullptr),
@ -89,7 +118,7 @@ QSharedPointer<QSslContext> QSslContext::sharedFromConfiguration(QSslSocket::Ssl
return sslContext;
}
#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG)
#ifndef OPENSSL_NO_NEXTPROTONEG
static int next_proto_cb(SSL *, unsigned char **out, unsigned char *outlen,
const unsigned char *in, unsigned int inlen, void *arg)
@ -126,7 +155,9 @@ QSslContext::NPNContext QSslContext::npnContext() const
{
return m_npnContext;
}
#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ...
#endif // !OPENSSL_NO_NEXTPROTONEG
// Needs to be deleted by caller
SSL* QSslContext::createSsl()
@ -150,7 +181,7 @@ SSL* QSslContext::createSsl()
}
}
#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG)
#ifndef OPENSSL_NO_NEXTPROTONEG
QList<QByteArray> protocols = sslConfiguration.d->nextAllowedProtocols;
if (!protocols.isEmpty()) {
m_supportedNPNVersions.clear();
@ -168,27 +199,22 @@ SSL* QSslContext::createSsl()
m_npnContext.data = reinterpret_cast<unsigned char *>(m_supportedNPNVersions.data());
m_npnContext.len = m_supportedNPNVersions.count();
m_npnContext.status = QSslConfiguration::NextProtocolNegotiationNone;
#if OPENSSL_VERSION_NUMBER >= 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').
// We just re-use our NPN callback and cast here:
typedef int (*alpn_callback_t) (SSL *, const unsigned char **, unsigned char *,
const unsigned char *, unsigned int, void *);
// With ALPN callback is for a server side only, for a client m_npnContext.status
// will stay in NextProtocolNegotiationNone.
q_SSL_CTX_set_alpn_select_cb(ctx, alpn_callback_t(next_proto_cb), &m_npnContext);
// Client:
q_SSL_set_alpn_protos(ssl, m_npnContext.data, m_npnContext.len);
}
#endif // OPENSSL_VERSION_NUMBER >= 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').
// We just re-use our NPN callback and cast here:
typedef int (*alpn_callback_t) (SSL *, const unsigned char **, unsigned char *,
const unsigned char *, unsigned int, void *);
// With ALPN callback is for a server side only, for a client m_npnContext.status
// will stay in NextProtocolNegotiationNone.
q_SSL_CTX_set_alpn_select_cb(ctx, alpn_callback_t(next_proto_cb), &m_npnContext);
// Client:
q_SSL_set_alpn_protos(ssl, m_npnContext.data, m_npnContext.len);
// And in case our peer does not support ALPN, but supports NPN:
q_SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &m_npnContext);
}
}
#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ...
#endif // !OPENSSL_NO_NEXTPROTONEG
return ssl;
}
@ -247,6 +273,392 @@ QString QSslContext::errorString() const
return errorStr;
}
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;
bool isDtls = 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 if (sslContext->sslConfiguration.protocol() == QSsl::SslV3) {
// SSL 3 is no longer supported, but chosen deliberately -> error
sslContext->ctx = nullptr;
unsupportedProtocol = true;
} else {
switch (sslContext->sslConfiguration.protocol()) {
case QSsl::DtlsV1_0:
case QSsl::DtlsV1_0OrLater:
case QSsl::DtlsV1_2:
case QSsl::DtlsV1_2OrLater:
#if QT_CONFIG(dtls)
isDtls = true;
sslContext->ctx = q_SSL_CTX_new(client ? q_DTLS_client_method() : q_DTLS_server_method());
#else // dtls
sslContext->ctx = nullptr;
unsupportedProtocol = true;
qCWarning(lcSsl, "DTLS protocol requested, but feature 'dtls' is disabled");
#endif // dtls
break;
case QSsl::TlsV1_3:
case QSsl::TlsV1_3OrLater:
#if !defined(TLS1_3_VERSION)
qCWarning(lcSsl, "TLS 1.3 is not supported");
sslContext->ctx = nullptr;
unsupportedProtocol = true;
break;
#endif // TLS1_3_VERSION
default:
// 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;
}
const long anyVersion =
#if QT_CONFIG(dtls)
isDtls ? DTLS_ANY_VERSION : TLS_ANY_VERSION;
#else
TLS_ANY_VERSION;
#endif // dtls
long minVersion = anyVersion;
long maxVersion = anyVersion;
switch (sslContext->sslConfiguration.protocol()) {
case QSsl::TlsV1_0:
minVersion = TLS1_VERSION;
maxVersion = TLS1_VERSION;
break;
case QSsl::TlsV1_1:
minVersion = TLS1_1_VERSION;
maxVersion = TLS1_1_VERSION;
break;
case QSsl::TlsV1_2:
minVersion = TLS1_2_VERSION;
maxVersion = TLS1_2_VERSION;
break;
case QSsl::TlsV1_3:
#ifdef TLS1_3_VERSION
minVersion = TLS1_3_VERSION;
maxVersion = TLS1_3_VERSION;
#else
// This protocol is not supported by OpenSSL 1.1 and we handle
// it as an error (see the code above).
Q_UNREACHABLE();
#endif // TLS1_3_VERSION
break;
// Ranges:
case QSsl::TlsV1SslV3:
case QSsl::AnyProtocol:
case QSsl::SecureProtocols:
case QSsl::TlsV1_0OrLater:
minVersion = TLS1_VERSION;
maxVersion = 0;
break;
case QSsl::TlsV1_1OrLater:
minVersion = TLS1_1_VERSION;
maxVersion = 0;
break;
case QSsl::TlsV1_2OrLater:
minVersion = TLS1_2_VERSION;
maxVersion = 0;
break;
case QSsl::DtlsV1_0:
minVersion = DTLS1_VERSION;
maxVersion = DTLS1_VERSION;
break;
case QSsl::DtlsV1_0OrLater:
minVersion = DTLS1_VERSION;
maxVersion = DTLS_MAX_VERSION;
break;
case QSsl::DtlsV1_2:
minVersion = DTLS1_2_VERSION;
maxVersion = DTLS1_2_VERSION;
break;
case QSsl::DtlsV1_2OrLater:
minVersion = DTLS1_2_VERSION;
maxVersion = DTLS_MAX_VERSION;
break;
case QSsl::TlsV1_3OrLater:
#ifdef TLS1_3_VERSION
minVersion = TLS1_3_VERSION;
maxVersion = 0;
break;
#else
// This protocol is not supported by OpenSSL 1.1 and we handle
// it as an error (see the code above).
Q_UNREACHABLE();
break;
#endif // TLS1_3_VERSION
case QSsl::SslV2:
case QSsl::SslV3:
// These protocols are not supported, and we handle
// them as an error (see the code above).
Q_UNREACHABLE();
break;
case QSsl::UnknownProtocol:
break;
}
if (minVersion != anyVersion
&& !q_SSL_CTX_set_min_proto_version(sslContext->ctx, minVersion)) {
sslContext->errorStr = QSslSocket::tr("Error while setting the minimal protocol version");
sslContext->errorCode = QSslError::UnspecifiedError;
return;
}
if (maxVersion != anyVersion
&& !q_SSL_CTX_set_max_proto_version(sslContext->ctx, maxVersion)) {
sslContext->errorStr = QSslSocket::tr("Error while setting the maximum protocol version");
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);
auto filterCiphers = [](const QList<QSslCipher> &ciphers, bool selectTls13)
{
QByteArray cipherString;
bool first = true;
for (const QSslCipher &cipher : qAsConst(ciphers)) {
const bool isTls13Cipher = cipher.protocol() == QSsl::TlsV1_3 || cipher.protocol() == QSsl::TlsV1_3OrLater;
if (selectTls13 != isTls13Cipher)
continue;
if (first)
first = false;
else
cipherString.append(':');
cipherString.append(cipher.name().toLatin1());
}
return cipherString;
};
// Initialize ciphers
QList<QSslCipher> ciphers = sslContext->sslConfiguration.ciphers();
if (ciphers.isEmpty())
ciphers = isDtls ? q_getDefaultDtlsCiphers() : QSslSocketPrivate::defaultCiphers();
const QByteArray preTls13Ciphers = filterCiphers(ciphers, false);
if (preTls13Ciphers.size()) {
if (!q_SSL_CTX_set_cipher_list(sslContext->ctx, preTls13Ciphers.data())) {
sslContext->errorStr = QSslSocket::tr("Invalid or empty cipher list (%1)").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
sslContext->errorCode = QSslError::UnspecifiedError;
return;
}
}
const QByteArray tls13Ciphers = filterCiphers(ciphers, true);
#ifdef TLS1_3_VERSION
if (tls13Ciphers.size()) {
if (!q_SSL_CTX_set_ciphersuites(sslContext->ctx, tls13Ciphers.data())) {
sslContext->errorStr = QSslSocket::tr("Invalid or empty cipher list (%1)").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
sslContext->errorCode = QSslError::UnspecifiedError;
return;
}
}
#endif // TLS1_3_VERSION
if (!preTls13Ciphers.size() && !tls13Ciphers.size()) {
sslContext->errorStr = QSslSocket::tr("Invalid or empty cipher list (%1)").arg(QStringLiteral(""));
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,
#if QT_CONFIG(dtls)
isDtls ? dtlscallbacks::q_X509DtlsCallback :
#endif // dtls
q_X509Callback);
}
#if QT_CONFIG(dtls)
if (mode == QSslSocket::SslServerMode && isDtls && configuration.dtlsCookieVerificationEnabled()) {
q_SSL_CTX_set_cookie_generate_cb(sslContext->ctx, dtlscallbacks::q_generate_cookie_callback);
q_SSL_CTX_set_cookie_verify_cb(sslContext->ctx, dtlscallbacks::q_verify_cookie_callback);
}
#endif // dtls
// 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 &params = dhparams.d->derData;
const char *ptr = params.constData();
DH *dh = q_d2i_DHparams(nullptr, reinterpret_cast<const unsigned char **>(&ptr),
params.length());
if (dh == nullptr)
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;
return;
#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;
return;
}
#endif
}
applyBackendConfig(sslContext);
}
#if QT_CONFIG(ocsp)
extern "C" int qt_OCSP_status_server_callback(SSL *ssl, void *); // Defined in qsslsocket_openssl.cpp.
#endif // ocsp
@ -269,65 +681,55 @@ void QSslContext::applyBackendConfig(QSslContext *sslContext)
}
#endif // ocsp
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
if (QSslSocket::sslLibraryVersionNumber() >= 0x10002000L) {
QSharedPointer<SSL_CONF_CTX> cctx(q_SSL_CONF_CTX_new(), &q_SSL_CONF_CTX_free);
if (cctx) {
q_SSL_CONF_CTX_set_ssl_ctx(cctx.data(), sslContext->ctx);
q_SSL_CONF_CTX_set_flags(cctx.data(), SSL_CONF_FLAG_FILE);
QSharedPointer<SSL_CONF_CTX> cctx(q_SSL_CONF_CTX_new(), &q_SSL_CONF_CTX_free);
if (cctx) {
q_SSL_CONF_CTX_set_ssl_ctx(cctx.data(), sslContext->ctx);
q_SSL_CONF_CTX_set_flags(cctx.data(), SSL_CONF_FLAG_FILE);
for (auto i = conf.constBegin(); i != conf.constEnd(); ++i) {
if (i.key() == "Qt-OCSP-response") // This never goes to SSL_CONF_cmd().
continue;
if (!i.value().canConvert(QMetaType::QByteArray)) {
sslContext->errorCode = QSslError::UnspecifiedError;
sslContext->errorStr = msgErrorSettingBackendConfig(
QSslSocket::tr("Expecting QByteArray for %1").arg(
QString::fromUtf8(i.key())));
return;
}
const QByteArray &value = i.value().toByteArray();
const int result = q_SSL_CONF_cmd(cctx.data(), i.key().constData(), value.constData());
if (result == 2)
continue;
for (auto i = conf.constBegin(); i != conf.constEnd(); ++i) {
if (i.key() == "Qt-OCSP-response") // This never goes to SSL_CONF_cmd().
continue;
if (!i.value().canConvert(QMetaType::QByteArray)) {
sslContext->errorCode = QSslError::UnspecifiedError;
switch (result) {
case 0:
sslContext->errorStr = msgErrorSettingBackendConfig(
QSslSocket::tr("An error occurred attempting to set %1 to %2").arg(
QString::fromUtf8(i.key()), QString::fromUtf8(value)));
return;
case 1:
sslContext->errorStr = msgErrorSettingBackendConfig(
QSslSocket::tr("Wrong value for %1 (%2)").arg(
QString::fromUtf8(i.key()), QString::fromUtf8(value)));
return;
default:
sslContext->errorStr = msgErrorSettingBackendConfig(
QSslSocket::tr("Unrecognized command %1 = %2").arg(
QString::fromUtf8(i.key()), QString::fromUtf8(value)));
return;
}
sslContext->errorStr = msgErrorSettingBackendConfig(
QSslSocket::tr("Expecting QByteArray for %1").arg(
QString::fromUtf8(i.key())));
return;
}
if (q_SSL_CONF_CTX_finish(cctx.data()) == 0) {
sslContext->errorStr = msgErrorSettingBackendConfig(QSslSocket::tr("SSL_CONF_finish() failed"));
sslContext->errorCode = QSslError::UnspecifiedError;
const QByteArray &value = i.value().toByteArray();
const int result = q_SSL_CONF_cmd(cctx.data(), i.key().constData(), value.constData());
if (result == 2)
continue;
sslContext->errorCode = QSslError::UnspecifiedError;
switch (result) {
case 0:
sslContext->errorStr = msgErrorSettingBackendConfig(
QSslSocket::tr("An error occurred attempting to set %1 to %2").arg(
QString::fromUtf8(i.key()), QString::fromUtf8(value)));
return;
case 1:
sslContext->errorStr = msgErrorSettingBackendConfig(
QSslSocket::tr("Wrong value for %1 (%2)").arg(
QString::fromUtf8(i.key()), QString::fromUtf8(value)));
return;
default:
sslContext->errorStr = msgErrorSettingBackendConfig(
QSslSocket::tr("Unrecognized command %1 = %2").arg(
QString::fromUtf8(i.key()), QString::fromUtf8(value)));
return;
}
} else {
sslContext->errorStr = msgErrorSettingBackendConfig(QSslSocket::tr("SSL_CONF_CTX_new() failed"));
sslContext->errorCode = QSslError::UnspecifiedError;
}
} else
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
{
// specific algorithms requested, but not possible to set
}
if (q_SSL_CONF_CTX_finish(cctx.data()) == 0) {
sslContext->errorStr = msgErrorSettingBackendConfig(QSslSocket::tr("SSL_CONF_finish() failed"));
sslContext->errorCode = QSslError::UnspecifiedError;
}
} else {
sslContext->errorStr = msgErrorSettingBackendConfig(QSslSocket::tr("SSL_CONF_CTX_new() failed"));
sslContext->errorCode = QSslError::UnspecifiedError;
sslContext->errorStr = msgErrorSettingBackendConfig(
QSslSocket::tr("OpenSSL version too old, need at least v1.0.2"));
}
}

View File

@ -1,467 +0,0 @@
/****************************************************************************
**
** 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();
#if QT_CONFIG(dtls)
// defined in qdtls_openssl.cpp:
namespace dtlscallbacks
{
extern "C" int q_X509DtlsCallback(int ok, X509_STORE_CTX *ctx);
extern "C" int q_generate_cookie_callback(SSL *ssl, unsigned char *dst,
unsigned *cookieLength);
extern "C" int q_verify_cookie_callback(SSL *ssl, const unsigned char *cookie,
unsigned cookieLength);
}
#endif // dtls
static inline QString msgErrorSettingEllipticCurves(const QString &why)
{
return QSslSocket::tr("Error when setting the elliptic curves (%1)").arg(why);
}
// Defined in qsslsocket.cpp
QList<QSslCipher> q_getDefaultDtlsCiphers();
// 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;
bool isDtls = 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 if (sslContext->sslConfiguration.protocol() == QSsl::SslV3) {
// SSL 3 is no longer supported, but chosen deliberately -> error
sslContext->ctx = nullptr;
unsupportedProtocol = true;
} else {
switch (sslContext->sslConfiguration.protocol()) {
case QSsl::DtlsV1_0:
case QSsl::DtlsV1_0OrLater:
case QSsl::DtlsV1_2:
case QSsl::DtlsV1_2OrLater:
#if QT_CONFIG(dtls)
isDtls = true;
sslContext->ctx = q_SSL_CTX_new(client ? q_DTLS_client_method() : q_DTLS_server_method());
#else // dtls
sslContext->ctx = nullptr;
unsupportedProtocol = true;
qCWarning(lcSsl, "DTLS protocol requested, but feature 'dtls' is disabled");
#endif // dtls
break;
case QSsl::TlsV1_3:
case QSsl::TlsV1_3OrLater:
#if !defined(TLS1_3_VERSION)
qCWarning(lcSsl, "TLS 1.3 is not supported");
sslContext->ctx = nullptr;
unsupportedProtocol = true;
break;
#endif // TLS1_3_VERSION
default:
// 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;
}
const long anyVersion =
#if QT_CONFIG(dtls)
isDtls ? DTLS_ANY_VERSION : TLS_ANY_VERSION;
#else
TLS_ANY_VERSION;
#endif // dtls
long minVersion = anyVersion;
long maxVersion = anyVersion;
switch (sslContext->sslConfiguration.protocol()) {
case QSsl::TlsV1_0:
minVersion = TLS1_VERSION;
maxVersion = TLS1_VERSION;
break;
case QSsl::TlsV1_1:
minVersion = TLS1_1_VERSION;
maxVersion = TLS1_1_VERSION;
break;
case QSsl::TlsV1_2:
minVersion = TLS1_2_VERSION;
maxVersion = TLS1_2_VERSION;
break;
case QSsl::TlsV1_3:
#ifdef TLS1_3_VERSION
minVersion = TLS1_3_VERSION;
maxVersion = TLS1_3_VERSION;
#else
// This protocol is not supported by OpenSSL 1.1 and we handle
// it as an error (see the code above).
Q_UNREACHABLE();
#endif // TLS1_3_VERSION
break;
// Ranges:
case QSsl::TlsV1SslV3:
case QSsl::AnyProtocol:
case QSsl::SecureProtocols:
case QSsl::TlsV1_0OrLater:
minVersion = TLS1_VERSION;
maxVersion = 0;
break;
case QSsl::TlsV1_1OrLater:
minVersion = TLS1_1_VERSION;
maxVersion = 0;
break;
case QSsl::TlsV1_2OrLater:
minVersion = TLS1_2_VERSION;
maxVersion = 0;
break;
case QSsl::DtlsV1_0:
minVersion = DTLS1_VERSION;
maxVersion = DTLS1_VERSION;
break;
case QSsl::DtlsV1_0OrLater:
minVersion = DTLS1_VERSION;
maxVersion = DTLS_MAX_VERSION;
break;
case QSsl::DtlsV1_2:
minVersion = DTLS1_2_VERSION;
maxVersion = DTLS1_2_VERSION;
break;
case QSsl::DtlsV1_2OrLater:
minVersion = DTLS1_2_VERSION;
maxVersion = DTLS_MAX_VERSION;
break;
case QSsl::TlsV1_3OrLater:
#ifdef TLS1_3_VERSION
minVersion = TLS1_3_VERSION;
maxVersion = 0;
break;
#else
// This protocol is not supported by OpenSSL 1.1 and we handle
// it as an error (see the code above).
Q_UNREACHABLE();
break;
#endif // TLS1_3_VERSION
case QSsl::SslV2:
case QSsl::SslV3:
// These protocols are not supported, and we handle
// them as an error (see the code above).
Q_UNREACHABLE();
break;
case QSsl::UnknownProtocol:
break;
}
if (minVersion != anyVersion
&& !q_SSL_CTX_set_min_proto_version(sslContext->ctx, minVersion)) {
sslContext->errorStr = QSslSocket::tr("Error while setting the minimal protocol version");
sslContext->errorCode = QSslError::UnspecifiedError;
return;
}
if (maxVersion != anyVersion
&& !q_SSL_CTX_set_max_proto_version(sslContext->ctx, maxVersion)) {
sslContext->errorStr = QSslSocket::tr("Error while setting the maximum protocol version");
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);
auto filterCiphers = [](const QList<QSslCipher> &ciphers, bool selectTls13)
{
QByteArray cipherString;
bool first = true;
for (const QSslCipher &cipher : qAsConst(ciphers)) {
const bool isTls13Cipher = cipher.protocol() == QSsl::TlsV1_3 || cipher.protocol() == QSsl::TlsV1_3OrLater;
if (selectTls13 != isTls13Cipher)
continue;
if (first)
first = false;
else
cipherString.append(':');
cipherString.append(cipher.name().toLatin1());
}
return cipherString;
};
// Initialize ciphers
QList<QSslCipher> ciphers = sslContext->sslConfiguration.ciphers();
if (ciphers.isEmpty())
ciphers = isDtls ? q_getDefaultDtlsCiphers() : QSslSocketPrivate::defaultCiphers();
const QByteArray preTls13Ciphers = filterCiphers(ciphers, false);
if (preTls13Ciphers.size()) {
if (!q_SSL_CTX_set_cipher_list(sslContext->ctx, preTls13Ciphers.data())) {
sslContext->errorStr = QSslSocket::tr("Invalid or empty cipher list (%1)").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
sslContext->errorCode = QSslError::UnspecifiedError;
return;
}
}
const QByteArray tls13Ciphers = filterCiphers(ciphers, true);
#ifdef TLS1_3_VERSION
if (tls13Ciphers.size()) {
if (!q_SSL_CTX_set_ciphersuites(sslContext->ctx, tls13Ciphers.data())) {
sslContext->errorStr = QSslSocket::tr("Invalid or empty cipher list (%1)").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
sslContext->errorCode = QSslError::UnspecifiedError;
return;
}
}
#endif // TLS1_3_VERSION
if (!preTls13Ciphers.size() && !tls13Ciphers.size()) {
sslContext->errorStr = QSslSocket::tr("Invalid or empty cipher list (%1)").arg(QStringLiteral(""));
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,
#if QT_CONFIG(dtls)
isDtls ? dtlscallbacks::q_X509DtlsCallback :
#endif // dtls
q_X509Callback);
}
#if QT_CONFIG(dtls)
if (mode == QSslSocket::SslServerMode && isDtls && configuration.dtlsCookieVerificationEnabled()) {
q_SSL_CTX_set_cookie_generate_cb(sslContext->ctx, dtlscallbacks::q_generate_cookie_callback);
q_SSL_CTX_set_cookie_verify_cb(sslContext->ctx, dtlscallbacks::q_verify_cookie_callback);
}
#endif // dtls
// 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 &params = dhparams.d->derData;
const char *ptr = params.constData();
DH *dh = q_d2i_DHparams(nullptr, reinterpret_cast<const unsigned char **>(&ptr),
params.length());
if (dh == nullptr)
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;
return;
#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;
return;
}
#endif
}
applyBackendConfig(sslContext);
}
QT_END_NAMESPACE

View File

@ -86,7 +86,7 @@ public:
void setSessionASN1(const QByteArray &sessionASN1);
int sessionTicketLifeTimeHint() const;
#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG)
#ifndef OPENSSL_NO_NEXTPROTONEG
// must be public because we want to use it from an OpenSSL callback
struct NPNContext {
NPNContext() : data(nullptr),
@ -98,7 +98,7 @@ public:
QSslConfiguration::NextProtocolNegotiationStatus status;
};
NPNContext npnContext() const;
#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ...
#endif // !OPENSSL_NO_NEXTPROTONEG
protected:
QSslContext();
@ -118,10 +118,10 @@ private:
QSslError::SslError errorCode;
QString errorStr;
QSslConfiguration sslConfiguration;
#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG)
#ifndef OPENSSL_NO_NEXTPROTONEG
QByteArray m_supportedNPNVersions;
NPNContext m_npnContext;
#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ...
#endif // !OPENSSL_NO_NEXTPROTONEG
};
#endif // QT_NO_SSL

View File

@ -1,407 +0,0 @@
/****************************************************************************
**
** 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();
#if QT_CONFIG(dtls)
// defined in qdtls_openssl.cpp:
namespace dtlscallbacks
{
extern "C" int q_X509DtlsCallback(int ok, X509_STORE_CTX *ctx);
extern "C" int q_generate_cookie_callback(SSL *ssl, unsigned char *dst,
unsigned *cookieLength);
extern "C" int q_verify_cookie_callback(SSL *ssl, const unsigned char *cookie,
unsigned cookieLength);
}
#endif // dtls
static inline QString msgErrorSettingEllipticCurves(const QString &why)
{
return QSslSocket::tr("Error when setting the elliptic curves (%1)").arg(why);
}
// Defined in qsslsocket.cpp
QList<QSslCipher> q_getDefaultDtlsCiphers();
// 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;
bool isDtls = false;
init_context:
switch (sslContext->sslConfiguration.protocol()) {
#if QT_CONFIG(dtls)
case QSsl::DtlsV1_0:
isDtls = true;
sslContext->ctx = q_SSL_CTX_new(client ? q_DTLSv1_client_method() : q_DTLSv1_server_method());
break;
case QSsl::DtlsV1_2:
case QSsl::DtlsV1_2OrLater:
// OpenSSL 1.0.2 and below will probably never receive TLS 1.3, so
// technically 1.2 or later is 1.2 and will stay so.
isDtls = true;
sslContext->ctx = q_SSL_CTX_new(client ? q_DTLSv1_2_client_method() : q_DTLSv1_2_server_method());
break;
case QSsl::DtlsV1_0OrLater:
isDtls = true;
sslContext->ctx = q_SSL_CTX_new(client ? q_DTLS_client_method() : q_DTLS_server_method());
break;
#else // dtls
case QSsl::DtlsV1_0:
case QSsl::DtlsV1_0OrLater:
case QSsl::DtlsV1_2:
case QSsl::DtlsV1_2OrLater:
sslContext->ctx = nullptr;
unsupportedProtocol = true;
qCWarning(lcSsl, "DTLS protocol requested, but feature 'dtls' is disabled");
break;
#endif // dtls
case QSsl::SslV2:
case QSsl::SslV3:
// We don't support SSLv2 / SSLv3.
sslContext->ctx = 0;
unsupportedProtocol = true;
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::AnyProtocol:
default:
sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method());
break;
case QSsl::TlsV1SslV3:
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;
case QSsl::TlsV1_3:
case QSsl::TlsV1_3OrLater:
// TLS 1.3 is not supported by the system, but chosen deliberately -> error
sslContext->ctx = nullptr;
unsupportedProtocol = true;
break;
}
if (!client && isDtls && configuration.peerVerifyMode() != QSslSocket::VerifyNone) {
sslContext->errorStr = QSslSocket::tr("DTLS server requires a 'VerifyNone' mode with your version of OpenSSL");
sslContext->errorCode = QSslError::UnspecifiedError;
return;
}
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.
// DTLSTODO: check this setupOpenSslOptions ...
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 = isDtls ? q_getDefaultDtlsCiphers() : 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,
#if QT_CONFIG(dtls)
isDtls ? dtlscallbacks::q_X509DtlsCallback :
#endif // dtls
q_X509Callback);
}
#if QT_CONFIG(dtls)
if (mode == QSslSocket::SslServerMode && isDtls && configuration.dtlsCookieVerificationEnabled()) {
q_SSL_CTX_set_cookie_generate_cb(sslContext->ctx, dtlscallbacks::q_generate_cookie_callback);
q_SSL_CTX_set_cookie_verify_cb(sslContext->ctx, CookieVerifyCallback(dtlscallbacks::q_verify_cookie_callback));
}
#endif // dtls
// 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 &params = 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;
return;
}
} 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;
return;
}
}
applyBackendConfig(sslContext);
}
QT_END_NAMESPACE

View File

@ -83,10 +83,8 @@ QSslEllipticCurve QSslEllipticCurve::fromShortName(const QString &name)
const QByteArray curveNameLatin1 = name.toLatin1();
int nid = q_OBJ_sn2nid(curveNameLatin1.data());
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
if (nid == 0 && QSslSocket::sslLibraryVersionNumber() >= 0x10002000L)
if (nid == 0)
nid = q_EC_curve_nist2nid(curveNameLatin1.data());
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
result.id = nid;

View File

@ -93,11 +93,7 @@ bool QSslKeyPrivate::fromEVP_PKEY(EVP_PKEY *pkey)
if (pkey == nullptr)
return false;
#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;
@ -350,33 +346,17 @@ static QByteArray doCrypt(QSslKeyPrivate::Cipher cipher, const QByteArray &data,
QByteArray output;
output.resize(data.size() + EVP_MAX_BLOCK_LENGTH);
#if QT_CONFIG(opensslv11)
EVP_CIPHER_CTX *ctx = q_EVP_CIPHER_CTX_new();
q_EVP_CIPHER_CTX_reset(ctx);
#else
EVP_CIPHER_CTX evpCipherContext;
EVP_CIPHER_CTX *ctx = &evpCipherContext;
q_EVP_CIPHER_CTX_init(ctx);
#endif
q_EVP_CipherInit(ctx, type, nullptr, nullptr, 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(), nullptr);
#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);
#endif // opensslv11
q_EVP_CipherUpdate(ctx,
reinterpret_cast<unsigned char *>(output.data()), &len,
reinterpret_cast<const unsigned char *>(data.constData()), data.size());
@ -384,12 +364,8 @@ static QByteArray doCrypt(QSslKeyPrivate::Cipher cipher, const QByteArray &data,
reinterpret_cast<unsigned char *>(output.data()) + len, &i);
len += i;
#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);
}

View File

@ -66,15 +66,12 @@
#include "qsslpresharedkeyauthenticator.h"
#include "qsslpresharedkeyauthenticator_p.h"
#include "qocspresponse_p.h"
#include "qsslkey.h"
#ifdef Q_OS_WIN
#include "qwindowscarootfetcher_p.h"
#endif
#if !QT_CONFIG(opensslv11)
#include <openssl/x509_vfy.h>
#endif
#include <QtCore/qdatetime.h>
#include <QtCore/qdebug.h>
#include <QtCore/qdir.h>
@ -87,6 +84,8 @@
#include <QtCore/qurl.h>
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qscopedvaluerollback.h>
#include <QtCore/qlibrary.h>
#include <QtCore/qoperatingsystemversion.h>
#if QT_CONFIG(ocsp)
#include "qocsp_p.h"
@ -98,13 +97,12 @@
QT_BEGIN_NAMESPACE
Q_GLOBAL_STATIC(QRecursiveMutex, qt_opensslInitMutex)
bool QSslSocketPrivate::s_libraryLoaded = false;
bool QSslSocketPrivate::s_loadedCiphersAndCerts = false;
bool QSslSocketPrivate::s_loadRootCertsOnDemand = false;
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
int QSslSocketBackendPrivate::s_indexForSSLExtraData = -1;
#endif
QString QSslSocketBackendPrivate::getErrorsFromOpenSsl()
{
@ -122,7 +120,7 @@ QString QSslSocketBackendPrivate::getErrorsFromOpenSsl()
extern "C" {
#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
#ifndef OPENSSL_NO_PSK
static unsigned int q_ssl_psk_client_callback(SSL *ssl,
const char *hint,
char *identity, unsigned int max_identity_len,
@ -143,7 +141,6 @@ static unsigned int q_ssl_psk_server_callback(SSL *ssl,
}
#ifdef TLS1_3_VERSION
#ifndef OPENSSL_NO_PSK
static unsigned int q_ssl_psk_restore_client(SSL *ssl,
const char *hint,
char *identity, unsigned int max_identity_len,
@ -164,7 +161,6 @@ static unsigned int q_ssl_psk_restore_client(SSL *ssl,
return 0;
}
#endif // !OPENSSL_NO_PSK
static int q_ssl_psk_use_session_callback(SSL *ssl, const EVP_MD *md, const unsigned char **id,
size_t *idlen, SSL_SESSION **sess)
@ -175,7 +171,6 @@ static int q_ssl_psk_use_session_callback(SSL *ssl, const EVP_MD *md, const unsi
Q_UNUSED(idlen);
Q_UNUSED(sess);
#ifndef OPENSSL_NO_PSK
#ifdef QT_DEBUG
QSslSocketBackendPrivate *d = reinterpret_cast<QSslSocketBackendPrivate *>(q_SSL_get_ex_data(ssl, QSslSocketBackendPrivate::s_indexForSSLExtraData));
Q_ASSERT(d);
@ -184,13 +179,12 @@ static int q_ssl_psk_use_session_callback(SSL *ssl, const EVP_MD *md, const unsi
// Temporarily rebind the psk because it will be called next. The function will restore it.
q_SSL_set_psk_client_callback(ssl, &q_ssl_psk_restore_client);
#endif
return 1; // need to return 1 or else "the connection setup fails."
}
#endif // TLS1_3_VERSION
#endif
#endif // !OPENSSL_NO_PSK
#if QT_CONFIG(ocsp)
@ -407,13 +401,8 @@ int q_X509Callback(int ok, X509_STORE_CTX *ctx)
ErrorListPtr errors = nullptr;
// Error list is attached to either 'SSL' or 'X509_STORE'.
if (X509_STORE *store = q_X509_STORE_CTX_get0_store(ctx)) { // We try store first:
#if QT_CONFIG(opensslv11)
if (X509_STORE *store = q_X509_STORE_CTX_get0_store(ctx)) // We try store first:
errors = ErrorListPtr(q_X509_STORE_get_ex_data(store, 0));
#else
errors = ErrorListPtr(q_CRYPTO_get_ex_data(&store->ex_data, 0));
#endif // opensslv11
}
if (!errors) {
// Not found on store? Try SSL and its external data then. According to the OpenSSL's
@ -476,17 +465,12 @@ long QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SslProtocol protocol, Q
options = SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3;
else if (protocol == QSsl::TlsV1_0OrLater)
options = SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3;
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
// Choosing Tlsv1_1OrLater or TlsV1_2OrLater on OpenSSL < 1.0.1
// will cause an error in QSslContext::fromConfiguration, meaning
// we will never get here.
else if (protocol == QSsl::TlsV1_1OrLater)
options = SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1;
else if (protocol == QSsl::TlsV1_2OrLater)
options = SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1;
else if (protocol == QSsl::TlsV1_3OrLater)
options = SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2;
#endif
else
options = SSL_OP_ALL;
@ -590,15 +574,13 @@ bool QSslSocketBackendPrivate::initSslContext()
q_SSL_set_ex_data(ssl, s_indexForSSLExtraData, this);
#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
#ifndef OPENSSL_NO_PSK
// Set the client callback for PSK
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)
q_SSL_set_psk_server_callback(ssl, &q_ssl_psk_server_callback);
}
#endif
if (mode == QSslSocket::SslClientMode)
q_SSL_set_psk_client_callback(ssl, &q_ssl_psk_client_callback);
else if (mode == QSslSocket::SslServerMode)
q_SSL_set_psk_server_callback(ssl, &q_ssl_psk_server_callback);
#if OPENSSL_VERSION_NUMBER >= 0x10101006L
// Set the client callback for TLSv1.3 PSK
if (mode == QSslSocket::SslClientMode
@ -607,6 +589,9 @@ bool QSslSocketBackendPrivate::initSslContext()
}
#endif // openssl version >= 0x10101006L
#endif // OPENSSL_NO_PSK
#if QT_CONFIG(ocsp)
if (configuration.ocspStaplingEnabled) {
if (mode == QSslSocket::SslServerMode) {
@ -670,13 +655,46 @@ bool QSslSocketPrivate::supportsSsl()
}
/*!
\internal
Returns the version number of the SSL library in use. Note that
this is the version of the library in use at run-time, not compile
time.
*/
long QSslSocketPrivate::sslLibraryVersionNumber()
{
if (!supportsSsl())
return 0;
return q_OpenSSL_version_num();
}
/*!
\internal
Returns the version string of the SSL library in use. Note that
this is the version of the library in use at run-time, not compile
time. If no SSL support is available then this will return an empty value.
*/
QString QSslSocketPrivate::sslLibraryVersionString()
{
if (!supportsSsl())
return QString();
const char *versionString = q_OpenSSL_version(OPENSSL_VERSION);
if (!versionString)
return QString();
return QString::fromLatin1(versionString);
}
/*!
\internal
Declared static in QSslSocketPrivate, makes sure the SSL libraries have
been initialized.
*/
void QSslSocketPrivate::ensureInitialized()
{
if (!supportsSsl())
@ -685,11 +703,23 @@ void QSslSocketPrivate::ensureInitialized()
ensureCiphersAndCertsLoaded();
}
/*!
\internal
Returns the version number of the SSL library in use at compile
time.
*/
long QSslSocketPrivate::sslLibraryBuildVersionNumber()
{
return OPENSSL_VERSION_NUMBER;
}
/*!
\internal
Returns the version string of the SSL library in use at compile
time.
*/
QString QSslSocketPrivate::sslLibraryBuildVersionString()
{
// Using QStringLiteral to store the version string as unicode and
@ -706,11 +736,7 @@ 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
// Note, we assert, not just silently return/bail out early:
// this should never happen and problems with OpenSSL's initialization
// must be caught before this (see supportsSsl()).
@ -1737,6 +1763,174 @@ 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_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 = nullptr;
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();
}
}
bool QSslSocketPrivate::ensureLibraryLoaded()
{
if (!q_resolveOpenSslSymbols())
return false;
const QMutexLocker locker(qt_opensslInitMutex);
if (!s_libraryLoaded) {
// 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;
}
s_libraryLoaded = true;
}
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_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.
//This flag is set false by setDefaultCaCertificates() indicating the app uses
//its own cert bundle rather than the system one.
//Same logic that disables the unix on demand cert loading.
//Unlike unix, we do preload the certificates from the cert store.
s_loadRootCertsOnDemand = true;
#endif
}
QList<QSslCertificate> QSslSocketBackendPrivate::STACKOFX509_to_QSslCertificates(STACK_OF(X509) *x509)
{
ensureInitialized();
@ -1788,19 +1982,11 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> &
}
QVector<QSslErrorEntry> lastErrors;
#if QT_CONFIG(opensslv11)
if (!q_X509_STORE_set_ex_data(certStore, 0, &lastErrors)) {
qCWarning(lcSsl) << "Unable to attach external data (error list) to a store";
errors << QSslError(QSslError::UnspecifiedError);
return errors;
}
#else
if (!q_CRYPTO_set_ex_data(&certStore->ex_data, 0, &lastErrors)) {
qCWarning(lcSsl) << "Unable to attach external data (error list) to a store";
errors << QSslError(QSslError::UnspecifiedError);
return errors;
}
#endif // opensslv11
// Register a custom callback to get all verification errors.
q_X509_STORE_set_verify_cb(certStore, q_X509Callback);

View File

@ -1,271 +0,0 @@
/****************************************************************************
**
** 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>
#include <QtCore/qoperatingsystemversion.h>
QT_BEGIN_NAMESPACE
Q_GLOBAL_STATIC(QRecursiveMutex, qt_opensslInitMutex)
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) {
// 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;
}
s_libraryLoaded = true;
}
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_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.
//This flag is set false by setDefaultCaCertificates() indicating the app uses
//its own cert bundle rather than the system one.
//Same logic that disables the unix on demand cert loading.
//Unlike unix, we do preload the certificates from the cert store.
s_loadRootCertsOnDemand = true;
#endif
}
long QSslSocketPrivate::sslLibraryVersionNumber()
{
if (!supportsSsl())
return 0;
return q_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 = nullptr;
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

View File

@ -1,195 +0,0 @@
/****************************************************************************
**
** 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);
Q_AUTOTEST_EXPORT int q_EVP_PKEY_up_ref(EVP_PKEY *a);
int q_EVP_PKEY_base_id(EVP_PKEY *a);
int q_RSA_bits(RSA *a);
Q_AUTOTEST_EXPORT int q_OPENSSL_sk_num(OPENSSL_STACK *a);
Q_AUTOTEST_EXPORT void q_OPENSSL_sk_pop_free(OPENSSL_STACK *a, void (*b)(void *));
Q_AUTOTEST_EXPORT OPENSSL_STACK *q_OPENSSL_sk_new_null();
Q_AUTOTEST_EXPORT void q_OPENSSL_sk_push(OPENSSL_STACK *st, void *data);
Q_AUTOTEST_EXPORT void q_OPENSSL_sk_free(OPENSSL_STACK *a);
Q_AUTOTEST_EXPORT 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);
Q_AUTOTEST_EXPORT void q_X509_up_ref(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);
int q_X509_STORE_set_ex_data(X509_STORE *ctx, int idx, void *data);
void *q_X509_STORE_get_ex_data(X509_STORE *r, int idx);
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);
unsigned long q_SSL_set_options(SSL *s, unsigned long op);
#ifdef TLS1_3_VERSION
int q_SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str);
#endif
#if QT_CONFIG(dtls)
// Functions and types required for DTLS support:
extern "C"
{
typedef int (*CookieVerifyCallback)(SSL *, const unsigned char *, unsigned);
typedef int (*DgramWriteCallback) (BIO *, const char *, int);
typedef int (*DgramReadCallback) (BIO *, char *, int);
typedef int (*DgramPutsCallback) (BIO *, const char *);
typedef long (*DgramCtrlCallback) (BIO *, int, long, void *);
typedef int (*DgramCreateCallback) (BIO *);
typedef int (*DgramDestroyCallback) (BIO *);
}
int q_DTLSv1_listen(SSL *s, BIO_ADDR *client);
BIO_ADDR *q_BIO_ADDR_new();
void q_BIO_ADDR_free(BIO_ADDR *ap);
// API we need for a custom dgram BIO:
BIO_METHOD *q_BIO_meth_new(int type, const char *name);
void q_BIO_meth_free(BIO_METHOD *biom);
int q_BIO_meth_set_write(BIO_METHOD *biom, DgramWriteCallback);
int q_BIO_meth_set_read(BIO_METHOD *biom, DgramReadCallback);
int q_BIO_meth_set_puts(BIO_METHOD *biom, DgramPutsCallback);
int q_BIO_meth_set_ctrl(BIO_METHOD *biom, DgramCtrlCallback);
int q_BIO_meth_set_create(BIO_METHOD *biom, DgramCreateCallback);
int q_BIO_meth_set_destroy(BIO_METHOD *biom, DgramDestroyCallback);
#endif // dtls
void q_BIO_set_data(BIO *a, void *ptr);
void *q_BIO_get_data(BIO *a);
void q_BIO_set_init(BIO *a, int init);
int q_BIO_get_shutdown(BIO *a);
void q_BIO_set_shutdown(BIO *a, int shut);
#if QT_CONFIG(ocsp)
const OCSP_CERTID *q_OCSP_SINGLERESP_get0_id(const OCSP_SINGLERESP *x);
#endif // ocsp
#define q_SSL_CTX_set_min_proto_version(ctx, version) \
q_SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MIN_PROTO_VERSION, version, nullptr)
#define q_SSL_CTX_set_max_proto_version(ctx, version) \
q_SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MAX_PROTO_VERSION, version, nullptr)
extern "C" {
typedef int (*q_SSL_psk_use_session_cb_func_t)(SSL *, const EVP_MD *, const unsigned char **, size_t *,
SSL_SESSION **);
}
void q_SSL_set_psk_use_session_callback(SSL *s, q_SSL_psk_use_session_cb_func_t);
#endif

View File

@ -130,9 +130,7 @@ public:
BIO *writeBio;
SSL_SESSION *session;
QVector<QSslErrorEntry> errorList;
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
static int s_indexForSSLExtraData; // index used in SSL_get_ex_data to get the matching QSslSocketBackendPrivate
#endif
bool inSetAndEmitError = false;

View File

@ -137,10 +137,6 @@ 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 nullptr, 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)
@ -237,93 +233,6 @@ DEFINEFUNC2(void, BIO_set_init, BIO *a, a, int init, init, return, DUMMYARG)
DEFINEFUNC(int, BIO_get_shutdown, BIO *a, a, return -1, return)
DEFINEFUNC2(void, BIO_set_shutdown, BIO *a, a, int shut, shut, return, DUMMYARG)
#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 nullptr, return)
#ifdef SSLEAY_MACROS
DEFINEFUNC3(void *, ASN1_dup, i2d_of_void *a, a, d2i_of_void *b, b, char *c, c, return nullptr, return)
#endif
DEFINEFUNC2(BIO *, BIO_new_file, const char *filename, filename, const char *mode, mode, return nullptr, return)
DEFINEFUNC(void, ERR_clear_error, DUMMYARG, DUMMYARG, return, DUMMYARG)
DEFINEFUNC(BIO *, BIO_new, BIO_METHOD *a, a, return nullptr, return)
DEFINEFUNC(BIO_METHOD *, BIO_s_mem, void, DUMMYARG, return nullptr, return)
DEFINEFUNC(int, CRYPTO_num_locks, DUMMYARG, DUMMYARG, return 0, return)
DEFINEFUNC(void, CRYPTO_set_locking_callback, void (*a)(int, int, const char *, int), a, return, DUMMYARG)
DEFINEFUNC(void, CRYPTO_set_id_callback, unsigned long (*a)(), a, return, DUMMYARG)
DEFINEFUNC(void, CRYPTO_free, void *a, a, return, DUMMYARG)
DEFINEFUNC3(int, CRYPTO_set_ex_data, CRYPTO_EX_DATA *ad, ad, int idx, idx, void *val, val, return 0, return)
DEFINEFUNC2(void *, CRYPTO_get_ex_data, const CRYPTO_EX_DATA *ad, ad, int idx, idx, return nullptr, 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)
#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 nullptr, 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 nullptr, return)
#endif // SSLEAY_MACROS
DEFINEFUNC(int, sk_num, STACK *a, a, return -1, return)
DEFINEFUNC2(void, sk_pop_free, STACK *a, a, void (*b)(void*), b, return, DUMMYARG)
DEFINEFUNC(_STACK *, sk_new_null, DUMMYARG, DUMMYARG, return nullptr, return)
DEFINEFUNC2(void, sk_push, _STACK *a, a, void *b, b, return, DUMMYARG)
DEFINEFUNC(void, sk_free, _STACK *a, a, return, DUMMYARG)
DEFINEFUNC2(void *, sk_value, STACK *a, a, int b, b, return nullptr, return)
DEFINEFUNC(int, SSL_library_init, void, DUMMYARG, return -1, return)
DEFINEFUNC(void, SSL_load_error_strings, void, DUMMYARG, return, DUMMYARG)
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
DEFINEFUNC5(int, SSL_get_ex_new_index, long argl, argl, void *argp, argp, CRYPTO_EX_new *new_func, new_func, CRYPTO_EX_dup *dup_func, dup_func, CRYPTO_EX_free *free_func, free_func, return -1, return)
#endif // OPENSSL_VERSION_NUMBER >= 0x10001000L
DEFINEFUNC(const SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
DEFINEFUNC(const SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
DEFINEFUNC(const SSL_METHOD *, TLSv1_1_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
DEFINEFUNC(const SSL_METHOD *, TLSv1_2_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
#endif
DEFINEFUNC(const SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
DEFINEFUNC(const SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
DEFINEFUNC(const SSL_METHOD *, TLSv1_1_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
DEFINEFUNC(const SSL_METHOD *, TLSv1_2_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
#endif
DEFINEFUNC(STACK_OF(X509) *, X509_STORE_CTX_get_chain, X509_STORE_CTX *a, a, return nullptr, 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 nullptr, return)
DEFINEFUNC3(DSA *, d2i_DSAPrivateKey, DSA **a, a, unsigned char **b, b, long c, c, return nullptr, return)
#ifndef OPENSSL_NO_EC
DEFINEFUNC3(EC_KEY *, d2i_ECPrivateKey, EC_KEY **a, a, unsigned char **b, b, long c, c, return nullptr, return)
#endif
#endif
#if QT_CONFIG(dtls)
DEFINEFUNC(const SSL_METHOD *, DTLSv1_server_method, void, DUMMYARG, return nullptr, return)
DEFINEFUNC(const SSL_METHOD *, DTLSv1_client_method, void, DUMMYARG, return nullptr, return)
DEFINEFUNC(const SSL_METHOD *, DTLSv1_2_server_method, void, DUMMYARG, return nullptr, return)
DEFINEFUNC(const SSL_METHOD *, DTLSv1_2_client_method, void, DUMMYARG, return nullptr, return)
#endif // dtls
DEFINEFUNC(char *, CONF_get1_default_config_file, DUMMYARG, DUMMYARG, return nullptr, 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 nullptr, return)
#endif // QT_CONFIG(opensslv11)
DEFINEFUNC(long, ASN1_INTEGER_get, ASN1_INTEGER *a, a, return 0, return)
DEFINEFUNC2(int, ASN1_INTEGER_cmp, const ASN1_INTEGER *a, a, const ASN1_INTEGER *b, b, return 1, return)
DEFINEFUNC(int, ASN1_STRING_length, ASN1_STRING *a, a, return 0, return)
@ -392,36 +301,28 @@ 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 nullptr, return)
DEFINEFUNC4(DSA *, PEM_read_bio_DSAPrivateKey, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return)
DEFINEFUNC4(RSA *, PEM_read_bio_RSAPrivateKey, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return nullptr, 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 nullptr, return)
#endif
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)
DEFINEFUNC4(EC_KEY *, PEM_read_bio_EC_PUBKEY, BIO *a, a, EC_KEY **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return)
DEFINEFUNC2(int, PEM_write_bio_EC_PUBKEY, BIO *a, a, EC_KEY *b, b, return 0, return)
#endif // OPENSSL_NO_EC
DEFINEFUNC4(DH *, PEM_read_bio_DHparams, BIO *a, a, DH **b, b, pem_password_cb *c, c, void *d, d, return nullptr, 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)
DEFINEFUNC7(int, PEM_write_bio_PrivateKey, BIO *a, a, EVP_PKEY *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 nullptr, return)
DEFINEFUNC4(DSA *, PEM_read_bio_DSA_PUBKEY, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return)
DEFINEFUNC4(RSA *, PEM_read_bio_RSA_PUBKEY, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return nullptr, 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 nullptr, 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)
DEFINEFUNC2(int, PEM_write_bio_PUBKEY, BIO *a, a, EVP_PKEY *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)
DEFINEFUNC2(int, RAND_bytes, unsigned char *b, b, int n, n, return 0, return)
@ -448,14 +349,12 @@ DEFINEFUNC2(int, SSL_CTX_use_PrivateKey, SSL_CTX *a, a, EVP_PKEY *b, b, 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 nullptr, return)
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
DEFINEFUNC(SSL_CONF_CTX *, SSL_CONF_CTX_new, DUMMYARG, DUMMYARG, return nullptr, return);
DEFINEFUNC(void, SSL_CONF_CTX_free, SSL_CONF_CTX *a, a, return ,return);
DEFINEFUNC2(void, SSL_CONF_CTX_set_ssl_ctx, SSL_CONF_CTX *a, a, SSL_CTX *b, b, return, return);
DEFINEFUNC2(unsigned int, SSL_CONF_CTX_set_flags, SSL_CONF_CTX *a, a, unsigned int b, b, return 0, return);
DEFINEFUNC(int, SSL_CONF_CTX_finish, SSL_CONF_CTX *a, a, return 0, return);
DEFINEFUNC3(int, SSL_CONF_cmd, SSL_CONF_CTX *a, a, const char *b, b, const char *c, c, return 0, return);
#endif
DEFINEFUNC(void, SSL_free, SSL *a, a, return, DUMMYARG)
DEFINEFUNC(STACK_OF(SSL_CIPHER) *, SSL_get_ciphers, const SSL *a, a, return nullptr, return)
DEFINEFUNC(const SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return nullptr, return)
@ -477,21 +376,19 @@ DEFINEFUNC2(int, SSL_set_session, SSL* to, to, SSL_SESSION *session, session, re
DEFINEFUNC(void, SSL_SESSION_free, SSL_SESSION *ses, ses, return, DUMMYARG)
DEFINEFUNC(SSL_SESSION*, SSL_get1_session, SSL *ssl, ssl, return nullptr, return)
DEFINEFUNC(SSL_SESSION*, SSL_get_session, const SSL *ssl, ssl, return nullptr, 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 nullptr, return)
#endif
#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
#ifndef 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_NO_PSK
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 nullptr, return)
#endif
DEFINEFUNC2(void, X509_print, BIO *a, a, X509 *b, b, return, DUMMYARG);
DEFINEFUNC(ASN1_OBJECT *, X509_EXTENSION_get_object, X509_EXTENSION *a, a, return nullptr, return)
DEFINEFUNC(void, X509_free, X509 *a, a, return, DUMMYARG)
@ -535,7 +432,8 @@ DEFINEFUNC(int, SSL_get_ex_data_X509_STORE_CTX_idx, DUMMYARG, DUMMYARG, return -
DEFINEFUNC3(int, SSL_CTX_load_verify_locations, SSL_CTX *ctx, ctx, const char *CAfile, CAfile, const char *CApath, CApath, 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 nullptr, return)
#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG)
#ifndef OPENSSL_NO_NEXTPROTONEG
DEFINEFUNC6(int, SSL_select_next_proto, unsigned char **out, out, unsigned char *outlen, outlen,
const unsigned char *in, in, unsigned int inlen, inlen,
const unsigned char *client, client, unsigned int client_len, client_len,
@ -548,7 +446,6 @@ DEFINEFUNC3(void, SSL_CTX_set_next_proto_select_cb, SSL_CTX *s, s,
void *arg, arg, return, DUMMYARG)
DEFINEFUNC3(void, SSL_get0_next_proto_negotiated, const SSL *s, s,
const unsigned char **data, data, unsigned *len, len, return, DUMMYARG)
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
DEFINEFUNC3(int, SSL_set_alpn_protos, SSL *s, s, const unsigned char *protos, protos,
unsigned protos_len, protos_len, return -1, return)
DEFINEFUNC3(void, SSL_CTX_set_alpn_select_cb, SSL_CTX *s, s,
@ -559,8 +456,7 @@ DEFINEFUNC3(void, SSL_CTX_set_alpn_select_cb, SSL_CTX *s, s,
void *arg, arg, return, DUMMYARG)
DEFINEFUNC3(void, SSL_get0_alpn_selected, const SSL *s, s, const unsigned char **data, data,
unsigned *len, len, return, DUMMYARG)
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L ...
#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ...
#endif // !OPENSSL_NO_NEXTPROTONEG
// DTLS:
#if QT_CONFIG(dtls)
@ -581,14 +477,13 @@ DEFINEFUNC3(DH *, d2i_DHparams, DH**a, a, const unsigned char **pp, pp, long len
DEFINEFUNC2(int, i2d_DHparams, DH *a, a, unsigned char **p, p, return -1, return)
DEFINEFUNC2(int, DH_check, DH *dh, dh, int *codes, codes, return 0, return)
DEFINEFUNC3(BIGNUM *, BN_bin2bn, const unsigned char *s, s, int len, len, BIGNUM *ret, ret, return nullptr, return)
#ifndef OPENSSL_NO_EC
DEFINEFUNC(EC_KEY *, EC_KEY_dup, const EC_KEY *ec, ec, return nullptr, return)
DEFINEFUNC(EC_KEY *, EC_KEY_new_by_curve_name, int nid, nid, return nullptr, return)
DEFINEFUNC(void, EC_KEY_free, EC_KEY *ecdh, ecdh, return, DUMMYARG)
DEFINEFUNC2(size_t, EC_get_builtin_curves, EC_builtin_curve * r, r, size_t nitems, nitems, return 0, return)
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
DEFINEFUNC(int, EC_curve_nist2nid, const char *name, name, return 0, return)
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
#endif // OPENSSL_NO_EC
DEFINEFUNC5(int, PKCS12_parse, PKCS12 *p12, p12, const char *pass, pass, EVP_PKEY **pkey, pkey, \
@ -760,7 +655,6 @@ static LoadedOpenSsl loadOpenSsl()
{
LoadedOpenSsl result;
#if QT_CONFIG(opensslv11)
// With OpenSSL 1.1 the names have changed to libssl-1_1(-x64) and libcrypto-1_1(-x64), for builds using
// MSVC and GCC, (-x64 suffix for 64-bit builds).
@ -774,21 +668,6 @@ static LoadedOpenSsl loadOpenSsl()
QLatin1String("libcrypto-1_1" QT_SSL_SUFFIX), result);
#undef QT_SSL_SUFFIX
#else // QT_CONFIG(opensslv11)
// When OpenSSL is built using MSVC then the libraries are named 'ssleay32.dll' and 'libeay32'dll'.
// When OpenSSL is built using GCC then different library names are used (depending on the OpenSSL version)
// The oldest version of a GCC-based OpenSSL which can be detected by the code below is 0.9.8g (released in 2007)
if (!tryToLoadOpenSslWin32Library(QLatin1String("ssleay32"), QLatin1String("libeay32"), result)) {
if (!tryToLoadOpenSslWin32Library(QLatin1String("libssl-10"), QLatin1String("libcrypto-10"), result)) {
if (!tryToLoadOpenSslWin32Library(QLatin1String("libssl-8"), QLatin1String("libcrypto-8"), result)) {
tryToLoadOpenSslWin32Library(QLatin1String("libssl-7"), QLatin1String("libcrypto-7"), result);
}
}
}
#endif // !QT_CONFIG(opensslv11)
return result;
}
#else
@ -852,27 +731,6 @@ static LoadedOpenSsl loadOpenSsl()
libssl->unload();
libcrypto->unload();
}
#if !QT_CONFIG(opensslv11)
// first-and-half attempts: for OpenSSL 1.0 try to load some hardcoded sonames:
// - "1.0.0" is the official upstream one
// - "1.0.2" is found on some distributions (e.g. Debian) that patch OpenSSL
static const QLatin1String fallbackSonames[] = {
QLatin1String("1.0.0"),
QLatin1String("1.0.2")
};
for (auto fallbackSoname : fallbackSonames) {
libssl->setFileNameAndVersion(QLatin1String("ssl"), fallbackSoname);
libcrypto->setFileNameAndVersion(QLatin1String("crypto"), fallbackSoname);
if (libcrypto->load() && libssl->load()) {
return result;
} else {
libssl->unload();
libcrypto->unload();
}
}
#endif
#endif
#ifndef Q_OS_DARWIN
@ -890,11 +748,9 @@ static LoadedOpenSsl loadOpenSsl()
return defaultSuffix;
return suffix;
};
# if QT_CONFIG(opensslv11)
static QString suffix = QString::fromLatin1(openSSLSuffix("_1_1"));
# else
static QString suffix = QString::fromLatin1(openSSLSuffix());
# endif
libssl->setFileNameAndVersion(QLatin1String("ssl") + suffix, -1);
libcrypto->setFileNameAndVersion(QLatin1String("crypto") + suffix, -1);
# else
@ -968,8 +824,6 @@ 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)
@ -985,10 +839,12 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(OPENSSL_sk_value)
RESOLVEFUNC(DH_get0_pqg)
RESOLVEFUNC(SSL_CTX_set_options)
#ifdef TLS1_3_VERSION
RESOLVEFUNC(SSL_CTX_set_ciphersuites)
RESOLVEFUNC(SSL_set_psk_use_session_callback)
#endif // TLS 1.3 or OpenSSL > 1.1.1
RESOLVEFUNC(SSL_get_client_random)
RESOLVEFUNC(SSL_SESSION_get_master_key)
RESOLVEFUNC(SSL_session_reused)
@ -1010,6 +866,7 @@ bool q_resolveOpenSslSymbols()
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.
@ -1034,6 +891,7 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(BIO_meth_set_create)
RESOLVEFUNC(BIO_meth_set_destroy)
#endif // dtls
#if QT_CONFIG(ocsp)
RESOLVEFUNC(OCSP_SINGLERESP_get0_id)
RESOLVEFUNC(d2i_OCSP_RESPONSE)
@ -1058,99 +916,12 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(OCSP_cert_to_id)
RESOLVEFUNC(OCSP_id_cmp)
#endif // ocsp
RESOLVEFUNC(BIO_set_data)
RESOLVEFUNC(BIO_get_data)
RESOLVEFUNC(BIO_set_init)
RESOLVEFUNC(BIO_get_shutdown)
RESOLVEFUNC(BIO_set_shutdown)
#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(CRYPTO_set_ex_data)
RESOLVEFUNC(CRYPTO_get_ex_data)
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
RESOLVEFUNC(SSLv23_client_method)
RESOLVEFUNC(TLSv1_client_method)
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
RESOLVEFUNC(TLSv1_1_client_method)
RESOLVEFUNC(TLSv1_2_client_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
#if QT_CONFIG(dtls)
RESOLVEFUNC(DTLSv1_server_method)
RESOLVEFUNC(DTLSv1_client_method)
RESOLVEFUNC(DTLSv1_2_server_method)
RESOLVEFUNC(DTLSv1_2_client_method)
#endif // dtls
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.
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_INTEGER_cmp)
RESOLVEFUNC(ASN1_STRING_length)
@ -1172,9 +943,7 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(EC_GROUP_get_degree)
#endif
RESOLVEFUNC(BN_num_bits)
#if QT_CONFIG(opensslv11)
RESOLVEFUNC(BN_is_word)
#endif
RESOLVEFUNC(BN_mod_word)
RESOLVEFUNC(DSA_new)
RESOLVEFUNC(DSA_free)
@ -1207,17 +976,21 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(EVP_PKEY_set1_RSA)
RESOLVEFUNC(EVP_PKEY_set1_DSA)
RESOLVEFUNC(EVP_PKEY_set1_DH)
#ifndef OPENSSL_NO_EC
RESOLVEFUNC(EVP_PKEY_set1_EC_KEY)
#endif
RESOLVEFUNC(EVP_PKEY_get1_EC_KEY)
RESOLVEFUNC(PEM_read_bio_ECPrivateKey)
RESOLVEFUNC(PEM_write_bio_ECPrivateKey)
RESOLVEFUNC(PEM_read_bio_EC_PUBKEY)
RESOLVEFUNC(PEM_write_bio_EC_PUBKEY)
#endif // OPENSSL_NO_EC
RESOLVEFUNC(EVP_PKEY_cmp)
RESOLVEFUNC(EVP_PKEY_free)
RESOLVEFUNC(EVP_PKEY_get1_DSA)
RESOLVEFUNC(EVP_PKEY_get1_RSA)
RESOLVEFUNC(EVP_PKEY_get1_DH)
#ifndef OPENSSL_NO_EC
RESOLVEFUNC(EVP_PKEY_get1_EC_KEY)
#endif
RESOLVEFUNC(EVP_PKEY_new)
RESOLVEFUNC(EVP_PKEY_type)
RESOLVEFUNC(OBJ_nid2sn)
@ -1227,35 +1000,19 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(i2t_ASN1_OBJECT)
RESOLVEFUNC(OBJ_obj2txt)
RESOLVEFUNC(OBJ_obj2nid)
#ifndef SSLEAY_MACROS
RESOLVEFUNC(PEM_read_bio_PrivateKey)
RESOLVEFUNC(PEM_read_bio_DSAPrivateKey)
RESOLVEFUNC(PEM_read_bio_RSAPrivateKey)
#ifndef OPENSSL_NO_EC
RESOLVEFUNC(PEM_read_bio_ECPrivateKey)
#endif
RESOLVEFUNC(PEM_read_bio_DHparams)
RESOLVEFUNC(PEM_write_bio_DSAPrivateKey)
RESOLVEFUNC(PEM_write_bio_RSAPrivateKey)
RESOLVEFUNC(PEM_write_bio_PrivateKey)
#ifndef OPENSSL_NO_EC
RESOLVEFUNC(PEM_write_bio_ECPrivateKey)
#endif
#endif // !SSLEAY_MACROS
RESOLVEFUNC(PEM_read_bio_PUBKEY)
RESOLVEFUNC(PEM_read_bio_DSA_PUBKEY)
RESOLVEFUNC(PEM_read_bio_RSA_PUBKEY)
#ifndef OPENSSL_NO_EC
RESOLVEFUNC(PEM_read_bio_EC_PUBKEY)
#endif
RESOLVEFUNC(PEM_write_bio_DSA_PUBKEY)
RESOLVEFUNC(PEM_write_bio_RSA_PUBKEY)
RESOLVEFUNC(PEM_write_bio_PUBKEY)
#ifndef OPENSSL_NO_EC
RESOLVEFUNC(PEM_write_bio_EC_PUBKEY)
#endif
RESOLVEFUNC(RAND_seed)
RESOLVEFUNC(RAND_status)
RESOLVEFUNC(RAND_bytes)
@ -1279,14 +1036,12 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(SSL_CTX_use_RSAPrivateKey)
RESOLVEFUNC(SSL_CTX_use_PrivateKey_file)
RESOLVEFUNC(SSL_CTX_get_cert_store);
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
RESOLVEFUNC(SSL_CONF_CTX_new);
RESOLVEFUNC(SSL_CONF_CTX_free);
RESOLVEFUNC(SSL_CONF_CTX_set_ssl_ctx);
RESOLVEFUNC(SSL_CONF_CTX_set_flags);
RESOLVEFUNC(SSL_CONF_CTX_finish);
RESOLVEFUNC(SSL_CONF_cmd);
#endif
RESOLVEFUNC(SSL_accept)
RESOLVEFUNC(SSL_clear)
RESOLVEFUNC(SSL_connect)
@ -1311,16 +1066,16 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(SSL_SESSION_free)
RESOLVEFUNC(SSL_get1_session)
RESOLVEFUNC(SSL_get_session)
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
RESOLVEFUNC(SSL_set_ex_data)
RESOLVEFUNC(SSL_get_ex_data)
RESOLVEFUNC(SSL_get_ex_data_X509_STORE_CTX_idx)
#endif
#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
#ifndef OPENSSL_NO_PSK
RESOLVEFUNC(SSL_set_psk_client_callback)
RESOLVEFUNC(SSL_set_psk_server_callback)
RESOLVEFUNC(SSL_CTX_use_psk_identity_hint)
#endif
#endif // !OPENSSL_NO_PSK
RESOLVEFUNC(SSL_write)
RESOLVEFUNC(X509_NAME_entry_count)
RESOLVEFUNC(X509_NAME_get_entry)
@ -1340,10 +1095,7 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(X509_STORE_CTX_get0_store)
RESOLVEFUNC(X509_cmp)
RESOLVEFUNC(X509_STORE_CTX_get_ex_data)
#ifndef SSLEAY_MACROS
RESOLVEFUNC(X509_dup)
#endif
RESOLVEFUNC(X509_print)
RESOLVEFUNC(X509_digest)
RESOLVEFUNC(X509_EXTENSION_get_object)
@ -1371,22 +1123,23 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(SSL_CTX_load_verify_locations)
RESOLVEFUNC(i2d_SSL_SESSION)
RESOLVEFUNC(d2i_SSL_SESSION)
#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG)
#ifndef OPENSSL_NO_NEXTPROTONEG
RESOLVEFUNC(SSL_select_next_proto)
RESOLVEFUNC(SSL_CTX_set_next_proto_select_cb)
RESOLVEFUNC(SSL_get0_next_proto_negotiated)
#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ...
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
RESOLVEFUNC(SSL_set_alpn_protos)
RESOLVEFUNC(SSL_CTX_set_alpn_select_cb)
RESOLVEFUNC(SSL_get0_alpn_selected)
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L ...
#endif // !OPENSSL_NO_NEXTPROTONEG
#if QT_CONFIG(dtls)
RESOLVEFUNC(SSL_CTX_set_cookie_generate_cb)
RESOLVEFUNC(SSL_CTX_set_cookie_verify_cb)
RESOLVEFUNC(DTLS_server_method)
RESOLVEFUNC(DTLS_client_method)
#endif // dtls
RESOLVEFUNC(CRYPTO_malloc)
RESOLVEFUNC(DH_new)
RESOLVEFUNC(DH_free)
@ -1394,12 +1147,14 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(i2d_DHparams)
RESOLVEFUNC(DH_check)
RESOLVEFUNC(BN_bin2bn)
#ifndef OPENSSL_NO_EC
RESOLVEFUNC(EC_KEY_dup)
RESOLVEFUNC(EC_KEY_new_by_curve_name)
RESOLVEFUNC(EC_KEY_free)
RESOLVEFUNC(EC_get_builtin_curves)
#endif // OPENSSL_NO_EC
RESOLVEFUNC(PKCS12_parse)
RESOLVEFUNC(d2i_PKCS12_bio)
RESOLVEFUNC(PKCS12_free)

View File

@ -220,11 +220,129 @@ 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
// TODO: the following lines previously were a part of 1.1 - specific header.
// To reduce the amount of the change, I'm directly copying and pasting the
// content of the header here. Later, can be better sorted/split into groups,
// depending on the functionality.
//#include "qsslsocket_openssl11_symbols_p.h"
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);
Q_AUTOTEST_EXPORT int q_EVP_PKEY_up_ref(EVP_PKEY *a);
int q_EVP_PKEY_base_id(EVP_PKEY *a);
int q_RSA_bits(RSA *a);
Q_AUTOTEST_EXPORT int q_OPENSSL_sk_num(OPENSSL_STACK *a);
Q_AUTOTEST_EXPORT void q_OPENSSL_sk_pop_free(OPENSSL_STACK *a, void (*b)(void *));
Q_AUTOTEST_EXPORT OPENSSL_STACK *q_OPENSSL_sk_new_null();
Q_AUTOTEST_EXPORT void q_OPENSSL_sk_push(OPENSSL_STACK *st, void *data);
Q_AUTOTEST_EXPORT void q_OPENSSL_sk_free(OPENSSL_STACK *a);
Q_AUTOTEST_EXPORT 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);
Q_AUTOTEST_EXPORT void q_X509_up_ref(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);
int q_X509_STORE_set_ex_data(X509_STORE *ctx, int idx, void *data);
void *q_X509_STORE_get_ex_data(X509_STORE *r, int idx);
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);
unsigned long q_SSL_set_options(SSL *s, unsigned long op);
#ifdef TLS1_3_VERSION
int q_SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str);
#endif
#if QT_CONFIG(dtls)
// Functions and types required for DTLS support:
extern "C"
{
typedef int (*CookieVerifyCallback)(SSL *, const unsigned char *, unsigned);
typedef int (*DgramWriteCallback) (BIO *, const char *, int);
typedef int (*DgramReadCallback) (BIO *, char *, int);
typedef int (*DgramPutsCallback) (BIO *, const char *);
typedef long (*DgramCtrlCallback) (BIO *, int, long, void *);
typedef int (*DgramCreateCallback) (BIO *);
typedef int (*DgramDestroyCallback) (BIO *);
}
int q_DTLSv1_listen(SSL *s, BIO_ADDR *client);
BIO_ADDR *q_BIO_ADDR_new();
void q_BIO_ADDR_free(BIO_ADDR *ap);
// API we need for a custom dgram BIO:
BIO_METHOD *q_BIO_meth_new(int type, const char *name);
void q_BIO_meth_free(BIO_METHOD *biom);
int q_BIO_meth_set_write(BIO_METHOD *biom, DgramWriteCallback);
int q_BIO_meth_set_read(BIO_METHOD *biom, DgramReadCallback);
int q_BIO_meth_set_puts(BIO_METHOD *biom, DgramPutsCallback);
int q_BIO_meth_set_ctrl(BIO_METHOD *biom, DgramCtrlCallback);
int q_BIO_meth_set_create(BIO_METHOD *biom, DgramCreateCallback);
int q_BIO_meth_set_destroy(BIO_METHOD *biom, DgramDestroyCallback);
#endif // dtls
void q_BIO_set_data(BIO *a, void *ptr);
void *q_BIO_get_data(BIO *a);
void q_BIO_set_init(BIO *a, int init);
int q_BIO_get_shutdown(BIO *a);
void q_BIO_set_shutdown(BIO *a, int shut);
#if QT_CONFIG(ocsp)
const OCSP_CERTID *q_OCSP_SINGLERESP_get0_id(const OCSP_SINGLERESP *x);
#endif // ocsp
#define q_SSL_CTX_set_min_proto_version(ctx, version) \
q_SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MIN_PROTO_VERSION, version, nullptr)
#define q_SSL_CTX_set_max_proto_version(ctx, version) \
q_SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MAX_PROTO_VERSION, version, nullptr)
extern "C" {
typedef int (*q_SSL_psk_use_session_cb_func_t)(SSL *, const EVP_MD *, const unsigned char **, size_t *,
SSL_SESSION **);
}
void q_SSL_set_psk_use_session_callback(SSL *s, q_SSL_psk_use_session_cb_func_t);
// Here the content of the 1.1 header ends.
bool q_resolveOpenSslSymbols();
long q_ASN1_INTEGER_get(ASN1_INTEGER *a);
@ -237,27 +355,14 @@ BIO *q_BIO_new_mem_buf(void *a, int b);
int q_BIO_read(BIO *a, void *b, int c);
Q_AUTOTEST_EXPORT int q_BIO_write(BIO *a, const void *b, int c);
int q_BN_num_bits(const BIGNUM *a);
#if QT_CONFIG(opensslv11)
int q_BN_is_word(BIGNUM *a, BN_ULONG w);
#else // opensslv11
// BN_is_word is implemented purely as a
// macro in OpenSSL < 1.1. It doesn't
// call any functions.
//
// The implementation of BN_is_word is
// 100% the same between 1.0.0, 1.0.1
// and 1.0.2.
//
// Users are required to include <openssl/bn.h>.
#define q_BN_is_word BN_is_word
#endif // !opensslv11
BN_ULONG q_BN_mod_word(const BIGNUM *a, BN_ULONG w);
#ifndef OPENSSL_NO_EC
const EC_GROUP* q_EC_KEY_get0_group(const EC_KEY* k);
int q_EC_GROUP_get_degree(const EC_GROUP* g);
#endif
#endif // OPENSSL_NO_EC
DSA *q_DSA_new();
void q_DSA_free(DSA *a);
X509 *q_d2i_X509(X509 **a, const unsigned char **b, long c);
@ -277,23 +382,28 @@ const EVP_MD *q_EVP_get_digestbyname(const char *name);
#ifndef OPENSSL_NO_DES
const EVP_CIPHER *q_EVP_des_cbc();
const EVP_CIPHER *q_EVP_des_ede3_cbc();
#endif
#endif // OPENSSL_NO_DES
#ifndef OPENSSL_NO_RC2
const EVP_CIPHER *q_EVP_rc2_cbc();
#endif
#endif // OPENSSL_NO_RC2
#ifndef OPENSSL_NO_AES
const EVP_CIPHER *q_EVP_aes_128_cbc();
const EVP_CIPHER *q_EVP_aes_192_cbc();
const EVP_CIPHER *q_EVP_aes_256_cbc();
#endif
#endif // OPENSSL_NO_AES
Q_AUTOTEST_EXPORT 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);
Q_AUTOTEST_EXPORT int q_EVP_PKEY_set1_DSA(EVP_PKEY *a, DSA *b);
Q_AUTOTEST_EXPORT int q_EVP_PKEY_set1_DH(EVP_PKEY *a, DH *b);
#ifndef OPENSSL_NO_EC
Q_AUTOTEST_EXPORT int q_EVP_PKEY_set1_EC_KEY(EVP_PKEY *a, EC_KEY *b);
#endif
Q_AUTOTEST_EXPORT int q_EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b);
Q_AUTOTEST_EXPORT void q_EVP_PKEY_free(EVP_PKEY *a);
RSA *q_EVP_PKEY_get1_RSA(EVP_PKEY *a);
@ -313,18 +423,18 @@ int q_i2t_ASN1_OBJECT(char *buf, int buf_len, ASN1_OBJECT *obj);
int q_OBJ_obj2txt(char *buf, int buf_len, ASN1_OBJECT *obj, int no_name);
int q_OBJ_obj2nid(const ASN1_OBJECT *a);
#define q_EVP_get_digestbynid(a) q_EVP_get_digestbyname(q_OBJ_nid2sn(a))
#ifdef SSLEAY_MACROS
// ### verify
void *q_PEM_ASN1_read_bio(d2i_of_void *a, const char *b, BIO *c, void **d, pem_password_cb *e,
void *f);
// ### ditto for write
#else
Q_AUTOTEST_EXPORT EVP_PKEY *q_PEM_read_bio_PrivateKey(BIO *a, EVP_PKEY **b, pem_password_cb *c, void *d);
DSA *q_PEM_read_bio_DSAPrivateKey(BIO *a, DSA **b, pem_password_cb *c, void *d);
RSA *q_PEM_read_bio_RSAPrivateKey(BIO *a, RSA **b, pem_password_cb *c, void *d);
#ifndef OPENSSL_NO_EC
EC_KEY *q_PEM_read_bio_ECPrivateKey(BIO *a, EC_KEY **b, pem_password_cb *c, void *d);
#endif
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);
EC_KEY *q_PEM_read_bio_EC_PUBKEY(BIO *a, EC_KEY **b, pem_password_cb *c, void *d);
int q_PEM_write_bio_EC_PUBKEY(BIO *a, EC_KEY *b);
#endif // OPENSSL_NO_EC
DH *q_PEM_read_bio_DHparams(BIO *a, DH **b, pem_password_cb *c, void *d);
int q_PEM_write_bio_DSAPrivateKey(BIO *a, DSA *b, const EVP_CIPHER *c, unsigned char *d,
int e, pem_password_cb *f, void *g);
@ -332,23 +442,13 @@ int q_PEM_write_bio_RSAPrivateKey(BIO *a, RSA *b, const EVP_CIPHER *c, unsigned
int e, pem_password_cb *f, void *g);
int q_PEM_write_bio_PrivateKey(BIO *a, EVP_PKEY *b, const EVP_CIPHER *c, unsigned char *d,
int e, pem_password_cb *f, void *g);
#ifndef OPENSSL_NO_EC
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 // 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);
#ifndef OPENSSL_NO_EC
EC_KEY *q_PEM_read_bio_EC_PUBKEY(BIO *a, EC_KEY **b, pem_password_cb *c, void *d);
#endif
int q_PEM_write_bio_DSA_PUBKEY(BIO *a, DSA *b);
int q_PEM_write_bio_RSA_PUBKEY(BIO *a, RSA *b);
int q_PEM_write_bio_PUBKEY(BIO *a, EVP_PKEY *b);
#ifndef OPENSSL_NO_EC
int q_PEM_write_bio_EC_PUBKEY(BIO *a, EC_KEY *b);
#endif
void q_RAND_seed(const void *a, int b);
int q_RAND_status();
int q_RAND_bytes(unsigned char *b, int n);
@ -378,14 +478,12 @@ int q_SSL_CTX_use_PrivateKey(SSL_CTX *a, EVP_PKEY *b);
int q_SSL_CTX_use_RSAPrivateKey(SSL_CTX *a, RSA *b);
int q_SSL_CTX_use_PrivateKey_file(SSL_CTX *a, const char *b, int c);
X509_STORE *q_SSL_CTX_get_cert_store(const SSL_CTX *a);
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
SSL_CONF_CTX *q_SSL_CONF_CTX_new();
void q_SSL_CONF_CTX_free(SSL_CONF_CTX *a);
void q_SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *a, SSL_CTX *b);
unsigned int q_SSL_CONF_CTX_set_flags(SSL_CONF_CTX *a, unsigned int b);
int q_SSL_CONF_CTX_finish(SSL_CONF_CTX *a);
int q_SSL_CONF_cmd(SSL_CONF_CTX *a, const char *b, const char *c);
#endif
void q_SSL_free(SSL *a);
STACK_OF(SSL_CIPHER) *q_SSL_get_ciphers(const SSL *a);
const SSL_CIPHER *q_SSL_get_current_cipher(SSL *a);
@ -407,26 +505,18 @@ int q_SSL_set_session(SSL *to, SSL_SESSION *session);
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_set_ex_data(SSL *ssl, int idx, void *arg);
void *q_SSL_get_ex_data(const SSL *ssl, int idx);
#endif
#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
#ifndef OPENSSL_NO_PSK
typedef unsigned int (*q_psk_client_callback_t)(SSL *ssl, const char *hint, char *identity, unsigned int max_identity_len, unsigned char *psk, unsigned int max_psk_len);
void q_SSL_set_psk_client_callback(SSL *ssl, q_psk_client_callback_t callback);
typedef unsigned int (*q_psk_server_callback_t)(SSL *ssl, const char *identity, unsigned char *psk, unsigned int max_psk_len);
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)
#endif // !OPENSSL_NO_PSK
int q_SSL_write(SSL *a, const void *b, int c);
int q_X509_cmp(X509 *a, X509 *b);
#ifdef SSLEAY_MACROS
void *q_ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, char *x);
#define q_X509_dup(x509) (X509 *)q_ASN1_dup((i2d_of_void *)q_i2d_X509, \
(d2i_of_void *)q_d2i_X509,(char *)x509)
#else
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);
@ -485,13 +575,10 @@ void q_EC_KEY_free(EC_KEY *ecdh);
// EC curves management
size_t q_EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems);
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
int q_EC_curve_nist2nid(const char *name);
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
#endif // OPENSSL_NO_EC
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
#define q_SSL_get_server_tmp_key(ssl, key) q_SSL_ctrl((ssl), SSL_CTRL_GET_SERVER_TMP_KEY, 0, (char *)key)
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
// PKCS#12 support
int q_PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca);
@ -521,7 +608,7 @@ int q_SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, const char
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);
#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG)
#ifndef OPENSSL_NO_NEXTPROTONEG
int q_SSL_select_next_proto(unsigned char **out, unsigned char *outlen,
const unsigned char *in, unsigned int inlen,
const unsigned char *client, unsigned int client_len);
@ -533,7 +620,6 @@ void q_SSL_CTX_set_next_proto_select_cb(SSL_CTX *s,
void *arg);
void q_SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data,
unsigned *len);
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
int q_SSL_set_alpn_protos(SSL *ssl, const unsigned char *protos,
unsigned protos_len);
void q_SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx,
@ -545,8 +631,8 @@ void q_SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx,
void *arg), void *arg);
void q_SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data,
unsigned *len);
#endif
#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ...
#endif // !OPENSSL_NO_NEXTPROTONEG
#if QT_CONFIG(dtls)
@ -586,13 +672,9 @@ int q_BIO_set_ex_data(BIO *b, int idx, void *data);
class QDateTime;
QDateTime q_getTimeFromASN1(const ASN1_TIME *aTime);
#ifndef OPENSSL_NO_TLSEXT
#define q_SSL_set_tlsext_status_type(ssl, type) \
q_SSL_ctrl((ssl), SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE, (type), nullptr)
#endif // OPENSSL_NO_TLSEXT
#if QT_CONFIG(ocsp)
OCSP_RESPONSE *q_d2i_OCSP_RESPONSE(OCSP_RESPONSE **a, const unsigned char **in, long len);

View File

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

View File

@ -1,202 +0,0 @@
/****************************************************************************
**
** 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);
int q_CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int idx, void *val);
void *q_CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad, int idx);
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);
typedef _STACK STACK;
// 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
void *q_sk_value(STACK *a, int b);
void q_sk_push(STACK *st, void *data);
#define q_OPENSSL_sk_value(a, b) q_sk_value(a, b)
#define q_OPENSSL_sk_push(st, data) q_sk_push(st, data)
SSL_CTX *q_SSL_CTX_new(const SSL_METHOD *a);
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
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();
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();
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_SSL_set_options(ssl,op) q_SSL_ctrl((ssl),SSL_CTRL_OPTIONS,(op),nullptr)
#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_DH_bits(dsa) q_BN_num_bits((dh)->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);
#if QT_CONFIG(dtls)
// DTLS:
extern "C"
{
typedef int (*CookieVerifyCallback)(SSL *, unsigned char *, unsigned);
}
#define q_DTLSv1_listen(ssl, peer) q_SSL_ctrl(ssl, DTLS_CTRL_LISTEN, 0, (void *)peer)
const SSL_METHOD *q_DTLSv1_server_method();
const SSL_METHOD *q_DTLSv1_client_method();
const SSL_METHOD *q_DTLSv1_2_server_method();
const SSL_METHOD *q_DTLSv1_2_client_method();
#endif // dtls
#endif // QSSLSOCKET_OPENSSL_PRE11_SYMBOLS_P_H

View File

@ -127,7 +127,6 @@ public:
static long sslLibraryBuildVersionNumber();
static QString sslLibraryBuildVersionString();
static void ensureInitialized();
static void deinitialize();
static QList<QSslCipher> defaultCiphers();
static QList<QSslCipher> supportedCiphers();
static void setDefaultCiphers(const QList<QSslCipher> &ciphers);

View File

@ -157,11 +157,6 @@ QSslSocketBackendPrivate::~QSslSocketBackendPrivate()
g->syncCaCertificates(QSet<QSslCertificate>(), previousCaCertificates);
}
void QSslSocketPrivate::deinitialize()
{
Q_UNIMPLEMENTED();
}
bool QSslSocketPrivate::supportsSsl()
{
return true;

View File

@ -102,17 +102,7 @@ qtConfig(ssl) {
qtConfig(ocsp): HEADERS += ssl/qocsp_p.h
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
}
QMAKE_CXXFLAGS += -DOPENSSL_API_COMPAT=0x10100000L
darwin:SOURCES += ssl/qsslsocket_mac_shared.cpp

View File

@ -837,10 +837,6 @@ void tst_QDtls::verifyServerCertificate()
void tst_QDtls::verifyClientCertificate_data()
{
#if !QT_CONFIG(opensslv11)
QSKIP("This test is not supposed to work with OpenSSL version below 1.1");
#endif
QTest::addColumn<QSslSocket::PeerVerifyMode>("verifyMode");
QTest::addColumn<QList<QSslCertificate>>("clientCerts");
QTest::addColumn<QSslKey>("clientKey");

View File

@ -77,7 +77,7 @@ typedef QSharedPointer<QSslSocket> QSslSocketPtr;
// Detect ALPN (Application-Layer Protocol Negotiation) support
#undef ALPN_SUPPORTED // Undef the variable first to be safe
#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_TLSEXT)
#if defined(OPENSSL_VERSION_NUMBER) && !defined(OPENSSL_NO_TLSEXT)
#define ALPN_SUPPORTED 1
#endif
@ -94,11 +94,13 @@ typedef QSharedPointer<QSslSocket> QSslSocketPtr;
// Use this cipher to force PSK key sharing.
// Also, it's a cipher w/o auth, to check that we emit the signals warning
// about the identity of the peer.
#ifndef QT_NO_OPENSSL
static const QString PSK_CIPHER_WITHOUT_AUTH = QStringLiteral("PSK-AES256-CBC-SHA");
static const quint16 PSK_SERVER_PORT = 4433;
static const QByteArray PSK_CLIENT_PRESHAREDKEY = QByteArrayLiteral("\x1a\x2b\x3c\x4d\x5e\x6f");
static const QByteArray PSK_SERVER_IDENTITY_HINT = QByteArrayLiteral("QtTestServerHint");
static const QByteArray PSK_CLIENT_IDENTITY = QByteArrayLiteral("Client_identity");
#endif // !QT_NO_OPENSSL
class tst_QSslSocket : public QObject
{
@ -1100,7 +1102,6 @@ void tst_QSslSocket::protocol()
QCOMPARE(socket->protocol(), QSsl::TlsV1_0);
socket->abort();
}
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
{
// qt-test-server probably doesn't allow TLSV1.1
socket->setProtocol(QSsl::TlsV1_1);
@ -1137,7 +1138,7 @@ void tst_QSslSocket::protocol()
QCOMPARE(socket->protocol(), QSsl::TlsV1_2);
socket->abort();
}
#endif
#ifdef TLS1_3_VERSION
{
// qt-test-server probably doesn't allow TLSV1.3
@ -2642,7 +2643,6 @@ void tst_QSslSocket::ignoreSslErrorsList()
connect(&socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
this, SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
// this->socket = &socket;
QSslCertificate cert;
QFETCH(QList<QSslError>, expectedSslErrors);
@ -4050,9 +4050,6 @@ void tst_QSslSocket::ephemeralServerKey_data()
QTest::addColumn<QString>("cipher");
QTest::addColumn<bool>("emptyKey");
#if !QT_CONFIG(opensslv11) // 1.1 drops support for RC4-SHA
QTest::newRow("NonForwardSecrecyCipher") << "RC4-SHA" << true;
#endif // !opensslv11
QTest::newRow("ForwardSecrecyCipher") << "ECDHE-RSA-AES256-SHA" << (QSslSocket::sslLibraryVersionNumber() < 0x10002000L);
}
@ -4177,9 +4174,6 @@ void tst_QSslSocket::signatureAlgorithm_data()
if (!QSslSocket::supportsSsl())
QSKIP("Signature algorithms cannot be tested without SSL support");
if (QSslSocket::sslLibraryVersionNumber() < 0x10002000L)
QSKIP("Signature algorithms cannot be tested with OpenSSL < 1.0.2");
if (QSslSocket::sslLibraryVersionNumber() >= 0x10101000L) {
// FIXME: investigate if this test makes any sense with TLS 1.3.
QSKIP("Test is not valid for TLS 1.3/OpenSSL 1.1.1");