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:
parent
7a13a09116
commit
1a878e65c2
@ -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": {
|
||||
|
@ -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"));
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 ¶ms = 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"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 ¶ms = 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
|
@ -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
|
||||
|
@ -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 ¶ms = dhparams.d->derData;
|
||||
const char *ptr = params.constData();
|
||||
DH *dh = q_d2i_DHparams(NULL, reinterpret_cast<const unsigned char **>(&ptr), params.length());
|
||||
if (dh == NULL)
|
||||
qFatal("q_d2i_DHparams failed to convert QSslDiffieHellmanParameters to DER form");
|
||||
q_SSL_CTX_set_tmp_dh(sslContext->ctx, dh);
|
||||
q_DH_free(dh);
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_EC
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
if (q_SSLeay() >= 0x10002000L) {
|
||||
q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_SET_ECDH_AUTO, 1, NULL);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
// Set temp ECDH params
|
||||
EC_KEY *ecdh = 0;
|
||||
ecdh = q_EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
|
||||
q_SSL_CTX_set_tmp_ecdh(sslContext->ctx, ecdh);
|
||||
q_EC_KEY_free(ecdh);
|
||||
}
|
||||
#endif // OPENSSL_NO_EC
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
|
||||
if (!client)
|
||||
q_SSL_CTX_use_psk_identity_hint(sslContext->ctx, sslContext->sslConfiguration.preSharedKeyIdentityHint().constData());
|
||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
|
||||
|
||||
const QVector<QSslEllipticCurve> qcurves = sslContext->sslConfiguration.ellipticCurves();
|
||||
if (!qcurves.isEmpty()) {
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_EC)
|
||||
// Set the curves to be used
|
||||
if (q_SSLeay() >= 0x10002000L) {
|
||||
// SSL_CTX_ctrl wants a non-const pointer as last argument,
|
||||
// but let's avoid a copy into a temporary array
|
||||
if (!q_SSL_CTX_ctrl(sslContext->ctx,
|
||||
SSL_CTRL_SET_CURVES,
|
||||
qcurves.size(),
|
||||
const_cast<int *>(reinterpret_cast<const int *>(qcurves.data())))) {
|
||||
sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
|
||||
sslContext->errorCode = QSslError::UnspecifiedError;
|
||||
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
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
@ -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
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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
|
@ -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
|
@ -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);
|
||||
|
@ -157,11 +157,6 @@ QSslSocketBackendPrivate::~QSslSocketBackendPrivate()
|
||||
g->syncCaCertificates(QSet<QSslCertificate>(), previousCaCertificates);
|
||||
}
|
||||
|
||||
void QSslSocketPrivate::deinitialize()
|
||||
{
|
||||
Q_UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
bool QSslSocketPrivate::supportsSsl()
|
||||
{
|
||||
return true;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user