QSslSocket - introduce the API providing information about backends
This API gives the names of available backends and provides a basic information about features/protocols supported by those backends. Also, it has the 'loadBackend' functions which allow to select a particular backend (which are becoming plugins). At the moment, the implementation is still 'hardcoded', the follow-up patch will allow to select different backends in runtime. Task-number: QTBUG-65922 Change-Id: I05877de9c02857594e76b24d52e7578bdb01df69 Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>bb10
parent
509196b1d9
commit
ee89f3a6e3
|
|
@ -1,6 +1,6 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2021 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtNetwork module of the Qt Toolkit.
|
||||
|
|
@ -243,4 +243,51 @@ Q_LOGGING_CATEGORY(lcSsl, "qt.network.ssl");
|
|||
\value UnknownAlertMessage
|
||||
*/
|
||||
|
||||
/*!
|
||||
\enum QSsl::ImplementedClass
|
||||
\brief Enumerates classes that a TLS backend implements
|
||||
\relates QSslSocket
|
||||
\since 6.1
|
||||
|
||||
\ingroup network
|
||||
\ingroup ssl
|
||||
\inmodule QtNetwork
|
||||
|
||||
In QtNetwork, some classes have backend-specific implementation and thus
|
||||
can be left unimplemented. Enumerators in this enum indicate, which class
|
||||
has a working implementation in the backend.
|
||||
|
||||
\value Key Class QSslKey.
|
||||
\value Certificate Class QSslCertificate.
|
||||
\value Socket Class QSslSocket.
|
||||
\value DiffieHellman Class QSslDiffieHellmanParameters
|
||||
\value EllipticCurve Class QSslEllipticCurve
|
||||
\value Dtls Classes QDtls and QDtlsClientVerifier
|
||||
*/
|
||||
|
||||
/*!
|
||||
\enum QSsl::SupportedFeature
|
||||
\brief Enumerates possible features that a TLS backend supports
|
||||
\relates QSslSocket
|
||||
\since 6.1
|
||||
|
||||
\ingroup network
|
||||
\ingroup ssl
|
||||
\inmodule QtNetwork
|
||||
|
||||
In QtNetwork TLS-related classes have public API, that may be left unimplemented
|
||||
by some backend, for example, our SecureTransport backend does not support
|
||||
server-side ALPN. Enumerators from SupportedFeature enum indicate that a particular
|
||||
feature is supported.
|
||||
|
||||
\value CertificateVerification Indicates that QSslCertificate::verify() is
|
||||
implemented by the backend.
|
||||
\value ClientSideAlpn Client-side ALPN (Application Layer Protocol Negotiation).
|
||||
\value ServerSideAlpn Server-side ALPN.
|
||||
\value Ocsp OCSP stapling (Online Certificate Status Protocol).
|
||||
\value Psk Pre-shared keys.
|
||||
\value SessionTicket Session tickets.
|
||||
\value Alerts Information about alert messages sent and received.
|
||||
*/
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2019 The Qt Company Ltd.
|
||||
** Copyright (C) 2021 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtNetwork module of the Qt Toolkit.
|
||||
|
|
@ -149,6 +149,26 @@ namespace QSsl {
|
|||
UnknownAlertMessage = 255
|
||||
};
|
||||
|
||||
enum class ImplementedClass
|
||||
{
|
||||
Key = 0x1,
|
||||
Certificate = 0x2,
|
||||
Socket = 0x4,
|
||||
DiffieHellman = 0x8,
|
||||
EllipticCurve = 0x10,
|
||||
Dtls = 0x20
|
||||
};
|
||||
|
||||
enum class SupportedFeature
|
||||
{
|
||||
CertificateVerification = 0x1,
|
||||
ClientSideAlpn = 0x2,
|
||||
ServerSideAlpn = 0x4,
|
||||
Ocsp = 0x8,
|
||||
Psk = 0x10,
|
||||
SessionTicket = 0x20,
|
||||
Alerts = 040
|
||||
};
|
||||
}
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QSsl::SslOptions)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2021 The Qt Company Ltd.
|
||||
** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
|
|
@ -1546,6 +1546,150 @@ QString QSslSocket::sslLibraryBuildVersionString()
|
|||
return QSslSocketPrivate::sslLibraryBuildVersionString();
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 6.1
|
||||
Returns the names of the currently available backends. These names
|
||||
are in lower case, e.g. "openssl", "securetransport", "schannel"
|
||||
(similar to the already existing feature names for TLS backends in Qt).
|
||||
|
||||
\sa activeBackend()
|
||||
*/
|
||||
QList<QString> QSslSocket::availableBackends()
|
||||
{
|
||||
return QSslSocketPrivate::availableBackends();
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 6.1
|
||||
Returns the name of the backend that was loaded (implicitly by QSslSocket
|
||||
or by an application via loadBackend() call). If no backend was loaded yet,
|
||||
this function returns the name of the backend that will be loaded by QSslSocket.
|
||||
|
||||
\note When selecting a default backend implicitly from the list of available
|
||||
backends, QSslSocket prefers native backends, such as SecureTransport on Darwin,
|
||||
or Schannel on Windows.
|
||||
|
||||
\sa loadBackend(), availableBackends()
|
||||
*/
|
||||
QString QSslSocket::activeBackend()
|
||||
{
|
||||
return QSslSocketPrivate::activeBackend();
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 6.1
|
||||
Returns true if a backend with name \a backendName was loaded
|
||||
and was made the current active backend. \a backendName must
|
||||
be one of names returned by availableBackends().
|
||||
|
||||
\note An application can switch from the default backend,
|
||||
that will be implicitly loaded by QSslSocket, to a different backend
|
||||
only once. It cannot mix several backends simultaneously. A non-default
|
||||
backend must be selected prior to any use of QSslSocket or related classes
|
||||
(like QSslCertificate or QSslKey).
|
||||
|
||||
\sa activeBackend(), availableBackends()
|
||||
*/
|
||||
bool QSslSocket::loadBackend(const QString &backendName)
|
||||
{
|
||||
return QSslSocketPrivate::loadBackend(backendName);
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 6.1
|
||||
If a backend with name \a backendName is available, this function returns the
|
||||
list of TLS protocol versions supported by this backend. An empty \a backendName
|
||||
is understood as a query about the currently active backend. Otherwise, this
|
||||
function returns an empty list.
|
||||
|
||||
\sa availableBackends(), activeBackend(), isProtocolSupported()
|
||||
*/
|
||||
QList<QSsl::SslProtocol> QSslSocket::supportedProtocols(const QString &backendName)
|
||||
{
|
||||
if (Q_UNLIKELY(backendName.size() && !availableBackends().contains(backendName))) {
|
||||
qCWarning(lcSsl) << "Cannot provide the list of supported protocols for the backend"
|
||||
<< backendName;
|
||||
return {};
|
||||
}
|
||||
|
||||
return QSslSocketPrivate::supportedProtocols(backendName);
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 6.1
|
||||
Returns true if \a protocol is supported by a backend named \a backendName. An empty
|
||||
\a backendName is understood as a query about the currently active backend.
|
||||
|
||||
\sa supportedProtocols()
|
||||
*/
|
||||
bool QSslSocket::isProtocolSupported(QSsl::SslProtocol protocol, const QString &backendName)
|
||||
{
|
||||
const auto versions = supportedProtocols(backendName);
|
||||
return versions.contains(protocol);
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 6.1
|
||||
This function returns backend-specific classes implemented by the backend named
|
||||
\a backendName. An empty \a backendName is understood as a query about the
|
||||
currently active backend.
|
||||
|
||||
\sa QSsl::ImplementedClass, activeBackend(), isClassImplemented()
|
||||
*/
|
||||
QList<QSsl::ImplementedClass> QSslSocket::implementedClasses(const QString &backendName)
|
||||
{
|
||||
if (Q_UNLIKELY(backendName.size() && !availableBackends().contains(backendName))) {
|
||||
qCWarning(lcSsl) << "Cannot provide information about supported classes for"
|
||||
<< "backend" << backendName;
|
||||
return {};
|
||||
}
|
||||
|
||||
return QSslSocketPrivate::implementedClasses(backendName);
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 6.1
|
||||
Returns true if a class \cl is implemented by the backend named \a backendName. An empty
|
||||
\a backendName is understood as a query about the currently active backend.
|
||||
|
||||
\sa implementedClasses()
|
||||
*/
|
||||
|
||||
bool QSslSocket::isClassImplemented(QSsl::ImplementedClass cl, const QString &backendName)
|
||||
{
|
||||
return implementedClasses(backendName).contains(cl);
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 6.1
|
||||
This function returns features supported by a backend named \a backendName.
|
||||
An empty \a backendName is understood as a query about the currently active backend.
|
||||
|
||||
\sa QSsl::SupportedFeature, activeBackend()
|
||||
*/
|
||||
QList<QSsl::SupportedFeature> QSslSocket::supportedFeatures(const QString &backendName)
|
||||
{
|
||||
if (Q_UNLIKELY(backendName.size() && !availableBackends().contains(backendName))) {
|
||||
qCWarning(lcSsl) << "Cannot provide information about supported features for"
|
||||
<< "backend" << backendName;
|
||||
return {};
|
||||
}
|
||||
|
||||
return QSslSocketPrivate::supportedFeatures(backendName);
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 6.1
|
||||
Returns true if a feature \a ft is supported by a backend named \a backendName. An empty
|
||||
\a backendName is understood as a query about the currently active backend.
|
||||
|
||||
\sa QSsl::SupportedFeature, supportedFeatures()
|
||||
*/
|
||||
bool QSslSocket::isFeatureSupported(QSsl::SupportedFeature ft, const QString &backendName)
|
||||
{
|
||||
return supportedFeatures(backendName).contains(ft);
|
||||
}
|
||||
|
||||
/*!
|
||||
Starts a delayed SSL handshake for a client connection. This
|
||||
function can be called when the socket is in the \l ConnectedState
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2021 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtNetwork module of the Qt Toolkit.
|
||||
|
|
@ -163,6 +163,16 @@ public:
|
|||
static long sslLibraryBuildVersionNumber();
|
||||
static QString sslLibraryBuildVersionString();
|
||||
|
||||
static QList<QString> availableBackends();
|
||||
static QString activeBackend();
|
||||
static bool loadBackend(const QString &backendName);
|
||||
static QList<QSsl::SslProtocol> supportedProtocols(const QString &backendName = {});
|
||||
static bool isProtocolSupported(QSsl::SslProtocol protocol, const QString &backendName = {});
|
||||
static QList<QSsl::ImplementedClass> implementedClasses(const QString &backendName = {});
|
||||
static bool isClassImplemented(QSsl::ImplementedClass cl, const QString &backendName = {});
|
||||
static QList<QSsl::SupportedFeature> supportedFeatures(const QString &backendName = {});
|
||||
static bool isFeatureSupported(QSsl::SupportedFeature feat, const QString &backendName = {});
|
||||
|
||||
void ignoreSslErrors(const QList<QSslError> &errors);
|
||||
void continueInterruptedHandshake();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2021 The Qt Company Ltd.
|
||||
** Copyright (C) 2014 Jeremy Lainé <jeremy.laine@m4x.org>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
|
|
@ -1551,4 +1552,90 @@ bool QSslSocketBackendPrivate::startHandshake()
|
|||
}
|
||||
}
|
||||
|
||||
QList<QString> QSslSocketPrivate::availableBackends()
|
||||
{
|
||||
return {QStringLiteral("securetransport")};
|
||||
}
|
||||
|
||||
QString QSslSocketPrivate::activeBackend()
|
||||
{
|
||||
return availableBackends().first();
|
||||
}
|
||||
|
||||
bool QSslSocketPrivate::loadBackend(const QString &backendName)
|
||||
{
|
||||
if (backendName.size() && !availableBackends().contains(backendName)) {
|
||||
qCWarning(lcSsl) << "A TLS backend with name" << backendName << "is not available";
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool loaded = false;
|
||||
static QBasicMutex mutex;
|
||||
const QMutexLocker locker(&mutex);
|
||||
if (loaded) {
|
||||
qCWarning(lcSsl) << "You have already loaded the backend named:" << activeBackend();
|
||||
if (backendName.size())
|
||||
qCWarning(lcSsl) << "Cannot load:" << backendName;
|
||||
else
|
||||
qCWarning(lcSsl) << "Cannot load the default backend (securetransport)";
|
||||
return true;
|
||||
}
|
||||
// This code to be placed in qsslsocket.cpp and there
|
||||
// the actual plugin to be loaded (so the result can be
|
||||
// false if we, for example, failed to resolve OpenSSL
|
||||
// symbols).
|
||||
return loaded = true;
|
||||
}
|
||||
|
||||
QList<QSsl::SslProtocol> QSslSocketPrivate::supportedProtocols(const QString &backendName)
|
||||
{
|
||||
QList<QSsl::SslProtocol> protocols;
|
||||
if (backendName.size() && backendName != activeBackend()) {
|
||||
qCWarning(lcSsl) << "Unexpected backend name" << backendName
|
||||
<< "no information about protocols supported can be found";
|
||||
return protocols;
|
||||
}
|
||||
|
||||
protocols << QSsl::AnyProtocol;
|
||||
protocols << QSsl::SecureProtocols;
|
||||
protocols << QSsl::TlsV1_0;
|
||||
protocols << QSsl::TlsV1_0OrLater;
|
||||
protocols << QSsl::TlsV1_1;
|
||||
protocols << QSsl::TlsV1_1OrLater;
|
||||
protocols << QSsl::TlsV1_2;
|
||||
protocols << QSsl::TlsV1_2OrLater;
|
||||
|
||||
return protocols;
|
||||
}
|
||||
|
||||
QList<QSsl::ImplementedClass> QSslSocketPrivate::implementedClasses(const QString &backendName)
|
||||
{
|
||||
QList<QSsl::ImplementedClass> classes;
|
||||
if (backendName.size() && backendName != activeBackend()) {
|
||||
qCWarning(lcSsl) << "Unexpected backend name" << backendName
|
||||
<< "no information about classes implemented can be found";
|
||||
return classes;
|
||||
}
|
||||
|
||||
classes << QSsl::ImplementedClass::Key;
|
||||
classes << QSsl::ImplementedClass::Certificate;
|
||||
classes << QSsl::ImplementedClass::Socket;
|
||||
|
||||
return classes;
|
||||
}
|
||||
|
||||
QList<QSsl::SupportedFeature> QSslSocketPrivate::supportedFeatures(const QString &backendName)
|
||||
{
|
||||
QList<QSsl::SupportedFeature> features;
|
||||
if (backendName.size() && backendName != activeBackend()) {
|
||||
qCWarning(lcSsl) << "Unexpected backend name" << backendName
|
||||
<< "no information about classes implemented can be found";
|
||||
return features;
|
||||
}
|
||||
|
||||
features << QSsl::SupportedFeature::ClientSideAlpn;
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2017 The Qt Company Ltd.
|
||||
** Copyright (C) 2021 The Qt Company Ltd.
|
||||
** Copyright (C) 2014 Governikus GmbH & Co. KG
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
|
|
@ -2510,5 +2510,111 @@ bool QSslSocketBackendPrivate::importPkcs12(QIODevice *device,
|
|||
return true;
|
||||
}
|
||||
|
||||
QList<QString> QSslSocketPrivate::availableBackends()
|
||||
{
|
||||
return {QStringLiteral("openssl")};
|
||||
}
|
||||
|
||||
QString QSslSocketPrivate::activeBackend()
|
||||
{
|
||||
return availableBackends().first();
|
||||
}
|
||||
|
||||
bool QSslSocketPrivate::loadBackend(const QString &backendName)
|
||||
{
|
||||
if (backendName.size() && backendName != activeBackend()) {
|
||||
qCWarning(lcSsl) << "A TLS backend with name" << backendName << "is not available";
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool loaded = false;
|
||||
static QBasicMutex mutex;
|
||||
const QMutexLocker locker(&mutex);
|
||||
if (loaded) {
|
||||
qCWarning(lcSsl) << "You have already loaded the backend named:" << activeBackend();
|
||||
if (backendName.size())
|
||||
qCWarning(lcSsl) << "Cannot load:" << backendName;
|
||||
else
|
||||
qCWarning(lcSsl) << "Cannot load the default backend (openssl)";
|
||||
return true;
|
||||
}
|
||||
// This code to be placed in qsslsocket.cpp and there
|
||||
// the actual plugin to be loaded (so the result can be
|
||||
// false if we, for example, failed to resolve OpenSSL
|
||||
// symbols).
|
||||
return loaded = true;
|
||||
}
|
||||
|
||||
QList<QSsl::SslProtocol> QSslSocketPrivate::supportedProtocols(const QString &backendName)
|
||||
{
|
||||
QList<QSsl::SslProtocol> protocols;
|
||||
if (backendName.size() && backendName != activeBackend()) {
|
||||
qCWarning(lcSsl) << "Unexpected backend name" << backendName
|
||||
<< "no information about protocols supported can be found";
|
||||
return protocols;
|
||||
}
|
||||
|
||||
protocols << QSsl::AnyProtocol;
|
||||
protocols << QSsl::SecureProtocols;
|
||||
protocols << QSsl::TlsV1_0;
|
||||
protocols << QSsl::TlsV1_0OrLater;
|
||||
protocols << QSsl::TlsV1_1;
|
||||
protocols << QSsl::TlsV1_1OrLater;
|
||||
protocols << QSsl::TlsV1_2;
|
||||
protocols << QSsl::TlsV1_2OrLater;
|
||||
|
||||
#ifdef TLS1_3_VERSION
|
||||
protocols << QSsl::TlsV1_3;
|
||||
protocols << QSsl::TlsV1_3OrLater;
|
||||
#endif // TLS1_3_VERSION
|
||||
|
||||
#if QT_CONFIG(dtls)
|
||||
protocols << QSsl::DtlsV1_0;
|
||||
protocols << QSsl::DtlsV1_0OrLater;
|
||||
protocols << QSsl::DtlsV1_2;
|
||||
protocols << QSsl::DtlsV1_2OrLater;
|
||||
#endif // dtls
|
||||
|
||||
return protocols;
|
||||
}
|
||||
|
||||
QList<QSsl::ImplementedClass> QSslSocketPrivate::implementedClasses(const QString &backendName)
|
||||
{
|
||||
QList<QSsl::ImplementedClass> classes;
|
||||
if (backendName.size() && backendName != activeBackend()) {
|
||||
qCWarning(lcSsl) << "Unexpected backend name" << backendName
|
||||
<< "no information about classes implemented can be found";
|
||||
return classes;
|
||||
}
|
||||
|
||||
classes << QSsl::ImplementedClass::Key;
|
||||
classes << QSsl::ImplementedClass::Certificate;
|
||||
classes << QSsl::ImplementedClass::Socket;
|
||||
classes << QSsl::ImplementedClass::Dtls;
|
||||
classes << QSsl::ImplementedClass::EllipticCurve;
|
||||
classes << QSsl::ImplementedClass::DiffieHellman;
|
||||
|
||||
return classes;
|
||||
}
|
||||
|
||||
QList<QSsl::SupportedFeature> QSslSocketPrivate::supportedFeatures(const QString &backendName)
|
||||
{
|
||||
QList<QSsl::SupportedFeature> features;
|
||||
if (backendName.size() && backendName != activeBackend()) {
|
||||
qCWarning(lcSsl) << "Unexpected backend name" << backendName
|
||||
<< "no information about classes implemented can be found";
|
||||
return features;
|
||||
}
|
||||
|
||||
features << QSsl::SupportedFeature::CertificateVerification;
|
||||
features << QSsl::SupportedFeature::ClientSideAlpn;
|
||||
features << QSsl::SupportedFeature::ServerSideAlpn;
|
||||
features << QSsl::SupportedFeature::Ocsp;
|
||||
features << QSsl::SupportedFeature::Psk;
|
||||
features << QSsl::SupportedFeature::SessionTicket;
|
||||
features << QSsl::SupportedFeature::Alerts;
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2021 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtNetwork module of the Qt Toolkit.
|
||||
|
|
@ -204,6 +204,12 @@ public:
|
|||
|
||||
Q_AUTOTEST_EXPORT static bool rootCertOnDemandLoadingSupported();
|
||||
|
||||
static QList<QString> availableBackends();
|
||||
static QString activeBackend();
|
||||
static bool loadBackend(const QString &backendName);
|
||||
static QList<QSsl::SslProtocol> supportedProtocols(const QString &backendName);
|
||||
static QList<QSsl::ImplementedClass> implementedClasses(const QString &backendName);
|
||||
static QList<QSsl::SupportedFeature> supportedFeatures(const QString &backendName);
|
||||
private:
|
||||
static bool ensureLibraryLoaded();
|
||||
static void ensureCiphersAndCertsLoaded();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Copyright (C) 2021 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtNetwork module of the Qt Toolkit.
|
||||
|
|
@ -2144,4 +2144,93 @@ bool QSslSocketBackendPrivate::rootCertOnDemandLoadingAllowed()
|
|||
return allowRootCertOnDemandLoading && s_loadRootCertsOnDemand;
|
||||
}
|
||||
|
||||
QList<QString> QSslSocketPrivate::availableBackends()
|
||||
{
|
||||
return {QStringLiteral("schannel")};
|
||||
}
|
||||
|
||||
QString QSslSocketPrivate::activeBackend()
|
||||
{
|
||||
return availableBackends().first();
|
||||
}
|
||||
|
||||
bool QSslSocketPrivate::loadBackend(const QString &backendName)
|
||||
{
|
||||
if (backendName.size() && !availableBackends().contains(backendName)) {
|
||||
qCWarning(lcSsl) << "A TLS backend with name" << backendName << "is not available";
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool loaded = false;
|
||||
static QBasicMutex mutex;
|
||||
const QMutexLocker locker(&mutex);
|
||||
if (loaded) {
|
||||
qCWarning(lcSsl) << "You have already loaded the backend named:" << activeBackend();
|
||||
qCWarning(lcSsl) << "Cannot load:" << backendName;
|
||||
return true;
|
||||
}
|
||||
// This code to be placed in qsslsocket.cpp and there
|
||||
// the actual plugin to be loaded (so the result can be
|
||||
// false if we, for example, failed to resolve OpenSSL
|
||||
// symbols).
|
||||
return loaded = true;
|
||||
}
|
||||
|
||||
QList<QSsl::SslProtocol> QSslSocketPrivate::supportedProtocols(const QString &backendName)
|
||||
{
|
||||
QList<QSsl::SslProtocol> protocols;
|
||||
if (backendName.size() && backendName != activeBackend()) {
|
||||
qCWarning(lcSsl) << "Unexpected backend name" << backendName
|
||||
<< "no information about protocols supported can be found";
|
||||
return protocols;
|
||||
}
|
||||
|
||||
protocols << QSsl::AnyProtocol;
|
||||
protocols << QSsl::SecureProtocols;
|
||||
protocols << QSsl::TlsV1_0;
|
||||
protocols << QSsl::TlsV1_0OrLater;
|
||||
protocols << QSsl::TlsV1_1;
|
||||
protocols << QSsl::TlsV1_1OrLater;
|
||||
protocols << QSsl::TlsV1_2;
|
||||
protocols << QSsl::TlsV1_2OrLater;
|
||||
|
||||
if (supportsTls13()) {
|
||||
protocols << QSsl::TlsV1_3;
|
||||
protocols << QSsl::TlsV1_3OrLater;
|
||||
}
|
||||
|
||||
return protocols;
|
||||
}
|
||||
|
||||
QList<QSsl::ImplementedClass> QSslSocketPrivate::implementedClasses(const QString &backendName)
|
||||
{
|
||||
QList<QSsl::ImplementedClass> classes;
|
||||
if (backendName.size() && backendName != activeBackend()) {
|
||||
qCWarning(lcSsl) << "Unexpected backend name" << backendName
|
||||
<< "no information about classes implemented can be found";
|
||||
return classes;
|
||||
}
|
||||
|
||||
classes << QSsl::ImplementedClass::Key;
|
||||
classes << QSsl::ImplementedClass::Certificate;
|
||||
classes << QSsl::ImplementedClass::Socket;
|
||||
|
||||
return classes;
|
||||
}
|
||||
|
||||
QList<QSsl::SupportedFeature> QSslSocketPrivate::supportedFeatures(const QString &backendName)
|
||||
{
|
||||
QList<QSsl::SupportedFeature> features;
|
||||
if (backendName.size() && backendName != activeBackend()) {
|
||||
qCWarning(lcSsl) << "Unexpected backend name" << backendName
|
||||
<< "no information about classes implemented can be found";
|
||||
return features;
|
||||
}
|
||||
|
||||
features << QSsl::SupportedFeature::ClientSideAlpn;
|
||||
features << QSsl::SupportedFeature::ServerSideAlpn;
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2021 The Qt Company Ltd.
|
||||
** Copyright (C) 2014 Governikus GmbH & Co. KG.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
|
|
@ -435,6 +435,50 @@ void tst_QSslSocket::initTestCase()
|
|||
QSKIP("No network test server available");
|
||||
#endif // QT_TEST_SERVER
|
||||
#endif // QT_NO_SSL
|
||||
|
||||
// Since a backend can be loaded only once by an application (this test in our case),
|
||||
// we do backend testing here:
|
||||
const QString nonExistingBackend = QStringLiteral("TheQtTLS");
|
||||
QCOMPARE(QSslSocket::loadBackend(nonExistingBackend), false);
|
||||
QCOMPARE(QSslSocket::supportedProtocols(nonExistingBackend).size(), 0);
|
||||
QCOMPARE(QSslSocket::supportedFeatures(nonExistingBackend), QList<QSsl::SupportedFeature>());
|
||||
QCOMPARE(QSslSocket::implementedClasses(nonExistingBackend), QList<QSsl::ImplementedClass>());
|
||||
|
||||
const QString backendName = QSslSocket::activeBackend();
|
||||
// Implemented by all our existing backends:
|
||||
const auto implemented = QSsl::ImplementedClass::Socket;
|
||||
const auto supportedFt = QSsl::SupportedFeature::ClientSideAlpn;
|
||||
|
||||
QVERIFY(QSslSocket::availableBackends().contains(backendName));
|
||||
QCOMPARE(QSslSocket::loadBackend(backendName), true);
|
||||
QCOMPARE(QSslSocket::activeBackend(), backendName);
|
||||
QCOMPARE(QSslSocket::loadBackend(backendName), true); // Already loaded, but not a fail.
|
||||
QCOMPARE(QSslSocket::activeBackend(), backendName);
|
||||
|
||||
const auto protocols = QSslSocket::supportedProtocols();
|
||||
QVERIFY(protocols.size() > 0);
|
||||
// 'Any' and 'Secure', since they are always present:
|
||||
QVERIFY(protocols.contains(QSsl::AnyProtocol));
|
||||
QVERIFY(protocols.contains(QSsl::SecureProtocols));
|
||||
|
||||
const auto protocolsForNamed = QSslSocket::supportedProtocols(backendName);
|
||||
QCOMPARE(protocols, protocolsForNamed);
|
||||
// Any and secure, new versions are coming, old
|
||||
// go away, nothing more specific.
|
||||
QVERIFY(protocolsForNamed.contains(QSsl::AnyProtocol));
|
||||
QVERIFY(protocolsForNamed.contains(QSsl::SecureProtocols));
|
||||
QCOMPARE(QSslSocket::isProtocolSupported(QSsl::SecureProtocols), true);
|
||||
QCOMPARE(QSslSocket::isProtocolSupported(QSsl::SecureProtocols, backendName), true);
|
||||
|
||||
const auto classes = QSslSocket::implementedClasses();
|
||||
QVERIFY(classes.contains(implemented));
|
||||
QVERIFY(QSslSocket::isClassImplemented(implemented));
|
||||
QVERIFY(QSslSocket::isClassImplemented(implemented, backendName));
|
||||
|
||||
const auto features = QSslSocket::supportedFeatures();
|
||||
QVERIFY(features.contains(QSsl::SupportedFeature(supportedFt)));
|
||||
QVERIFY(QSslSocket::isFeatureSupported(QSsl::SupportedFeature(supportedFt)));
|
||||
QVERIFY(QSslSocket::isFeatureSupported(QSsl::SupportedFeature(supportedFt), backendName));
|
||||
}
|
||||
|
||||
void tst_QSslSocket::init()
|
||||
|
|
|
|||
Loading…
Reference in New Issue