Merge remote-tracking branch 'origin/5.15' into dev
Change-Id: I256a4b0bac4d2f5eb170967fedc4eccaec8c7f2abb10
commit
ab6affac10
|
|
@ -52,21 +52,6 @@
|
|||
|
||||
#include <QDebug>
|
||||
|
||||
//! [Message class implementation]
|
||||
Message::Message()
|
||||
{
|
||||
}
|
||||
|
||||
Message::Message(const Message &other)
|
||||
: m_body(other.m_body), m_headers(other.m_headers)
|
||||
{
|
||||
}
|
||||
|
||||
Message::~Message()
|
||||
{
|
||||
}
|
||||
//! [Message class implementation]
|
||||
|
||||
Message::Message(const QString &body, const QStringList &headers)
|
||||
: m_body(body), m_headers(headers)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -58,9 +58,10 @@
|
|||
class Message
|
||||
{
|
||||
public:
|
||||
Message();
|
||||
Message(const Message &other);
|
||||
~Message();
|
||||
Message() = default;
|
||||
~Message() = default;
|
||||
Message(const Message &) = default;
|
||||
Message &operator=(const Message &) = default;
|
||||
|
||||
Message(const QString &body, const QStringList &headers);
|
||||
|
||||
|
|
|
|||
|
|
@ -50,19 +50,6 @@
|
|||
|
||||
#include "message.h"
|
||||
|
||||
Message::Message()
|
||||
{
|
||||
}
|
||||
|
||||
Message::Message(const Message &other)
|
||||
: m_body(other.m_body), m_headers(other.m_headers)
|
||||
{
|
||||
}
|
||||
|
||||
Message::~Message()
|
||||
{
|
||||
}
|
||||
|
||||
Message::Message(const QString &body, const QStringList &headers)
|
||||
: m_body(body), m_headers(headers)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -58,9 +58,10 @@
|
|||
class Message
|
||||
{
|
||||
public:
|
||||
Message();
|
||||
Message(const Message &other);
|
||||
~Message();
|
||||
Message() = default;
|
||||
~Message() = default;
|
||||
Message(const Message &) = default;
|
||||
Message &operator=(const Message &) = default;
|
||||
|
||||
Message(const QString &body, const QStringList &headers);
|
||||
|
||||
|
|
|
|||
|
|
@ -81,11 +81,6 @@
|
|||
|
||||
\section1 The Message Class Implementation
|
||||
|
||||
The implementation of the default constructor, copy constructor and destructor
|
||||
are straightforward for the \c Message class:
|
||||
|
||||
\snippet tools/customtype/message.cpp Message class implementation
|
||||
|
||||
The streaming operator is implemented in the following way:
|
||||
|
||||
\snippet tools/customtype/message.cpp custom type streaming operator
|
||||
|
|
|
|||
|
|
@ -38,6 +38,11 @@
|
|||
#include <double-conversion/strtod.h>
|
||||
#include <double-conversion/utils.h>
|
||||
|
||||
// Fix warning C4244: 'argument': conversion from 'const uc16' to 'char', possible loss of data
|
||||
#ifdef _MSC_VER
|
||||
__pragma(warning(disable: 4244))
|
||||
#endif
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
const DoubleToStringConverter& DoubleToStringConverter::EcmaScriptConverter() {
|
||||
|
|
|
|||
|
|
@ -2599,7 +2599,7 @@ void QStateMachine::setGlobalRestorePolicy(QState::RestorePolicy restorePolicy)
|
|||
|
||||
/*!
|
||||
Adds the given \a state to this state machine. The state becomes a top-level
|
||||
state.
|
||||
state and the state machine takes ownership of the state.
|
||||
|
||||
If the state is already in a different machine, it will first be removed
|
||||
from its old machine, and then added to this machine.
|
||||
|
|
|
|||
|
|
@ -56,8 +56,6 @@ using namespace QRoundingDown;
|
|||
\brief The QMilankovicCalendar class provides Milanković calendar system
|
||||
implementation.
|
||||
|
||||
\section1
|
||||
|
||||
The Revised Julian calendar, also known as the Milanković calendar, or,
|
||||
less formally, new calendar, is a calendar, developed and proposed by the
|
||||
Serbian scientist Milutin Milanković in 1923, which effectively discontinued
|
||||
|
|
|
|||
|
|
@ -6044,11 +6044,11 @@ static inline void alphargbblend_argb32(quint32 *dst, uint coverage, const QRgba
|
|||
// nothing
|
||||
} else if (coverage == 0xffffffff && qAlpha(src) == 255) {
|
||||
blend_pixel(*dst, src);
|
||||
} else if (!colorProfile) {
|
||||
*dst = rgbBlend(*dst, src, coverage);
|
||||
} else if (*dst < 0xff000000) {
|
||||
// Give up and do a naive gray alphablend. Needed to deal with ARGB32 and invalid ARGB32_premultiplied, see QTBUG-60571
|
||||
blend_pixel(*dst, src, qRgbAvg(coverage));
|
||||
} else if (!colorProfile) {
|
||||
*dst = rgbBlend(*dst, src, coverage);
|
||||
} else if (srcLinear.isOpaque()) {
|
||||
rgbBlendPixel(dst, coverage, srcLinear, colorProfile);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -375,15 +375,6 @@ void QCocoaScreen::deliverUpdateRequests()
|
|||
// it on the main thread yet, because the processing of the update request is taking
|
||||
// too long, or because the update request was deferred due to window live resizing.
|
||||
qDeferredDebug(screenUpdates) << ", " << framesAheadOfDelivery << " frame(s) ahead";
|
||||
|
||||
// We skip the frame completely if we're live-resizing, to not put any extra
|
||||
// strain on the main thread runloop. Otherwise we assume we should push frames
|
||||
// as fast as possible, and hopefully the callback will be delivered on the
|
||||
// main thread just when the previous finished.
|
||||
if (qt_apple_sharedApplication().keyWindow.inLiveResize) {
|
||||
qDeferredDebug(screenUpdates) << "; waiting for main thread to catch up";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
qDeferredDebug(screenUpdates) << "; signaling dispatch source";
|
||||
|
|
|
|||
|
|
@ -2481,7 +2481,7 @@ void QWidgetTextControl::setExtraSelections(const QList<QTextEdit::ExtraSelectio
|
|||
{
|
||||
Q_D(QWidgetTextControl);
|
||||
|
||||
QHash<int, int> hash;
|
||||
QMultiHash<int, int> hash;
|
||||
for (int i = 0; i < d->extraSelections.count(); ++i) {
|
||||
const QAbstractTextDocumentLayout::Selection &esel = d->extraSelections.at(i);
|
||||
hash.insert(esel.cursor.anchor(), i);
|
||||
|
|
|
|||
|
|
@ -1,2 +1,5 @@
|
|||
HEADERS += $$PWD/qdom.h
|
||||
SOURCES += $$PWD/qdom.cpp
|
||||
HEADERS += $$PWD/qdom.h \
|
||||
$$PWD/qdom_p.h \
|
||||
$$PWD/qdomhelpers_p.h
|
||||
SOURCES += $$PWD/qdom.cpp \
|
||||
$$PWD/qdomhelpers.cpp
|
||||
|
|
|
|||
|
|
@ -39,15 +39,15 @@
|
|||
|
||||
#include <qplatformdefs.h>
|
||||
#include <qdom.h>
|
||||
#include "qdom_p.h"
|
||||
#include "qdomhelpers_p.h"
|
||||
#include "private/qxmlutils_p.h"
|
||||
|
||||
#ifndef QT_NO_DOM
|
||||
|
||||
#include <qatomic.h>
|
||||
#include <qbuffer.h>
|
||||
#include <qhash.h>
|
||||
#include <qiodevice.h>
|
||||
#include <qlist.h>
|
||||
#if QT_CONFIG(regularexpression)
|
||||
#include <qregularexpression.h>
|
||||
#endif
|
||||
|
|
@ -56,9 +56,7 @@
|
|||
#endif
|
||||
#include <qtextstream.h>
|
||||
#include <qxml.h>
|
||||
#include "private/qxml_p.h"
|
||||
#include <qvariant.h>
|
||||
#include <qmap.h>
|
||||
#include <qshareddata.h>
|
||||
#include <qdebug.h>
|
||||
#include <stdio.h>
|
||||
|
|
@ -117,510 +115,6 @@ static void qt_split_namespace(QString& prefix, QString& name, const QString& qN
|
|||
}
|
||||
}
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* Private class declerations
|
||||
*
|
||||
**************************************************************/
|
||||
|
||||
class QDomImplementationPrivate
|
||||
{
|
||||
public:
|
||||
inline QDomImplementationPrivate() {}
|
||||
|
||||
QDomImplementationPrivate* clone();
|
||||
QAtomicInt ref;
|
||||
static QDomImplementation::InvalidDataPolicy invalidDataPolicy;
|
||||
};
|
||||
|
||||
class QDomNodePrivate
|
||||
{
|
||||
public:
|
||||
QDomNodePrivate(QDomDocumentPrivate*, QDomNodePrivate* parent = nullptr);
|
||||
QDomNodePrivate(QDomNodePrivate* n, bool deep);
|
||||
virtual ~QDomNodePrivate();
|
||||
|
||||
QString nodeName() const { return name; }
|
||||
QString nodeValue() const { return value; }
|
||||
virtual void setNodeValue(const QString& v) { value = v; }
|
||||
|
||||
QDomDocumentPrivate* ownerDocument();
|
||||
void setOwnerDocument(QDomDocumentPrivate* doc);
|
||||
|
||||
virtual QDomNodePrivate* insertBefore(QDomNodePrivate* newChild, QDomNodePrivate* refChild);
|
||||
virtual QDomNodePrivate* insertAfter(QDomNodePrivate* newChild, QDomNodePrivate* refChild);
|
||||
virtual QDomNodePrivate* replaceChild(QDomNodePrivate* newChild, QDomNodePrivate* oldChild);
|
||||
virtual QDomNodePrivate* removeChild(QDomNodePrivate* oldChild);
|
||||
virtual QDomNodePrivate* appendChild(QDomNodePrivate* newChild);
|
||||
|
||||
QDomNodePrivate* namedItem(const QString& name);
|
||||
|
||||
virtual QDomNodePrivate* cloneNode(bool deep = true);
|
||||
virtual void normalize();
|
||||
virtual void clear();
|
||||
|
||||
inline QDomNodePrivate* parent() const { return hasParent ? ownerNode : nullptr; }
|
||||
inline void setParent(QDomNodePrivate *p) { ownerNode = p; hasParent = true; }
|
||||
|
||||
void setNoParent() {
|
||||
ownerNode = hasParent ? (QDomNodePrivate*)ownerDocument() : nullptr;
|
||||
hasParent = false;
|
||||
}
|
||||
|
||||
// Dynamic cast
|
||||
bool isAttr() const { return nodeType() == QDomNode::AttributeNode; }
|
||||
bool isCDATASection() const { return nodeType() == QDomNode::CDATASectionNode; }
|
||||
bool isDocumentFragment() const { return nodeType() == QDomNode::DocumentFragmentNode; }
|
||||
bool isDocument() const { return nodeType() == QDomNode::DocumentNode; }
|
||||
bool isDocumentType() const { return nodeType() == QDomNode::DocumentTypeNode; }
|
||||
bool isElement() const { return nodeType() == QDomNode::ElementNode; }
|
||||
bool isEntityReference() const { return nodeType() == QDomNode::EntityReferenceNode; }
|
||||
bool isText() const { const QDomNode::NodeType nt = nodeType();
|
||||
return (nt == QDomNode::TextNode)
|
||||
|| (nt == QDomNode::CDATASectionNode); }
|
||||
bool isEntity() const { return nodeType() == QDomNode::EntityNode; }
|
||||
bool isNotation() const { return nodeType() == QDomNode::NotationNode; }
|
||||
bool isProcessingInstruction() const { return nodeType() == QDomNode::ProcessingInstructionNode; }
|
||||
bool isCharacterData() const { const QDomNode::NodeType nt = nodeType();
|
||||
return (nt == QDomNode::CharacterDataNode)
|
||||
|| (nt == QDomNode::TextNode)
|
||||
|| (nt == QDomNode::CommentNode); }
|
||||
bool isComment() const { return nodeType() == QDomNode::CommentNode; }
|
||||
|
||||
virtual QDomNode::NodeType nodeType() const { return QDomNode::BaseNode; }
|
||||
|
||||
virtual void save(QTextStream&, int, int) const;
|
||||
|
||||
void setLocation(int lineNumber, int columnNumber);
|
||||
|
||||
// Variables
|
||||
QAtomicInt ref;
|
||||
QDomNodePrivate* prev;
|
||||
QDomNodePrivate* next;
|
||||
QDomNodePrivate* ownerNode; // either the node's parent or the node's owner document
|
||||
QDomNodePrivate* first;
|
||||
QDomNodePrivate* last;
|
||||
|
||||
QString name; // this is the local name if prefix != null
|
||||
QString value;
|
||||
QString prefix; // set this only for ElementNode and AttributeNode
|
||||
QString namespaceURI; // set this only for ElementNode and AttributeNode
|
||||
bool createdWithDom1Interface : 1;
|
||||
bool hasParent : 1;
|
||||
|
||||
int lineNumber;
|
||||
int columnNumber;
|
||||
};
|
||||
|
||||
class QDomNodeListPrivate
|
||||
{
|
||||
public:
|
||||
QDomNodeListPrivate(QDomNodePrivate*);
|
||||
QDomNodeListPrivate(QDomNodePrivate*, const QString& );
|
||||
QDomNodeListPrivate(QDomNodePrivate*, const QString&, const QString& );
|
||||
~QDomNodeListPrivate();
|
||||
|
||||
bool operator== (const QDomNodeListPrivate&) const;
|
||||
bool operator!= (const QDomNodeListPrivate&) const;
|
||||
|
||||
void createList();
|
||||
QDomNodePrivate* item(int index);
|
||||
int length() const;
|
||||
|
||||
QAtomicInt ref;
|
||||
/*
|
||||
This list contains the children of this node.
|
||||
*/
|
||||
QDomNodePrivate* node_impl;
|
||||
QString tagname;
|
||||
QString nsURI;
|
||||
QList<QDomNodePrivate*> list;
|
||||
long timestamp;
|
||||
};
|
||||
|
||||
class QDomNamedNodeMapPrivate
|
||||
{
|
||||
public:
|
||||
QDomNamedNodeMapPrivate(QDomNodePrivate*);
|
||||
~QDomNamedNodeMapPrivate();
|
||||
|
||||
QDomNodePrivate* namedItem(const QString& name) const;
|
||||
QDomNodePrivate* namedItemNS(const QString& nsURI, const QString& localName) const;
|
||||
QDomNodePrivate* setNamedItem(QDomNodePrivate* arg);
|
||||
QDomNodePrivate* setNamedItemNS(QDomNodePrivate* arg);
|
||||
QDomNodePrivate* removeNamedItem(const QString& name);
|
||||
QDomNodePrivate* item(int index) const;
|
||||
int length() const;
|
||||
bool contains(const QString& name) const;
|
||||
bool containsNS(const QString& nsURI, const QString & localName) const;
|
||||
|
||||
/**
|
||||
* Remove all children from the map.
|
||||
*/
|
||||
void clearMap();
|
||||
bool isReadOnly() { return readonly; }
|
||||
void setReadOnly(bool r) { readonly = r; }
|
||||
bool isAppendToParent() { return appendToParent; }
|
||||
/**
|
||||
* If true, then the node will redirect insert/remove calls
|
||||
* to its parent by calling QDomNodePrivate::appendChild or removeChild.
|
||||
* In addition the map won't increase or decrease the reference count
|
||||
* of the nodes it contains.
|
||||
*
|
||||
* By default this value is false and the map will handle reference counting
|
||||
* by itself.
|
||||
*/
|
||||
void setAppendToParent(bool b) { appendToParent = b; }
|
||||
|
||||
/**
|
||||
* Creates a copy of the map. It is a deep copy
|
||||
* that means that all children are cloned.
|
||||
*/
|
||||
QDomNamedNodeMapPrivate* clone(QDomNodePrivate* parent);
|
||||
|
||||
// Variables
|
||||
QAtomicInt ref;
|
||||
QHash<QString, QDomNodePrivate *> map;
|
||||
QDomNodePrivate* parent;
|
||||
bool readonly;
|
||||
bool appendToParent;
|
||||
};
|
||||
|
||||
class QDomDocumentTypePrivate : public QDomNodePrivate
|
||||
{
|
||||
public:
|
||||
QDomDocumentTypePrivate(QDomDocumentPrivate*, QDomNodePrivate* parent = nullptr);
|
||||
QDomDocumentTypePrivate(QDomDocumentTypePrivate* n, bool deep);
|
||||
~QDomDocumentTypePrivate();
|
||||
void init();
|
||||
|
||||
// Reimplemented from QDomNodePrivate
|
||||
QDomNodePrivate* cloneNode(bool deep = true) override;
|
||||
QDomNodePrivate* insertBefore(QDomNodePrivate* newChild, QDomNodePrivate* refChild) override;
|
||||
QDomNodePrivate* insertAfter(QDomNodePrivate* newChild, QDomNodePrivate* refChild) override;
|
||||
QDomNodePrivate* replaceChild(QDomNodePrivate* newChild, QDomNodePrivate* oldChild) override;
|
||||
QDomNodePrivate* removeChild(QDomNodePrivate* oldChild) override;
|
||||
QDomNodePrivate* appendChild(QDomNodePrivate* newChild) override;
|
||||
|
||||
QDomNode::NodeType nodeType() const override { return QDomNode::DocumentTypeNode; }
|
||||
|
||||
void save(QTextStream& s, int, int) const override;
|
||||
|
||||
// Variables
|
||||
QDomNamedNodeMapPrivate* entities;
|
||||
QDomNamedNodeMapPrivate* notations;
|
||||
QString publicId;
|
||||
QString systemId;
|
||||
QString internalSubset;
|
||||
};
|
||||
|
||||
class QDomDocumentFragmentPrivate : public QDomNodePrivate
|
||||
{
|
||||
public:
|
||||
QDomDocumentFragmentPrivate(QDomDocumentPrivate*, QDomNodePrivate* parent = nullptr);
|
||||
QDomDocumentFragmentPrivate(QDomNodePrivate* n, bool deep);
|
||||
|
||||
// Reimplemented from QDomNodePrivate
|
||||
virtual QDomNodePrivate* cloneNode(bool deep = true) override;
|
||||
QDomNode::NodeType nodeType() const override { return QDomNode::DocumentFragmentNode; }
|
||||
};
|
||||
|
||||
class QDomCharacterDataPrivate : public QDomNodePrivate
|
||||
{
|
||||
public:
|
||||
QDomCharacterDataPrivate(QDomDocumentPrivate*, QDomNodePrivate* parent, const QString& data);
|
||||
QDomCharacterDataPrivate(QDomCharacterDataPrivate* n, bool deep);
|
||||
|
||||
int dataLength() const;
|
||||
QString substringData(unsigned long offset, unsigned long count) const;
|
||||
void appendData(const QString& arg);
|
||||
void insertData(unsigned long offset, const QString& arg);
|
||||
void deleteData(unsigned long offset, unsigned long count);
|
||||
void replaceData(unsigned long offset, unsigned long count, const QString& arg);
|
||||
|
||||
// Reimplemented from QDomNodePrivate
|
||||
QDomNode::NodeType nodeType() const override { return QDomNode::CharacterDataNode; }
|
||||
QDomNodePrivate* cloneNode(bool deep = true) override;
|
||||
};
|
||||
|
||||
class QDomTextPrivate : public QDomCharacterDataPrivate
|
||||
{
|
||||
public:
|
||||
QDomTextPrivate(QDomDocumentPrivate*, QDomNodePrivate* parent, const QString& val);
|
||||
QDomTextPrivate(QDomTextPrivate* n, bool deep);
|
||||
|
||||
QDomTextPrivate* splitText(int offset);
|
||||
|
||||
// Reimplemented from QDomNodePrivate
|
||||
QDomNodePrivate* cloneNode(bool deep = true) override;
|
||||
QDomNode::NodeType nodeType() const override { return QDomNode::TextNode; }
|
||||
virtual void save(QTextStream& s, int, int) const override;
|
||||
};
|
||||
|
||||
class QDomAttrPrivate : public QDomNodePrivate
|
||||
{
|
||||
public:
|
||||
QDomAttrPrivate(QDomDocumentPrivate*, QDomNodePrivate*, const QString& name);
|
||||
QDomAttrPrivate(QDomDocumentPrivate*, QDomNodePrivate*, const QString& nsURI, const QString& qName);
|
||||
QDomAttrPrivate(QDomAttrPrivate* n, bool deep);
|
||||
|
||||
bool specified() const;
|
||||
|
||||
// Reimplemented from QDomNodePrivate
|
||||
void setNodeValue(const QString& v) override;
|
||||
QDomNodePrivate* cloneNode(bool deep = true) override;
|
||||
QDomNode::NodeType nodeType() const override { return QDomNode::AttributeNode; }
|
||||
virtual void save(QTextStream& s, int, int) const override;
|
||||
|
||||
// Variables
|
||||
bool m_specified;
|
||||
};
|
||||
|
||||
class QDomElementPrivate : public QDomNodePrivate
|
||||
{
|
||||
public:
|
||||
QDomElementPrivate(QDomDocumentPrivate*, QDomNodePrivate* parent, const QString& name);
|
||||
QDomElementPrivate(QDomDocumentPrivate*, QDomNodePrivate* parent, const QString& nsURI, const QString& qName);
|
||||
QDomElementPrivate(QDomElementPrivate* n, bool deep);
|
||||
~QDomElementPrivate();
|
||||
|
||||
QString attribute(const QString& name, const QString& defValue) const;
|
||||
QString attributeNS(const QString& nsURI, const QString& localName, const QString& defValue) const;
|
||||
void setAttribute(const QString& name, const QString& value);
|
||||
void setAttributeNS(const QString& nsURI, const QString& qName, const QString& newValue);
|
||||
void removeAttribute(const QString& name);
|
||||
QDomAttrPrivate* attributeNode(const QString& name);
|
||||
QDomAttrPrivate* attributeNodeNS(const QString& nsURI, const QString& localName);
|
||||
QDomAttrPrivate* setAttributeNode(QDomAttrPrivate* newAttr);
|
||||
QDomAttrPrivate* setAttributeNodeNS(QDomAttrPrivate* newAttr);
|
||||
QDomAttrPrivate* removeAttributeNode(QDomAttrPrivate* oldAttr);
|
||||
bool hasAttribute(const QString& name);
|
||||
bool hasAttributeNS(const QString& nsURI, const QString& localName);
|
||||
|
||||
QString text();
|
||||
|
||||
// Reimplemented from QDomNodePrivate
|
||||
QDomNamedNodeMapPrivate* attributes() { return m_attr; }
|
||||
bool hasAttributes() { return (m_attr->length() > 0); }
|
||||
QDomNode::NodeType nodeType() const override { return QDomNode::ElementNode; }
|
||||
QDomNodePrivate* cloneNode(bool deep = true) override;
|
||||
virtual void save(QTextStream& s, int, int) const override;
|
||||
|
||||
// Variables
|
||||
QDomNamedNodeMapPrivate* m_attr;
|
||||
};
|
||||
|
||||
|
||||
class QDomCommentPrivate : public QDomCharacterDataPrivate
|
||||
{
|
||||
public:
|
||||
QDomCommentPrivate(QDomDocumentPrivate*, QDomNodePrivate* parent, const QString& val);
|
||||
QDomCommentPrivate(QDomCommentPrivate* n, bool deep);
|
||||
|
||||
// Reimplemented from QDomNodePrivate
|
||||
QDomNodePrivate* cloneNode(bool deep = true) override;
|
||||
QDomNode::NodeType nodeType() const override { return QDomNode::CommentNode; }
|
||||
virtual void save(QTextStream& s, int, int) const override;
|
||||
};
|
||||
|
||||
class QDomCDATASectionPrivate : public QDomTextPrivate
|
||||
{
|
||||
public:
|
||||
QDomCDATASectionPrivate(QDomDocumentPrivate*, QDomNodePrivate* parent, const QString& val);
|
||||
QDomCDATASectionPrivate(QDomCDATASectionPrivate* n, bool deep);
|
||||
|
||||
// Reimplemented from QDomNodePrivate
|
||||
QDomNodePrivate* cloneNode(bool deep = true) override;
|
||||
QDomNode::NodeType nodeType() const override { return QDomNode::CDATASectionNode; }
|
||||
virtual void save(QTextStream& s, int, int) const override;
|
||||
};
|
||||
|
||||
class QDomNotationPrivate : public QDomNodePrivate
|
||||
{
|
||||
public:
|
||||
QDomNotationPrivate(QDomDocumentPrivate*, QDomNodePrivate* parent, const QString& name,
|
||||
const QString& pub, const QString& sys);
|
||||
QDomNotationPrivate(QDomNotationPrivate* n, bool deep);
|
||||
|
||||
// Reimplemented from QDomNodePrivate
|
||||
QDomNodePrivate* cloneNode(bool deep = true) override;
|
||||
QDomNode::NodeType nodeType() const override { return QDomNode::NotationNode; }
|
||||
virtual void save(QTextStream& s, int, int) const override;
|
||||
|
||||
// Variables
|
||||
QString m_sys;
|
||||
QString m_pub;
|
||||
};
|
||||
|
||||
class QDomEntityPrivate : public QDomNodePrivate
|
||||
{
|
||||
public:
|
||||
QDomEntityPrivate(QDomDocumentPrivate*, QDomNodePrivate* parent, const QString& name,
|
||||
const QString& pub, const QString& sys, const QString& notation);
|
||||
QDomEntityPrivate(QDomEntityPrivate* n, bool deep);
|
||||
|
||||
// Reimplemented from QDomNodePrivate
|
||||
QDomNodePrivate* cloneNode(bool deep = true) override;
|
||||
QDomNode::NodeType nodeType() const override { return QDomNode::EntityNode; }
|
||||
virtual void save(QTextStream& s, int, int) const override;
|
||||
|
||||
// Variables
|
||||
QString m_sys;
|
||||
QString m_pub;
|
||||
QString m_notationName;
|
||||
};
|
||||
|
||||
class QDomEntityReferencePrivate : public QDomNodePrivate
|
||||
{
|
||||
public:
|
||||
QDomEntityReferencePrivate(QDomDocumentPrivate*, QDomNodePrivate* parent, const QString& name);
|
||||
QDomEntityReferencePrivate(QDomNodePrivate* n, bool deep);
|
||||
|
||||
// Reimplemented from QDomNodePrivate
|
||||
QDomNodePrivate* cloneNode(bool deep = true) override;
|
||||
QDomNode::NodeType nodeType() const override { return QDomNode::EntityReferenceNode; }
|
||||
virtual void save(QTextStream& s, int, int) const override;
|
||||
};
|
||||
|
||||
class QDomProcessingInstructionPrivate : public QDomNodePrivate
|
||||
{
|
||||
public:
|
||||
QDomProcessingInstructionPrivate(QDomDocumentPrivate*, QDomNodePrivate* parent, const QString& target,
|
||||
const QString& data);
|
||||
QDomProcessingInstructionPrivate(QDomProcessingInstructionPrivate* n, bool deep);
|
||||
|
||||
// Reimplemented from QDomNodePrivate
|
||||
QDomNodePrivate* cloneNode(bool deep = true) override;
|
||||
QDomNode::NodeType nodeType() const override { return QDomNode::ProcessingInstructionNode; }
|
||||
virtual void save(QTextStream& s, int, int) const override;
|
||||
};
|
||||
|
||||
class QDomDocumentPrivate : public QDomNodePrivate
|
||||
{
|
||||
public:
|
||||
QDomDocumentPrivate();
|
||||
QDomDocumentPrivate(const QString& name);
|
||||
QDomDocumentPrivate(QDomDocumentTypePrivate* dt);
|
||||
QDomDocumentPrivate(QDomDocumentPrivate* n, bool deep);
|
||||
~QDomDocumentPrivate();
|
||||
|
||||
bool setContent(QXmlInputSource *source, bool namespaceProcessing, QString *errorMsg, int *errorLine, int *errorColumn);
|
||||
bool setContent(QXmlInputSource *source, QXmlReader *reader, QXmlSimpleReader *simpleReader, QString *errorMsg, int *errorLine, int *errorColumn);
|
||||
|
||||
// Attributes
|
||||
QDomDocumentTypePrivate* doctype() { return type.data(); }
|
||||
QDomImplementationPrivate* implementation() { return impl.data(); }
|
||||
QDomElementPrivate* documentElement();
|
||||
|
||||
// Factories
|
||||
QDomElementPrivate* createElement(const QString& tagName);
|
||||
QDomElementPrivate* createElementNS(const QString& nsURI, const QString& qName);
|
||||
QDomDocumentFragmentPrivate* createDocumentFragment();
|
||||
QDomTextPrivate* createTextNode(const QString& data);
|
||||
QDomCommentPrivate* createComment(const QString& data);
|
||||
QDomCDATASectionPrivate* createCDATASection(const QString& data);
|
||||
QDomProcessingInstructionPrivate* createProcessingInstruction(const QString& target, const QString& data);
|
||||
QDomAttrPrivate* createAttribute(const QString& name);
|
||||
QDomAttrPrivate* createAttributeNS(const QString& nsURI, const QString& qName);
|
||||
QDomEntityReferencePrivate* createEntityReference(const QString& name);
|
||||
|
||||
QDomNodePrivate* importNode(QDomNodePrivate* importedNode, bool deep);
|
||||
|
||||
// Reimplemented from QDomNodePrivate
|
||||
QDomNodePrivate* cloneNode(bool deep = true) override;
|
||||
QDomNode::NodeType nodeType() const override { return QDomNode::DocumentNode; }
|
||||
void clear() override;
|
||||
|
||||
// Variables
|
||||
QExplicitlySharedDataPointer<QDomImplementationPrivate> impl;
|
||||
QExplicitlySharedDataPointer<QDomDocumentTypePrivate> type;
|
||||
|
||||
void saveDocument(QTextStream& stream, const int indent, QDomNode::EncodingPolicy encUsed) const;
|
||||
|
||||
/* \internal
|
||||
Counter for the QDomNodeListPrivate timestamps.
|
||||
|
||||
This is a cache optimization, that might in some cases be effective. The
|
||||
dilemma is that QDomNode::childNodes() returns a list, but the
|
||||
implementation stores the children in a linked list. Hence, in order to
|
||||
get the children out through childNodes(), a list must be populated each
|
||||
time, which is O(N).
|
||||
|
||||
DOM has the requirement of node references being live, see DOM Core
|
||||
Level 3, 1.1.1 The DOM Structure Model, which means that changes to the
|
||||
underlying documents must be reflected in node lists.
|
||||
|
||||
This mechanism, nodeListTime, is a caching optimization that reduces the
|
||||
amount of times the node list is rebuilt, by only doing so when the
|
||||
document actually changes. However, a change to anywhere in any document
|
||||
invalidate all lists, since no dependency tracking is done.
|
||||
|
||||
It functions by that all modifying functions(insertBefore() and so on)
|
||||
increment the count; each QDomNodeListPrivate copies nodeListTime on
|
||||
construction, and compares its own value to nodeListTime in order to
|
||||
determine whether it needs to rebuild.
|
||||
|
||||
This is reentrant. The nodeListTime may overflow, but that's ok since we
|
||||
check for equalness, not whether nodeListTime is smaller than the list's
|
||||
stored timestamp.
|
||||
*/
|
||||
long nodeListTime;
|
||||
};
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* QDomHandler
|
||||
*
|
||||
**************************************************************/
|
||||
|
||||
class QDomHandler : public QXmlDefaultHandler
|
||||
{
|
||||
public:
|
||||
QDomHandler(QDomDocumentPrivate* d, QXmlSimpleReader *reader, bool namespaceProcessing);
|
||||
~QDomHandler();
|
||||
|
||||
// content handler
|
||||
bool endDocument() override;
|
||||
bool startElement(const QString& nsURI, const QString& localName, const QString& qName, const QXmlAttributes& atts) override;
|
||||
bool endElement(const QString& nsURI, const QString& localName, const QString& qName) override;
|
||||
bool characters(const QString& ch) override;
|
||||
bool processingInstruction(const QString& target, const QString& data) override;
|
||||
bool skippedEntity(const QString& name) override;
|
||||
|
||||
// error handler
|
||||
bool fatalError(const QXmlParseException& exception) override;
|
||||
|
||||
// lexical handler
|
||||
bool startCDATA() override;
|
||||
bool endCDATA() override;
|
||||
bool startEntity(const QString &) override;
|
||||
bool endEntity(const QString &) override;
|
||||
bool startDTD(const QString& name, const QString& publicId, const QString& systemId) override;
|
||||
bool comment(const QString& ch) override;
|
||||
|
||||
// decl handler
|
||||
bool externalEntityDecl(const QString &name, const QString &publicId, const QString &systemId) override ;
|
||||
|
||||
// DTD handler
|
||||
bool notationDecl(const QString & name, const QString & publicId, const QString & systemId) override;
|
||||
bool unparsedEntityDecl(const QString &name, const QString &publicId, const QString &systemId, const QString ¬ationName) override ;
|
||||
|
||||
void setDocumentLocator(QXmlLocator *locator) override;
|
||||
|
||||
QString errorMsg;
|
||||
int errorLine;
|
||||
int errorColumn;
|
||||
|
||||
private:
|
||||
QDomDocumentPrivate *doc;
|
||||
QDomNodePrivate *node;
|
||||
QString entityName;
|
||||
bool cdata;
|
||||
bool nsProcessing;
|
||||
QXmlLocator *locator;
|
||||
QXmlSimpleReader *reader;
|
||||
};
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* Functions for verifying legal data
|
||||
|
|
@ -7361,200 +6855,6 @@ QDomComment QDomNode::toComment() const
|
|||
return QDomComment();
|
||||
}
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* QDomHandler
|
||||
*
|
||||
**************************************************************/
|
||||
|
||||
QDomHandler::QDomHandler(QDomDocumentPrivate* adoc, QXmlSimpleReader* areader, bool namespaceProcessing)
|
||||
: errorLine(0), errorColumn(0), doc(adoc), node(adoc), cdata(false),
|
||||
nsProcessing(namespaceProcessing), locator(nullptr), reader(areader)
|
||||
{
|
||||
}
|
||||
|
||||
QDomHandler::~QDomHandler()
|
||||
{
|
||||
}
|
||||
|
||||
bool QDomHandler::endDocument()
|
||||
{
|
||||
// ### is this really necessary? (rms)
|
||||
if (node != doc)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QDomHandler::startDTD(const QString& name, const QString& publicId, const QString& systemId)
|
||||
{
|
||||
doc->doctype()->name = name;
|
||||
doc->doctype()->publicId = publicId;
|
||||
doc->doctype()->systemId = systemId;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QDomHandler::startElement(const QString& nsURI, const QString&, const QString& qName, const QXmlAttributes& atts)
|
||||
{
|
||||
// tag name
|
||||
QDomNodePrivate* n;
|
||||
if (nsProcessing) {
|
||||
n = doc->createElementNS(nsURI, qName);
|
||||
} else {
|
||||
n = doc->createElement(qName);
|
||||
}
|
||||
|
||||
if (!n)
|
||||
return false;
|
||||
|
||||
n->setLocation(locator->lineNumber(), locator->columnNumber());
|
||||
|
||||
node->appendChild(n);
|
||||
node = n;
|
||||
|
||||
// attributes
|
||||
for (int i=0; i<atts.length(); i++)
|
||||
{
|
||||
if (nsProcessing) {
|
||||
((QDomElementPrivate*)node)->setAttributeNS(atts.uri(i), atts.qName(i), atts.value(i));
|
||||
} else {
|
||||
((QDomElementPrivate*)node)->setAttribute(atts.qName(i), atts.value(i));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QDomHandler::endElement(const QString&, const QString&, const QString&)
|
||||
{
|
||||
if (!node || node == doc)
|
||||
return false;
|
||||
node = node->parent();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QDomHandler::characters(const QString& ch)
|
||||
{
|
||||
// No text as child of some document
|
||||
if (node == doc)
|
||||
return false;
|
||||
|
||||
QScopedPointer<QDomNodePrivate> n;
|
||||
if (cdata) {
|
||||
n.reset(doc->createCDATASection(ch));
|
||||
} else if (!entityName.isEmpty()) {
|
||||
QScopedPointer<QDomEntityPrivate> e(new QDomEntityPrivate(doc, nullptr, entityName,
|
||||
QString(), QString(), QString()));
|
||||
e->value = ch;
|
||||
e->ref.deref();
|
||||
doc->doctype()->appendChild(e.data());
|
||||
e.take();
|
||||
n.reset(doc->createEntityReference(entityName));
|
||||
} else {
|
||||
n.reset(doc->createTextNode(ch));
|
||||
}
|
||||
n->setLocation(locator->lineNumber(), locator->columnNumber());
|
||||
node->appendChild(n.data());
|
||||
n.take();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QDomHandler::processingInstruction(const QString& target, const QString& data)
|
||||
{
|
||||
QDomNodePrivate *n;
|
||||
n = doc->createProcessingInstruction(target, data);
|
||||
if (n) {
|
||||
n->setLocation(locator->lineNumber(), locator->columnNumber());
|
||||
node->appendChild(n);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QDomHandler::skippedEntity(const QString& name)
|
||||
{
|
||||
// we can only handle inserting entity references into content
|
||||
if (reader && !reader->d_ptr->skipped_entity_in_content)
|
||||
return true;
|
||||
|
||||
QDomNodePrivate *n = doc->createEntityReference(name);
|
||||
n->setLocation(locator->lineNumber(), locator->columnNumber());
|
||||
node->appendChild(n);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QDomHandler::fatalError(const QXmlParseException& exception)
|
||||
{
|
||||
errorMsg = exception.message();
|
||||
errorLine = exception.lineNumber();
|
||||
errorColumn = exception.columnNumber();
|
||||
return QXmlDefaultHandler::fatalError(exception);
|
||||
}
|
||||
|
||||
bool QDomHandler::startCDATA()
|
||||
{
|
||||
cdata = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QDomHandler::endCDATA()
|
||||
{
|
||||
cdata = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QDomHandler::startEntity(const QString &name)
|
||||
{
|
||||
entityName = name;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QDomHandler::endEntity(const QString &)
|
||||
{
|
||||
entityName.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QDomHandler::comment(const QString& ch)
|
||||
{
|
||||
QDomNodePrivate *n;
|
||||
n = doc->createComment(ch);
|
||||
n->setLocation(locator->lineNumber(), locator->columnNumber());
|
||||
node->appendChild(n);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QDomHandler::unparsedEntityDecl(const QString &name, const QString &publicId, const QString &systemId, const QString ¬ationName)
|
||||
{
|
||||
QDomEntityPrivate* e = new QDomEntityPrivate(doc, nullptr, name,
|
||||
publicId, systemId, notationName);
|
||||
// keep the refcount balanced: appendChild() does a ref anyway.
|
||||
e->ref.deref();
|
||||
doc->doctype()->appendChild(e);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QDomHandler::externalEntityDecl(const QString &name, const QString &publicId, const QString &systemId)
|
||||
{
|
||||
return unparsedEntityDecl(name, publicId, systemId, QString());
|
||||
}
|
||||
|
||||
bool QDomHandler::notationDecl(const QString & name, const QString & publicId, const QString & systemId)
|
||||
{
|
||||
QDomNotationPrivate* n = new QDomNotationPrivate(doc, nullptr, name, publicId, systemId);
|
||||
// keep the refcount balanced: appendChild() does a ref anyway.
|
||||
n->ref.deref();
|
||||
doc->doctype()->appendChild(n);
|
||||
return true;
|
||||
}
|
||||
|
||||
void QDomHandler::setDocumentLocator(QXmlLocator *locator)
|
||||
{
|
||||
this->locator = locator;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QT_NO_DOM
|
||||
|
|
|
|||
|
|
@ -0,0 +1,533 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2019 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtXml 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$
|
||||
**
|
||||
****************************************************************************/
|
||||
#ifndef QDOM_P_H
|
||||
#define QDOM_P_H
|
||||
|
||||
#include "qdom.h"
|
||||
|
||||
#include <qglobal.h>
|
||||
#include <qhash.h>
|
||||
#include <qstring.h>
|
||||
#include <qlist.h>
|
||||
#include <qxml.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists for the convenience of
|
||||
// qxml.cpp and qdom.cpp. This header file may change from version to version without
|
||||
// notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* Private class declerations
|
||||
*
|
||||
**************************************************************/
|
||||
|
||||
class QDomImplementationPrivate
|
||||
{
|
||||
public:
|
||||
inline QDomImplementationPrivate() {}
|
||||
|
||||
QDomImplementationPrivate *clone();
|
||||
QAtomicInt ref;
|
||||
static QDomImplementation::InvalidDataPolicy invalidDataPolicy;
|
||||
};
|
||||
|
||||
class QDomNodePrivate
|
||||
{
|
||||
public:
|
||||
QDomNodePrivate(QDomDocumentPrivate *, QDomNodePrivate *parent = nullptr);
|
||||
QDomNodePrivate(QDomNodePrivate *n, bool deep);
|
||||
virtual ~QDomNodePrivate();
|
||||
|
||||
QString nodeName() const { return name; }
|
||||
QString nodeValue() const { return value; }
|
||||
virtual void setNodeValue(const QString &v) { value = v; }
|
||||
|
||||
QDomDocumentPrivate *ownerDocument();
|
||||
void setOwnerDocument(QDomDocumentPrivate *doc);
|
||||
|
||||
virtual QDomNodePrivate *insertBefore(QDomNodePrivate *newChild, QDomNodePrivate *refChild);
|
||||
virtual QDomNodePrivate *insertAfter(QDomNodePrivate *newChild, QDomNodePrivate *refChild);
|
||||
virtual QDomNodePrivate *replaceChild(QDomNodePrivate *newChild, QDomNodePrivate *oldChild);
|
||||
virtual QDomNodePrivate *removeChild(QDomNodePrivate *oldChild);
|
||||
virtual QDomNodePrivate *appendChild(QDomNodePrivate *newChild);
|
||||
|
||||
QDomNodePrivate *namedItem(const QString &name);
|
||||
|
||||
virtual QDomNodePrivate *cloneNode(bool deep = true);
|
||||
virtual void normalize();
|
||||
virtual void clear();
|
||||
|
||||
inline QDomNodePrivate *parent() const { return hasParent ? ownerNode : nullptr; }
|
||||
inline void setParent(QDomNodePrivate *p)
|
||||
{
|
||||
ownerNode = p;
|
||||
hasParent = true;
|
||||
}
|
||||
|
||||
void setNoParent()
|
||||
{
|
||||
ownerNode = hasParent ? (QDomNodePrivate *)ownerDocument() : nullptr;
|
||||
hasParent = false;
|
||||
}
|
||||
|
||||
// Dynamic cast
|
||||
bool isAttr() const { return nodeType() == QDomNode::AttributeNode; }
|
||||
bool isCDATASection() const { return nodeType() == QDomNode::CDATASectionNode; }
|
||||
bool isDocumentFragment() const { return nodeType() == QDomNode::DocumentFragmentNode; }
|
||||
bool isDocument() const { return nodeType() == QDomNode::DocumentNode; }
|
||||
bool isDocumentType() const { return nodeType() == QDomNode::DocumentTypeNode; }
|
||||
bool isElement() const { return nodeType() == QDomNode::ElementNode; }
|
||||
bool isEntityReference() const { return nodeType() == QDomNode::EntityReferenceNode; }
|
||||
bool isText() const
|
||||
{
|
||||
const QDomNode::NodeType nt = nodeType();
|
||||
return (nt == QDomNode::TextNode) || (nt == QDomNode::CDATASectionNode);
|
||||
}
|
||||
bool isEntity() const { return nodeType() == QDomNode::EntityNode; }
|
||||
bool isNotation() const { return nodeType() == QDomNode::NotationNode; }
|
||||
bool isProcessingInstruction() const
|
||||
{
|
||||
return nodeType() == QDomNode::ProcessingInstructionNode;
|
||||
}
|
||||
bool isCharacterData() const
|
||||
{
|
||||
const QDomNode::NodeType nt = nodeType();
|
||||
return (nt == QDomNode::CharacterDataNode) || (nt == QDomNode::TextNode)
|
||||
|| (nt == QDomNode::CommentNode);
|
||||
}
|
||||
bool isComment() const { return nodeType() == QDomNode::CommentNode; }
|
||||
|
||||
virtual QDomNode::NodeType nodeType() const { return QDomNode::BaseNode; }
|
||||
|
||||
virtual void save(QTextStream &, int, int) const;
|
||||
|
||||
void setLocation(int lineNumber, int columnNumber);
|
||||
|
||||
// Variables
|
||||
QAtomicInt ref;
|
||||
QDomNodePrivate *prev;
|
||||
QDomNodePrivate *next;
|
||||
QDomNodePrivate *ownerNode; // either the node's parent or the node's owner document
|
||||
QDomNodePrivate *first;
|
||||
QDomNodePrivate *last;
|
||||
|
||||
QString name; // this is the local name if prefix != null
|
||||
QString value;
|
||||
QString prefix; // set this only for ElementNode and AttributeNode
|
||||
QString namespaceURI; // set this only for ElementNode and AttributeNode
|
||||
bool createdWithDom1Interface : 1;
|
||||
bool hasParent : 1;
|
||||
|
||||
int lineNumber;
|
||||
int columnNumber;
|
||||
};
|
||||
|
||||
class QDomNodeListPrivate
|
||||
{
|
||||
public:
|
||||
QDomNodeListPrivate(QDomNodePrivate *);
|
||||
QDomNodeListPrivate(QDomNodePrivate *, const QString &);
|
||||
QDomNodeListPrivate(QDomNodePrivate *, const QString &, const QString &);
|
||||
~QDomNodeListPrivate();
|
||||
|
||||
bool operator==(const QDomNodeListPrivate &) const;
|
||||
bool operator!=(const QDomNodeListPrivate &) const;
|
||||
|
||||
void createList();
|
||||
QDomNodePrivate *item(int index);
|
||||
int length() const;
|
||||
|
||||
QAtomicInt ref;
|
||||
/*
|
||||
This list contains the children of this node.
|
||||
*/
|
||||
QDomNodePrivate *node_impl;
|
||||
QString tagname;
|
||||
QString nsURI;
|
||||
QList<QDomNodePrivate *> list;
|
||||
long timestamp;
|
||||
};
|
||||
|
||||
class QDomNamedNodeMapPrivate
|
||||
{
|
||||
public:
|
||||
QDomNamedNodeMapPrivate(QDomNodePrivate *);
|
||||
~QDomNamedNodeMapPrivate();
|
||||
|
||||
QDomNodePrivate *namedItem(const QString &name) const;
|
||||
QDomNodePrivate *namedItemNS(const QString &nsURI, const QString &localName) const;
|
||||
QDomNodePrivate *setNamedItem(QDomNodePrivate *arg);
|
||||
QDomNodePrivate *setNamedItemNS(QDomNodePrivate *arg);
|
||||
QDomNodePrivate *removeNamedItem(const QString &name);
|
||||
QDomNodePrivate *item(int index) const;
|
||||
int length() const;
|
||||
bool contains(const QString &name) const;
|
||||
bool containsNS(const QString &nsURI, const QString &localName) const;
|
||||
|
||||
/**
|
||||
* Remove all children from the map.
|
||||
*/
|
||||
void clearMap();
|
||||
bool isReadOnly() { return readonly; }
|
||||
void setReadOnly(bool r) { readonly = r; }
|
||||
bool isAppendToParent() { return appendToParent; }
|
||||
/**
|
||||
* If true, then the node will redirect insert/remove calls
|
||||
* to its parent by calling QDomNodePrivate::appendChild or removeChild.
|
||||
* In addition the map won't increase or decrease the reference count
|
||||
* of the nodes it contains.
|
||||
*
|
||||
* By default this value is false and the map will handle reference counting
|
||||
* by itself.
|
||||
*/
|
||||
void setAppendToParent(bool b) { appendToParent = b; }
|
||||
|
||||
/**
|
||||
* Creates a copy of the map. It is a deep copy
|
||||
* that means that all children are cloned.
|
||||
*/
|
||||
QDomNamedNodeMapPrivate *clone(QDomNodePrivate *parent);
|
||||
|
||||
// Variables
|
||||
QAtomicInt ref;
|
||||
QHash<QString, QDomNodePrivate *> map;
|
||||
QDomNodePrivate *parent;
|
||||
bool readonly;
|
||||
bool appendToParent;
|
||||
};
|
||||
|
||||
class QDomDocumentTypePrivate : public QDomNodePrivate
|
||||
{
|
||||
public:
|
||||
QDomDocumentTypePrivate(QDomDocumentPrivate *, QDomNodePrivate *parent = nullptr);
|
||||
QDomDocumentTypePrivate(QDomDocumentTypePrivate *n, bool deep);
|
||||
~QDomDocumentTypePrivate();
|
||||
void init();
|
||||
|
||||
// Reimplemented from QDomNodePrivate
|
||||
QDomNodePrivate *cloneNode(bool deep = true) override;
|
||||
QDomNodePrivate *insertBefore(QDomNodePrivate *newChild, QDomNodePrivate *refChild) override;
|
||||
QDomNodePrivate *insertAfter(QDomNodePrivate *newChild, QDomNodePrivate *refChild) override;
|
||||
QDomNodePrivate *replaceChild(QDomNodePrivate *newChild, QDomNodePrivate *oldChild) override;
|
||||
QDomNodePrivate *removeChild(QDomNodePrivate *oldChild) override;
|
||||
QDomNodePrivate *appendChild(QDomNodePrivate *newChild) override;
|
||||
|
||||
QDomNode::NodeType nodeType() const override { return QDomNode::DocumentTypeNode; }
|
||||
|
||||
void save(QTextStream &s, int, int) const override;
|
||||
|
||||
// Variables
|
||||
QDomNamedNodeMapPrivate *entities;
|
||||
QDomNamedNodeMapPrivate *notations;
|
||||
QString publicId;
|
||||
QString systemId;
|
||||
QString internalSubset;
|
||||
};
|
||||
|
||||
class QDomDocumentFragmentPrivate : public QDomNodePrivate
|
||||
{
|
||||
public:
|
||||
QDomDocumentFragmentPrivate(QDomDocumentPrivate *, QDomNodePrivate *parent = nullptr);
|
||||
QDomDocumentFragmentPrivate(QDomNodePrivate *n, bool deep);
|
||||
|
||||
// Reimplemented from QDomNodePrivate
|
||||
virtual QDomNodePrivate *cloneNode(bool deep = true) override;
|
||||
QDomNode::NodeType nodeType() const override { return QDomNode::DocumentFragmentNode; }
|
||||
};
|
||||
|
||||
class QDomCharacterDataPrivate : public QDomNodePrivate
|
||||
{
|
||||
public:
|
||||
QDomCharacterDataPrivate(QDomDocumentPrivate *, QDomNodePrivate *parent, const QString &data);
|
||||
QDomCharacterDataPrivate(QDomCharacterDataPrivate *n, bool deep);
|
||||
|
||||
int dataLength() const;
|
||||
QString substringData(unsigned long offset, unsigned long count) const;
|
||||
void appendData(const QString &arg);
|
||||
void insertData(unsigned long offset, const QString &arg);
|
||||
void deleteData(unsigned long offset, unsigned long count);
|
||||
void replaceData(unsigned long offset, unsigned long count, const QString &arg);
|
||||
|
||||
// Reimplemented from QDomNodePrivate
|
||||
QDomNode::NodeType nodeType() const override { return QDomNode::CharacterDataNode; }
|
||||
QDomNodePrivate *cloneNode(bool deep = true) override;
|
||||
};
|
||||
|
||||
class QDomTextPrivate : public QDomCharacterDataPrivate
|
||||
{
|
||||
public:
|
||||
QDomTextPrivate(QDomDocumentPrivate *, QDomNodePrivate *parent, const QString &val);
|
||||
QDomTextPrivate(QDomTextPrivate *n, bool deep);
|
||||
|
||||
QDomTextPrivate *splitText(int offset);
|
||||
|
||||
// Reimplemented from QDomNodePrivate
|
||||
QDomNodePrivate *cloneNode(bool deep = true) override;
|
||||
QDomNode::NodeType nodeType() const override { return QDomNode::TextNode; }
|
||||
virtual void save(QTextStream &s, int, int) const override;
|
||||
};
|
||||
|
||||
class QDomAttrPrivate : public QDomNodePrivate
|
||||
{
|
||||
public:
|
||||
QDomAttrPrivate(QDomDocumentPrivate *, QDomNodePrivate *, const QString &name);
|
||||
QDomAttrPrivate(QDomDocumentPrivate *, QDomNodePrivate *, const QString &nsURI,
|
||||
const QString &qName);
|
||||
QDomAttrPrivate(QDomAttrPrivate *n, bool deep);
|
||||
|
||||
bool specified() const;
|
||||
|
||||
// Reimplemented from QDomNodePrivate
|
||||
void setNodeValue(const QString &v) override;
|
||||
QDomNodePrivate *cloneNode(bool deep = true) override;
|
||||
QDomNode::NodeType nodeType() const override { return QDomNode::AttributeNode; }
|
||||
virtual void save(QTextStream &s, int, int) const override;
|
||||
|
||||
// Variables
|
||||
bool m_specified;
|
||||
};
|
||||
|
||||
class QDomElementPrivate : public QDomNodePrivate
|
||||
{
|
||||
public:
|
||||
QDomElementPrivate(QDomDocumentPrivate *, QDomNodePrivate *parent, const QString &name);
|
||||
QDomElementPrivate(QDomDocumentPrivate *, QDomNodePrivate *parent, const QString &nsURI,
|
||||
const QString &qName);
|
||||
QDomElementPrivate(QDomElementPrivate *n, bool deep);
|
||||
~QDomElementPrivate();
|
||||
|
||||
QString attribute(const QString &name, const QString &defValue) const;
|
||||
QString attributeNS(const QString &nsURI, const QString &localName,
|
||||
const QString &defValue) const;
|
||||
void setAttribute(const QString &name, const QString &value);
|
||||
void setAttributeNS(const QString &nsURI, const QString &qName, const QString &newValue);
|
||||
void removeAttribute(const QString &name);
|
||||
QDomAttrPrivate *attributeNode(const QString &name);
|
||||
QDomAttrPrivate *attributeNodeNS(const QString &nsURI, const QString &localName);
|
||||
QDomAttrPrivate *setAttributeNode(QDomAttrPrivate *newAttr);
|
||||
QDomAttrPrivate *setAttributeNodeNS(QDomAttrPrivate *newAttr);
|
||||
QDomAttrPrivate *removeAttributeNode(QDomAttrPrivate *oldAttr);
|
||||
bool hasAttribute(const QString &name);
|
||||
bool hasAttributeNS(const QString &nsURI, const QString &localName);
|
||||
|
||||
QString text();
|
||||
|
||||
// Reimplemented from QDomNodePrivate
|
||||
QDomNamedNodeMapPrivate *attributes() { return m_attr; }
|
||||
bool hasAttributes() { return (m_attr->length() > 0); }
|
||||
QDomNode::NodeType nodeType() const override { return QDomNode::ElementNode; }
|
||||
QDomNodePrivate *cloneNode(bool deep = true) override;
|
||||
virtual void save(QTextStream &s, int, int) const override;
|
||||
|
||||
// Variables
|
||||
QDomNamedNodeMapPrivate *m_attr;
|
||||
};
|
||||
|
||||
class QDomCommentPrivate : public QDomCharacterDataPrivate
|
||||
{
|
||||
public:
|
||||
QDomCommentPrivate(QDomDocumentPrivate *, QDomNodePrivate *parent, const QString &val);
|
||||
QDomCommentPrivate(QDomCommentPrivate *n, bool deep);
|
||||
|
||||
// Reimplemented from QDomNodePrivate
|
||||
QDomNodePrivate *cloneNode(bool deep = true) override;
|
||||
QDomNode::NodeType nodeType() const override { return QDomNode::CommentNode; }
|
||||
virtual void save(QTextStream &s, int, int) const override;
|
||||
};
|
||||
|
||||
class QDomCDATASectionPrivate : public QDomTextPrivate
|
||||
{
|
||||
public:
|
||||
QDomCDATASectionPrivate(QDomDocumentPrivate *, QDomNodePrivate *parent, const QString &val);
|
||||
QDomCDATASectionPrivate(QDomCDATASectionPrivate *n, bool deep);
|
||||
|
||||
// Reimplemented from QDomNodePrivate
|
||||
QDomNodePrivate *cloneNode(bool deep = true) override;
|
||||
QDomNode::NodeType nodeType() const override { return QDomNode::CDATASectionNode; }
|
||||
virtual void save(QTextStream &s, int, int) const override;
|
||||
};
|
||||
|
||||
class QDomNotationPrivate : public QDomNodePrivate
|
||||
{
|
||||
public:
|
||||
QDomNotationPrivate(QDomDocumentPrivate *, QDomNodePrivate *parent, const QString &name,
|
||||
const QString &pub, const QString &sys);
|
||||
QDomNotationPrivate(QDomNotationPrivate *n, bool deep);
|
||||
|
||||
// Reimplemented from QDomNodePrivate
|
||||
QDomNodePrivate *cloneNode(bool deep = true) override;
|
||||
QDomNode::NodeType nodeType() const override { return QDomNode::NotationNode; }
|
||||
virtual void save(QTextStream &s, int, int) const override;
|
||||
|
||||
// Variables
|
||||
QString m_sys;
|
||||
QString m_pub;
|
||||
};
|
||||
|
||||
class QDomEntityPrivate : public QDomNodePrivate
|
||||
{
|
||||
public:
|
||||
QDomEntityPrivate(QDomDocumentPrivate *, QDomNodePrivate *parent, const QString &name,
|
||||
const QString &pub, const QString &sys, const QString ¬ation);
|
||||
QDomEntityPrivate(QDomEntityPrivate *n, bool deep);
|
||||
|
||||
// Reimplemented from QDomNodePrivate
|
||||
QDomNodePrivate *cloneNode(bool deep = true) override;
|
||||
QDomNode::NodeType nodeType() const override { return QDomNode::EntityNode; }
|
||||
virtual void save(QTextStream &s, int, int) const override;
|
||||
|
||||
// Variables
|
||||
QString m_sys;
|
||||
QString m_pub;
|
||||
QString m_notationName;
|
||||
};
|
||||
|
||||
class QDomEntityReferencePrivate : public QDomNodePrivate
|
||||
{
|
||||
public:
|
||||
QDomEntityReferencePrivate(QDomDocumentPrivate *, QDomNodePrivate *parent, const QString &name);
|
||||
QDomEntityReferencePrivate(QDomNodePrivate *n, bool deep);
|
||||
|
||||
// Reimplemented from QDomNodePrivate
|
||||
QDomNodePrivate *cloneNode(bool deep = true) override;
|
||||
QDomNode::NodeType nodeType() const override { return QDomNode::EntityReferenceNode; }
|
||||
virtual void save(QTextStream &s, int, int) const override;
|
||||
};
|
||||
|
||||
class QDomProcessingInstructionPrivate : public QDomNodePrivate
|
||||
{
|
||||
public:
|
||||
QDomProcessingInstructionPrivate(QDomDocumentPrivate *, QDomNodePrivate *parent,
|
||||
const QString &target, const QString &data);
|
||||
QDomProcessingInstructionPrivate(QDomProcessingInstructionPrivate *n, bool deep);
|
||||
|
||||
// Reimplemented from QDomNodePrivate
|
||||
QDomNodePrivate *cloneNode(bool deep = true) override;
|
||||
QDomNode::NodeType nodeType() const override { return QDomNode::ProcessingInstructionNode; }
|
||||
virtual void save(QTextStream &s, int, int) const override;
|
||||
};
|
||||
|
||||
class QDomDocumentPrivate : public QDomNodePrivate
|
||||
{
|
||||
public:
|
||||
QDomDocumentPrivate();
|
||||
QDomDocumentPrivate(const QString &name);
|
||||
QDomDocumentPrivate(QDomDocumentTypePrivate *dt);
|
||||
QDomDocumentPrivate(QDomDocumentPrivate *n, bool deep);
|
||||
~QDomDocumentPrivate();
|
||||
|
||||
bool setContent(QXmlInputSource *source, bool namespaceProcessing, QString *errorMsg,
|
||||
int *errorLine, int *errorColumn);
|
||||
bool setContent(QXmlInputSource *source, QXmlReader *reader, QXmlSimpleReader *simpleReader,
|
||||
QString *errorMsg, int *errorLine, int *errorColumn);
|
||||
|
||||
// Attributes
|
||||
QDomDocumentTypePrivate *doctype() { return type.data(); }
|
||||
QDomImplementationPrivate *implementation() { return impl.data(); }
|
||||
QDomElementPrivate *documentElement();
|
||||
|
||||
// Factories
|
||||
QDomElementPrivate *createElement(const QString &tagName);
|
||||
QDomElementPrivate *createElementNS(const QString &nsURI, const QString &qName);
|
||||
QDomDocumentFragmentPrivate *createDocumentFragment();
|
||||
QDomTextPrivate *createTextNode(const QString &data);
|
||||
QDomCommentPrivate *createComment(const QString &data);
|
||||
QDomCDATASectionPrivate *createCDATASection(const QString &data);
|
||||
QDomProcessingInstructionPrivate *createProcessingInstruction(const QString &target,
|
||||
const QString &data);
|
||||
QDomAttrPrivate *createAttribute(const QString &name);
|
||||
QDomAttrPrivate *createAttributeNS(const QString &nsURI, const QString &qName);
|
||||
QDomEntityReferencePrivate *createEntityReference(const QString &name);
|
||||
|
||||
QDomNodePrivate *importNode(QDomNodePrivate *importedNode, bool deep);
|
||||
|
||||
// Reimplemented from QDomNodePrivate
|
||||
QDomNodePrivate *cloneNode(bool deep = true) override;
|
||||
QDomNode::NodeType nodeType() const override { return QDomNode::DocumentNode; }
|
||||
void clear() override;
|
||||
|
||||
// Variables
|
||||
QExplicitlySharedDataPointer<QDomImplementationPrivate> impl;
|
||||
QExplicitlySharedDataPointer<QDomDocumentTypePrivate> type;
|
||||
|
||||
void saveDocument(QTextStream &stream, const int indent,
|
||||
QDomNode::EncodingPolicy encUsed) const;
|
||||
|
||||
/* \internal
|
||||
Counter for the QDomNodeListPrivate timestamps.
|
||||
|
||||
This is a cache optimization, that might in some cases be effective. The
|
||||
dilemma is that QDomNode::childNodes() returns a list, but the
|
||||
implementation stores the children in a linked list. Hence, in order to
|
||||
get the children out through childNodes(), a list must be populated each
|
||||
time, which is O(N).
|
||||
|
||||
DOM has the requirement of node references being live, see DOM Core
|
||||
Level 3, 1.1.1 The DOM Structure Model, which means that changes to the
|
||||
underlying documents must be reflected in node lists.
|
||||
|
||||
This mechanism, nodeListTime, is a caching optimization that reduces the
|
||||
amount of times the node list is rebuilt, by only doing so when the
|
||||
document actually changes. However, a change to anywhere in any document
|
||||
invalidate all lists, since no dependency tracking is done.
|
||||
|
||||
It functions by that all modifying functions(insertBefore() and so on)
|
||||
increment the count; each QDomNodeListPrivate copies nodeListTime on
|
||||
construction, and compares its own value to nodeListTime in order to
|
||||
determine whether it needs to rebuild.
|
||||
|
||||
This is reentrant. The nodeListTime may overflow, but that's ok since we
|
||||
check for equalness, not whether nodeListTime is smaller than the list's
|
||||
stored timestamp.
|
||||
*/
|
||||
long nodeListTime;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QDOMHELPERS_P_H
|
||||
|
|
@ -0,0 +1,247 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2019 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtXml 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 "qdomhelpers_p.h"
|
||||
#include "qdom_p.h"
|
||||
#include "private/qxml_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* QDomHandler
|
||||
*
|
||||
**************************************************************/
|
||||
|
||||
QDomHandler::QDomHandler(QDomDocumentPrivate *adoc, QXmlSimpleReader *areader,
|
||||
bool namespaceProcessing)
|
||||
: errorLine(0),
|
||||
errorColumn(0),
|
||||
doc(adoc),
|
||||
node(adoc),
|
||||
cdata(false),
|
||||
nsProcessing(namespaceProcessing),
|
||||
locator(nullptr),
|
||||
reader(areader)
|
||||
{
|
||||
}
|
||||
|
||||
QDomHandler::~QDomHandler() {}
|
||||
|
||||
bool QDomHandler::endDocument()
|
||||
{
|
||||
// ### is this really necessary? (rms)
|
||||
if (node != doc)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QDomHandler::startDTD(const QString &name, const QString &publicId, const QString &systemId)
|
||||
{
|
||||
doc->doctype()->name = name;
|
||||
doc->doctype()->publicId = publicId;
|
||||
doc->doctype()->systemId = systemId;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QDomHandler::startElement(const QString &nsURI, const QString &, const QString &qName,
|
||||
const QXmlAttributes &atts)
|
||||
{
|
||||
// tag name
|
||||
QDomNodePrivate *n;
|
||||
if (nsProcessing) {
|
||||
n = doc->createElementNS(nsURI, qName);
|
||||
} else {
|
||||
n = doc->createElement(qName);
|
||||
}
|
||||
|
||||
if (!n)
|
||||
return false;
|
||||
|
||||
n->setLocation(locator->lineNumber(), locator->columnNumber());
|
||||
|
||||
node->appendChild(n);
|
||||
node = n;
|
||||
|
||||
// attributes
|
||||
for (int i = 0; i < atts.length(); i++) {
|
||||
if (nsProcessing) {
|
||||
((QDomElementPrivate *)node)->setAttributeNS(atts.uri(i), atts.qName(i), atts.value(i));
|
||||
} else {
|
||||
((QDomElementPrivate *)node)->setAttribute(atts.qName(i), atts.value(i));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QDomHandler::endElement(const QString &, const QString &, const QString &)
|
||||
{
|
||||
if (!node || node == doc)
|
||||
return false;
|
||||
node = node->parent();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QDomHandler::characters(const QString &ch)
|
||||
{
|
||||
// No text as child of some document
|
||||
if (node == doc)
|
||||
return false;
|
||||
|
||||
QScopedPointer<QDomNodePrivate> n;
|
||||
if (cdata) {
|
||||
n.reset(doc->createCDATASection(ch));
|
||||
} else if (!entityName.isEmpty()) {
|
||||
QScopedPointer<QDomEntityPrivate> e(
|
||||
new QDomEntityPrivate(doc, nullptr, entityName, QString(), QString(), QString()));
|
||||
e->value = ch;
|
||||
e->ref.deref();
|
||||
doc->doctype()->appendChild(e.data());
|
||||
e.take();
|
||||
n.reset(doc->createEntityReference(entityName));
|
||||
} else {
|
||||
n.reset(doc->createTextNode(ch));
|
||||
}
|
||||
n->setLocation(locator->lineNumber(), locator->columnNumber());
|
||||
node->appendChild(n.data());
|
||||
n.take();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QDomHandler::processingInstruction(const QString &target, const QString &data)
|
||||
{
|
||||
QDomNodePrivate *n;
|
||||
n = doc->createProcessingInstruction(target, data);
|
||||
if (n) {
|
||||
n->setLocation(locator->lineNumber(), locator->columnNumber());
|
||||
node->appendChild(n);
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QDomHandler::skippedEntity(const QString &name)
|
||||
{
|
||||
// we can only handle inserting entity references into content
|
||||
if (reader && !reader->d_ptr->skipped_entity_in_content)
|
||||
return true;
|
||||
|
||||
QDomNodePrivate *n = doc->createEntityReference(name);
|
||||
n->setLocation(locator->lineNumber(), locator->columnNumber());
|
||||
node->appendChild(n);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QDomHandler::fatalError(const QXmlParseException &exception)
|
||||
{
|
||||
errorMsg = exception.message();
|
||||
errorLine = exception.lineNumber();
|
||||
errorColumn = exception.columnNumber();
|
||||
return QXmlDefaultHandler::fatalError(exception);
|
||||
}
|
||||
|
||||
bool QDomHandler::startCDATA()
|
||||
{
|
||||
cdata = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QDomHandler::endCDATA()
|
||||
{
|
||||
cdata = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QDomHandler::startEntity(const QString &name)
|
||||
{
|
||||
entityName = name;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QDomHandler::endEntity(const QString &)
|
||||
{
|
||||
entityName.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QDomHandler::comment(const QString &ch)
|
||||
{
|
||||
QDomNodePrivate *n;
|
||||
n = doc->createComment(ch);
|
||||
n->setLocation(locator->lineNumber(), locator->columnNumber());
|
||||
node->appendChild(n);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QDomHandler::unparsedEntityDecl(const QString &name, const QString &publicId,
|
||||
const QString &systemId, const QString ¬ationName)
|
||||
{
|
||||
QDomEntityPrivate *e =
|
||||
new QDomEntityPrivate(doc, nullptr, name, publicId, systemId, notationName);
|
||||
// keep the refcount balanced: appendChild() does a ref anyway.
|
||||
e->ref.deref();
|
||||
doc->doctype()->appendChild(e);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QDomHandler::externalEntityDecl(const QString &name, const QString &publicId,
|
||||
const QString &systemId)
|
||||
{
|
||||
return unparsedEntityDecl(name, publicId, systemId, QString());
|
||||
}
|
||||
|
||||
bool QDomHandler::notationDecl(const QString &name, const QString &publicId,
|
||||
const QString &systemId)
|
||||
{
|
||||
QDomNotationPrivate *n = new QDomNotationPrivate(doc, nullptr, name, publicId, systemId);
|
||||
// keep the refcount balanced: appendChild() does a ref anyway.
|
||||
n->ref.deref();
|
||||
doc->doctype()->appendChild(n);
|
||||
return true;
|
||||
}
|
||||
|
||||
void QDomHandler::setDocumentLocator(QXmlLocator *locator)
|
||||
{
|
||||
this->locator = locator;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2019 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtXml 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$
|
||||
**
|
||||
****************************************************************************/
|
||||
#ifndef QDOMHELPERS_P_H
|
||||
#define QDOMHELPERS_P_H
|
||||
|
||||
#include <qglobal.h>
|
||||
#include <qxml.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists for the convenience of
|
||||
// qxml.cpp and qdom.cpp. This header file may change from version to version without
|
||||
// notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
class QDomDocumentPrivate;
|
||||
class QDomNodePrivate;
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* QDomHandler
|
||||
*
|
||||
**************************************************************/
|
||||
|
||||
class QDomHandler : public QXmlDefaultHandler
|
||||
{
|
||||
public:
|
||||
QDomHandler(QDomDocumentPrivate *d, QXmlSimpleReader *reader, bool namespaceProcessing);
|
||||
~QDomHandler();
|
||||
|
||||
// content handler
|
||||
bool endDocument() override;
|
||||
bool startElement(const QString &nsURI, const QString &localName, const QString &qName,
|
||||
const QXmlAttributes &atts) override;
|
||||
bool endElement(const QString &nsURI, const QString &localName, const QString &qName) override;
|
||||
bool characters(const QString &ch) override;
|
||||
bool processingInstruction(const QString &target, const QString &data) override;
|
||||
bool skippedEntity(const QString &name) override;
|
||||
|
||||
// error handler
|
||||
bool fatalError(const QXmlParseException &exception) override;
|
||||
|
||||
// lexical handler
|
||||
bool startCDATA() override;
|
||||
bool endCDATA() override;
|
||||
bool startEntity(const QString &) override;
|
||||
bool endEntity(const QString &) override;
|
||||
bool startDTD(const QString &name, const QString &publicId, const QString &systemId) override;
|
||||
bool comment(const QString &ch) override;
|
||||
|
||||
// decl handler
|
||||
bool externalEntityDecl(const QString &name, const QString &publicId,
|
||||
const QString &systemId) override;
|
||||
|
||||
// DTD handler
|
||||
bool notationDecl(const QString &name, const QString &publicId,
|
||||
const QString &systemId) override;
|
||||
bool unparsedEntityDecl(const QString &name, const QString &publicId, const QString &systemId,
|
||||
const QString ¬ationName) override;
|
||||
|
||||
void setDocumentLocator(QXmlLocator *locator) override;
|
||||
|
||||
QString errorMsg;
|
||||
int errorLine;
|
||||
int errorColumn;
|
||||
|
||||
private:
|
||||
QDomDocumentPrivate *doc;
|
||||
QDomNodePrivate *node;
|
||||
QString entityName;
|
||||
bool cdata;
|
||||
bool nsProcessing;
|
||||
QXmlLocator *locator;
|
||||
QXmlSimpleReader *reader;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QDOMHELPERS_P_H
|
||||
|
|
@ -1590,6 +1590,9 @@ void tst_QRhi::renderToWindowSimple()
|
|||
QScopedPointer<QWindow> window(new QWindow);
|
||||
switch (impl) {
|
||||
case QRhi::OpenGLES2:
|
||||
#if QT_CONFIG(opengl)
|
||||
window->setFormat(QRhiGles2InitParams::adjustedFormat());
|
||||
#endif
|
||||
Q_FALLTHROUGH();
|
||||
case QRhi::D3D11:
|
||||
window->setSurfaceType(QSurface::OpenGLSurface);
|
||||
|
|
|
|||
|
|
@ -836,10 +836,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