diff options
-rw-r--r-- | src/network/ssl/qsslsocket.cpp | 12 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_mac.cpp | 19 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_openssl.cpp | 20 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_schannel.cpp | 22 | ||||
-rw-r--r-- | src/network/ssl/qtlsbackend.cpp | 221 | ||||
-rw-r--r-- | src/network/ssl/qtlsbackend_p.h | 32 | ||||
-rw-r--r-- | tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp | 166 |
7 files changed, 208 insertions, 284 deletions
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index 0c231c1600..d2b386d024 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -1557,7 +1557,7 @@ QString QSslSocket::sslLibraryBuildVersionString() */ QList<QString> QSslSocket::availableBackends() { - return QTlsBackendFactory::availableBackendNames(); + return QTlsBackend::availableBackendNames(); } /*! @@ -1577,7 +1577,7 @@ QString QSslSocket::activeBackend() const QMutexLocker locker(&QSslSocketPrivate::backendMutex); if (!QSslSocketPrivate::activeBackendName.size()) - QSslSocketPrivate::activeBackendName = QTlsBackendFactory::defaultBackendName(); + QSslSocketPrivate::activeBackendName = QTlsBackend::defaultBackendName(); return QSslSocketPrivate::activeBackendName; } @@ -1610,7 +1610,7 @@ bool QSslSocket::setActiveBackend(const QString &backendName) return activeBackend() == backendName; } - if (!QTlsBackendFactory::availableBackendNames().contains(backendName)) { + if (!QTlsBackend::availableBackendNames().contains(backendName)) { qCWarning(lcSsl) << "Cannot set unavailable backend named" << backendName << "as active"; return false; @@ -1632,7 +1632,7 @@ bool QSslSocket::setActiveBackend(const QString &backendName) */ QList<QSsl::SslProtocol> QSslSocket::supportedProtocols(const QString &backendName) { - return QTlsBackendFactory::supportedProtocols(backendName.size() ? backendName : activeBackend()); + return QTlsBackend::supportedProtocols(backendName.size() ? backendName : activeBackend()); } /*! @@ -1658,7 +1658,7 @@ bool QSslSocket::isProtocolSupported(QSsl::SslProtocol protocol, const QString & */ QList<QSsl::ImplementedClass> QSslSocket::implementedClasses(const QString &backendName) { - return QTlsBackendFactory::implementedClasses(backendName.size() ? backendName : activeBackend()); + return QTlsBackend::implementedClasses(backendName.size() ? backendName : activeBackend()); } /*! @@ -1683,7 +1683,7 @@ bool QSslSocket::isClassImplemented(QSsl::ImplementedClass cl, const QString &ba */ QList<QSsl::SupportedFeature> QSslSocket::supportedFeatures(const QString &backendName) { - return QTlsBackendFactory::supportedFeatures(backendName.size() ? backendName : activeBackend()); + return QTlsBackend::supportedFeatures(backendName.size() ? backendName : activeBackend()); } /*! diff --git a/src/network/ssl/qsslsocket_mac.cpp b/src/network/ssl/qsslsocket_mac.cpp index abbcf8a6ac..6370a83dd3 100644 --- a/src/network/ssl/qsslsocket_mac.cpp +++ b/src/network/ssl/qsslsocket_mac.cpp @@ -84,20 +84,7 @@ class SecureTransportBackend : public QTlsBackend private: QString backendName() const override { - return QTlsBackendFactory::builtinBackendNames[QTlsBackendFactory::nameIndexSecureTransport]; - } -}; - -class SecureTransportBackendFactory : public QTlsBackendFactory -{ -private: - QString backendName() const override - { - return QTlsBackendFactory::builtinBackendNames[QTlsBackendFactory::nameIndexSecureTransport]; - } - QTlsBackend *create() const override - { - return new SecureTransportBackend; + return builtinBackendNames[nameIndexSecureTransport]; } QList<QSsl::SslProtocol> supportedProtocols() const override @@ -135,7 +122,7 @@ private: } }; -Q_GLOBAL_STATIC(SecureTransportBackendFactory, factory) +Q_GLOBAL_STATIC(SecureTransportBackend, backend) #ifdef Q_OS_MACOS /* @@ -1618,7 +1605,7 @@ void QSslSocketPrivate::registerAdHocFactory() { // TLSTODO: this is a temporary solution, waiting for // backends to move to ... plugins. - if (!factory()) + if (!backend()) qCWarning(lcSsl, "Failed to create backend factory"); } diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index 2f39b68002..e6efaca2d0 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -108,22 +108,8 @@ class OpenSSLBackend : public QTlsBackend private: QString backendName() const override { - return QTlsBackendFactory::builtinBackendNames[QTlsBackendFactory::nameIndexOpenSSL]; + return builtinBackendNames[nameIndexOpenSSL]; } -}; - -class OpenSSLBackendFactory : public QTlsBackendFactory -{ -private: - QString backendName() const override - { - return QTlsBackendFactory::builtinBackendNames[QTlsBackendFactory::nameIndexOpenSSL]; - } - QTlsBackend *create() const override - { - return new OpenSSLBackend; - } - QList<QSsl::SslProtocol> supportedProtocols() const override { QList<QSsl::SslProtocol> protocols; @@ -182,7 +168,7 @@ private: } }; -Q_GLOBAL_STATIC(OpenSSLBackendFactory, factory) +Q_GLOBAL_STATIC(OpenSSLBackend, backend) QSsl::AlertLevel tlsAlertLevel(int value) { @@ -2597,7 +2583,7 @@ void QSslSocketPrivate::registerAdHocFactory() { // TLSTODO: this is a temporary solution, waiting for // backends to move to ... plugins. - if (!factory()) + if (!backend()) qCWarning(lcSsl, "Failed to create backend factory"); } diff --git a/src/network/ssl/qsslsocket_schannel.cpp b/src/network/ssl/qsslsocket_schannel.cpp index ca9bad96b6..d36b1790e1 100644 --- a/src/network/ssl/qsslsocket_schannel.cpp +++ b/src/network/ssl/qsslsocket_schannel.cpp @@ -46,6 +46,7 @@ #include "qsslcertificateextension.h" #include "qsslcertificate_p.h" #include "qsslcipher_p.h" +#include "qtlsbackend_p.h" #include <QtCore/qscopeguard.h> #include <QtCore/qoperatingsystemversion.h> @@ -163,21 +164,7 @@ class SchannelBackend : public QTlsBackend private: QString backendName() const override { - return QTlsBackendFactory::builtinBackendNames[QTlsBackendFactory::nameIndexSchannel]; - } -}; - -bool supportsTls13(); -class SchannelBackendFactory : public QTlsBackendFactory -{ -private: - QString backendName() const override - { - return QTlsBackendFactory::builtinBackendNames[QTlsBackendFactory::nameIndexSchannel]; - } - QTlsBackend *create() const override - { - return new SchannelBackend; + return builtinBackendNames[nameIndexSchannel]; } QList<QSsl::SslProtocol> supportedProtocols() const override @@ -223,8 +210,7 @@ private: } }; -Q_GLOBAL_STATIC(SchannelBackendFactory, factory); - +Q_GLOBAL_STATIC(SchannelBackend, backend) SecBuffer createSecBuffer(void *ptr, unsigned long length, unsigned long bufferType) { @@ -2217,7 +2203,7 @@ void QSslSocketPrivate::registerAdHocFactory() { // TLSTODO: this is a temporary solution, waiting for // backends to move to ... plugins. - if (!factory()) + if (!backend()) qCWarning(lcSsl, "Failed to create backend factory"); } diff --git a/src/network/ssl/qtlsbackend.cpp b/src/network/ssl/qtlsbackend.cpp index 4183c1e2f1..4c726a5b5d 100644 --- a/src/network/ssl/qtlsbackend.cpp +++ b/src/network/ssl/qtlsbackend.cpp @@ -51,99 +51,28 @@ QT_BEGIN_NAMESPACE Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, - (QTlsBackendFactory_iid, QStringLiteral("/tlsbackends"))) - -const QString QTlsBackendFactory::builtinBackendNames[] = { - QStringLiteral("schannel"), - QStringLiteral("securetransport"), - QStringLiteral("openssl") -}; - - -QTlsBackend::QTlsBackend() = default; -QTlsBackend::~QTlsBackend() = default; - -const QString dummyName = QStringLiteral("dummyTLS"); - -QString QTlsBackend::backendName() const -{ - return dummyName; -} - -QSsl::TlsKey *QTlsBackend::createKey() const -{ - qCWarning(lcSsl, "Dummy TLS backend, cannot generate a key"); - return nullptr; -} - -QSsl::X509Certificate *QTlsBackend::createCertificate() const -{ - qCWarning(lcSsl, "Dummy TLS backend, cannot create a certificate"); - return nullptr; -} - -QSsl::TlsCryptograph *QTlsBackend::createTlsCryptograph() const -{ - qCWarning(lcSsl, "Dummy TLS backend, cannot create TLS session"); - return nullptr; -} - -QSsl::DtlsCryptograph *QTlsBackend::createDtlsCryptograph() const -{ - qCWarning(lcSsl, "Dummy TLS backend, cannot create DTLS session"); - return nullptr; -} - -QSsl::DtlsCookieVerifier *QTlsBackend::createDtlsCookieVerifier() const -{ - qCWarning(lcSsl, "Dummy TLS backend, cannot create DTLS cookie generator/verifier"); - return nullptr; -} - -QSsl::X509ChainVerifyPtr QTlsBackend::X509Verifier() const -{ - qCWarning(lcSsl, "Dummy TLS backend, cannot verify X509 chain"); - return nullptr; -} - -QSsl::X509PemReaderPtr QTlsBackend::X509PemReader() const -{ - qCWarning(lcSsl, "Dummy TLS backend, cannot read PEM format"); - return nullptr; -} - -QSsl::X509DerReaderPtr QTlsBackend::X509DerReader() const -{ - qCWarning(lcSsl, "Dummy TLS backend, don't know how to read DER"); - return nullptr; -} - -QSsl::X509Pkcs12ReaderPtr QTlsBackend::X509Pkcs12Reader() const -{ - qCWarning(lcSsl, "Dummy TLS backend, cannot read PKCS12"); - return nullptr; -} + (QTlsBackend_iid, QStringLiteral("/tlsbackends"))) namespace { -class BackEndFactoryCollection +class BackendCollection { public: - void addFactory(QTlsBackendFactory *newFactory) + void addBackend(QTlsBackend *backend) { - Q_ASSERT(newFactory); - Q_ASSERT(std::find(backendFactories.begin(), backendFactories.end(), newFactory) == backendFactories.end()); + Q_ASSERT(backend); + Q_ASSERT(std::find(backends.begin(), backends.end(), backend) == backends.end()); const QMutexLocker locker(&collectionMutex); - backendFactories.push_back(newFactory); + backends.push_back(backend); } - void removeFactory(QTlsBackendFactory *factory) + void removeBackend(QTlsBackend *backend) { - Q_ASSERT(factory); + Q_ASSERT(backend); const QMutexLocker locker(&collectionMutex); - const auto it = std::find(backendFactories.begin(), backendFactories.end(), factory); - Q_ASSERT(it != backendFactories.end()); - backendFactories.erase(it); + const auto it = std::find(backends.begin(), backends.end(), backend); + Q_ASSERT(it != backends.end()); + backends.erase(it); } bool tryPopulateCollection() @@ -176,64 +105,124 @@ public: return names; const QMutexLocker locker(&collectionMutex); - if (!backendFactories.size()) + if (!backends.size()) return names; - names.reserve(backendFactories.size()); - for (const auto *factory : backendFactories) + names.reserve(backends.size()); + for (const auto *factory : backends) names.append(factory->backendName()); return names; } - QTlsBackendFactory *factory(const QString &name) + QTlsBackend *backend(const QString &name) { if (!tryPopulateCollection()) return nullptr; const QMutexLocker locker(&collectionMutex); - const auto it = std::find_if(backendFactories.begin(), backendFactories.end(), + const auto it = std::find_if(backends.begin(), backends.end(), [&name](const auto *fct) {return fct->backendName() == name;}); - return it == backendFactories.end() ? nullptr : *it; + return it == backends.end() ? nullptr : *it; } private: - std::vector<QTlsBackendFactory *> backendFactories; + std::vector<QTlsBackend *> backends; QMutex collectionMutex; bool loaded = false; }; -Q_GLOBAL_STATIC(BackEndFactoryCollection, factories); +} // Unnamed namespace + +Q_GLOBAL_STATIC(BackendCollection, backends); + +const QString QTlsBackend::builtinBackendNames[] = { + QStringLiteral("schannel"), + QStringLiteral("securetransport"), + QStringLiteral("openssl") +}; + +QTlsBackend::QTlsBackend() +{ + if (backends()) + backends->addBackend(this); +} + +QTlsBackend::~QTlsBackend() +{ + if (backends()) + backends->removeBackend(this); +} + +QString QTlsBackend::backendName() const +{ + return QStringLiteral("dummyTLS"); +} -} // unnamed namespace +QSsl::TlsKey *QTlsBackend::createKey() const +{ + qCWarning(lcSsl, "Dummy TLS backend, cannot generate a key"); + return nullptr; +} -QTlsBackendFactory::QTlsBackendFactory() +QSsl::X509Certificate *QTlsBackend::createCertificate() const { - if (factories()) - factories->addFactory(this); + qCWarning(lcSsl, "Dummy TLS backend, cannot create a certificate"); + return nullptr; } -QTlsBackendFactory::~QTlsBackendFactory() +QSsl::TlsCryptograph *QTlsBackend::createTlsCryptograph() const { - if (factories()) - factories->removeFactory(this); + qCWarning(lcSsl, "Dummy TLS backend, cannot create TLS session"); + return nullptr; } -QString QTlsBackendFactory::backendName() const +QSsl::DtlsCryptograph *QTlsBackend::createDtlsCryptograph() const { - return dummyName; + qCWarning(lcSsl, "Dummy TLS backend, cannot create DTLS session"); + return nullptr; +} + +QSsl::DtlsCookieVerifier *QTlsBackend::createDtlsCookieVerifier() const +{ + qCWarning(lcSsl, "Dummy TLS backend, cannot create DTLS cookie generator/verifier"); + return nullptr; +} + +QSsl::X509ChainVerifyPtr QTlsBackend::X509Verifier() const +{ + qCWarning(lcSsl, "Dummy TLS backend, cannot verify X509 chain"); + return nullptr; +} + +QSsl::X509PemReaderPtr QTlsBackend::X509PemReader() const +{ + qCWarning(lcSsl, "Dummy TLS backend, cannot read PEM format"); + return nullptr; +} + +QSsl::X509DerReaderPtr QTlsBackend::X509DerReader() const +{ + qCWarning(lcSsl, "Dummy TLS backend, don't know how to read DER"); + return nullptr; +} + +QSsl::X509Pkcs12ReaderPtr QTlsBackend::X509Pkcs12Reader() const +{ + qCWarning(lcSsl, "Dummy TLS backend, cannot read PKCS12"); + return nullptr; } -QList<QString> QTlsBackendFactory::availableBackendNames() +QList<QString> QTlsBackend::availableBackendNames() { - if (!factories()) + if (!backends()) return {}; - return factories->backendNames(); + return backends->backendNames(); } -QString QTlsBackendFactory::defaultBackendName() +QString QTlsBackend::defaultBackendName() { // We prefer native as default: const auto names = availableBackendNames(); @@ -250,46 +239,46 @@ QString QTlsBackendFactory::defaultBackendName() return {}; } -QTlsBackend *QTlsBackendFactory::create(const QString &backendName) +QTlsBackend *QTlsBackend::findBackend(const QString &backendName) { - if (!factories()) + if (!backends()) return {}; - if (const auto *fct = factories->factory(backendName)) - return fct->create(); + if (auto *fct = backends->backend(backendName)) + return fct; qCWarning(lcSsl) << "Cannot create unknown backend named" << backendName; return nullptr; } -QList<QSsl::SslProtocol> QTlsBackendFactory::supportedProtocols(const QString &backendName) +QList<QSsl::SslProtocol> QTlsBackend::supportedProtocols(const QString &backendName) { - if (!factories()) + if (!backends()) return {}; - if (const auto *fct = factories->factory(backendName)) + if (const auto *fct = backends->backend(backendName)) return fct->supportedProtocols(); return {}; } -QList<QSsl::SupportedFeature> QTlsBackendFactory::supportedFeatures(const QString &backendName) +QList<QSsl::SupportedFeature> QTlsBackend::supportedFeatures(const QString &backendName) { - if (!factories()) + if (!backends()) return {}; - if (const auto *fct = factories->factory(backendName)) + if (const auto *fct = backends->backend(backendName)) return fct->supportedFeatures(); return {}; } -QList<QSsl::ImplementedClass> QTlsBackendFactory::implementedClasses(const QString &backendName) +QList<QSsl::ImplementedClass> QTlsBackend::implementedClasses(const QString &backendName) { - if (!factories()) + if (!backends()) return {}; - if (const auto *fct = factories->factory(backendName)) + if (const auto *fct = backends->backend(backendName)) return fct->implementedClasses(); return {}; diff --git a/src/network/ssl/qtlsbackend_p.h b/src/network/ssl/qtlsbackend_p.h index 9c4f2d3eb8..4650848a53 100644 --- a/src/network/ssl/qtlsbackend_p.h +++ b/src/network/ssl/qtlsbackend_p.h @@ -107,8 +107,6 @@ class DtlsCookieVerifier; // Factory, creating back-end specific implementations of // different entities QSslSocket is using. -// TLSTODO: consider merging with ... it's own factory -// below, no real benefit in having this split. class Q_NETWORK_EXPORT QTlsBackend : public QObject { Q_OBJECT @@ -116,7 +114,10 @@ public: QTlsBackend(); ~QTlsBackend() override; - virtual QString backendName() const; + virtual QString backendName() const = 0; + virtual QList<QSsl::SslProtocol> supportedProtocols() const = 0; + virtual QList<QSsl::SupportedFeature> supportedFeatures() const = 0; + virtual QList<QSsl::ImplementedClass> implementedClasses() const = 0; // X509 and keys: virtual QSsl::TlsKey *createKey() const; @@ -133,26 +134,9 @@ public: virtual QSsl::X509DerReaderPtr X509DerReader() const; virtual QSsl::X509Pkcs12ReaderPtr X509Pkcs12Reader() const; - Q_DISABLE_COPY_MOVE(QTlsBackend) -}; - -// Factory for a backend. -class Q_NETWORK_EXPORT QTlsBackendFactory : public QObject -{ - Q_OBJECT -public: - QTlsBackendFactory(); - ~QTlsBackendFactory() override; - - virtual QString backendName() const = 0; - virtual QTlsBackend *create() const = 0; - virtual QList<QSsl::SslProtocol> supportedProtocols() const = 0; - virtual QList<QSsl::SupportedFeature> supportedFeatures() const = 0; - virtual QList<QSsl::ImplementedClass> implementedClasses() const = 0; - static QList<QString> availableBackendNames(); static QString defaultBackendName(); - static QTlsBackend *create(const QString &backendName); + static QTlsBackend *findBackend(const QString &backendName); static QList<QSsl::SslProtocol> supportedProtocols(const QString &backendName); static QList<QSsl::SupportedFeature> supportedFeatures(const QString &backendName); @@ -165,11 +149,11 @@ public: static const QString builtinBackendNames[]; - Q_DISABLE_COPY_MOVE(QTlsBackendFactory) + Q_DISABLE_COPY_MOVE(QTlsBackend) }; -#define QTlsBackendFactory_iid "org.qt-project.Qt.QTlsBackendFactory" -Q_DECLARE_INTERFACE(QTlsBackendFactory, QTlsBackendFactory_iid); +#define QTlsBackend_iid "org.qt-project.Qt.QTlsBackend" +Q_DECLARE_INTERFACE(QTlsBackend, QTlsBackend_iid); QT_END_NAMESPACE diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp index bb77668b81..f9790e8597 100644 --- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp +++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp @@ -165,6 +165,7 @@ public slots: #ifndef QT_NO_SSL private slots: + void activeBackend(); void backends(); void constructing(); void configNoOnDemandLoad(); @@ -438,54 +439,6 @@ 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. - - // Before we tried to load anything, the active is the same thing as the default one: - QCOMPARE(QSslSocket::activeBackend(), QTlsBackendFactory::defaultBackendName()); - - const QString nonExistingBackend = QStringLiteral("TheQtTLS"); - QCOMPARE(QSslSocket::setActiveBackend(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::setActiveBackend(backendName), true); - QCOMPARE(QSslSocket::activeBackend(), backendName); - QCOMPARE(QSslSocket::setActiveBackend(backendName), true); // We can do it again. - 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() @@ -564,19 +517,62 @@ void tst_QSslSocket::proxyAuthenticationRequired(const QNetworkProxy &, QAuthent #ifndef QT_NO_SSL -struct MockTlsBackend : QTlsBackend +void tst_QSslSocket::activeBackend() { - MockTlsBackend(const QString &n) : name(n) {} - QString backendName() const override - { - return name; - } - QString name; -}; + QFETCH_GLOBAL(const bool, setProxy); + if (setProxy) // Not interesting for backend test. + return; -struct MockTlsFactory : QTlsBackendFactory + QCOMPARE(QSslSocket::activeBackend(), QTlsBackend::defaultBackendName()); + + // We cannot set non-existing as active: + const QString nonExistingBackend = QStringLiteral("TheQtTLS"); + QCOMPARE(QSslSocket::setActiveBackend(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::setActiveBackend(backendName), true); + QCOMPARE(QSslSocket::activeBackend(), backendName); + QCOMPARE(QSslSocket::setActiveBackend(backendName), true); // We can do it again. + 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)); +} + +namespace { +struct MockTlsBackend : QTlsBackend { - MockTlsFactory(const QString &mockName) : name(mockName) + MockTlsBackend(const QString &mockName) : name(mockName) { } QString backendName() const override @@ -596,26 +592,24 @@ struct MockTlsFactory : QTlsBackendFactory { return classes; } - QTlsBackend *create() const override - { - auto tls = new MockTlsBackend(name); - return tls; - } + QString name; QList<QSsl::ImplementedClass> classes; QList<QSsl::SupportedFeature> features; QList<QSsl::SslProtocol> protocols; }; +} // Unnamed backend. + void tst_QSslSocket::backends() { QFETCH_GLOBAL(const bool, setProxy); - if (setProxy) - QSKIP("Proxy is not interesting for backend test"); + if (setProxy) // Not interesting for backend test. + return; // We are here, protected by !QT_NO_SSL. Some backend must be pre-existing. // Let's test the 'real' backend: - auto backendNames = QTlsBackendFactory::availableBackendNames(); + auto backendNames = QTlsBackend::availableBackendNames(); const auto sizeBefore = backendNames.size(); QVERIFY(sizeBefore > 0); @@ -628,11 +622,9 @@ void tst_QSslSocket::backends() const auto builtinFeatures = QSslSocket::supportedFeatures(builtinBackend); QVERIFY(builtinFeatures.contains(QSsl::SupportedFeature::ClientSideAlpn)); - { - // Verify that non-dummy backend can be created (and delete it): - const std::unique_ptr<QTlsBackend> systemBackend(QTlsBackendFactory::create(backendNames.first())); - QVERIFY(systemBackend.get()); - } + // Verify that non-dummy backend can be created (and delete it): + auto *systemBackend = QTlsBackend::findBackend(builtinBackend); + QVERIFY(systemBackend); const auto protocols = QList<QSsl::SslProtocol>{QSsl::SecureProtocols}; const auto classes = QList<QSsl::ImplementedClass>{QSsl::ImplementedClass::Socket}; @@ -646,12 +638,16 @@ void tst_QSslSocket::backends() QVERIFY(!backendNames.contains(nameB)); QVERIFY(!backendNames.contains(nonExisting)); { - MockTlsFactory factoryA(nameA); - backendNames = QTlsBackendFactory::availableBackendNames(); + MockTlsBackend factoryA(nameA); + backendNames = QTlsBackend::availableBackendNames(); QVERIFY(backendNames.contains(nameA)); QVERIFY(!backendNames.contains(nameB)); QVERIFY(!backendNames.contains(nonExisting)); + const auto *backendA = QTlsBackend::findBackend(nameA); + QVERIFY(backendA); + QCOMPARE(backendA->backendName(), nameA); + QCOMPARE(factoryA.supportedFeatures().size(), 0); QCOMPARE(factoryA.supportedProtocols().size(), 0); QCOMPARE(factoryA.implementedClasses().size(), 0); @@ -666,23 +662,19 @@ void tst_QSslSocket::backends() QCOMPARE(factoryA.implementedClasses(), classes); // That's a helper function (static member function): - QCOMPARE(QTlsBackendFactory::supportedProtocols(nameA), protocols); - QCOMPARE(QTlsBackendFactory::supportedFeatures(nameA), features); - QCOMPARE(QTlsBackendFactory::implementedClasses(nameA), classes); - - MockTlsFactory factoryB(nameB); - QVERIFY(QTlsBackendFactory::availableBackendNames().contains(nameA)); - QVERIFY(QTlsBackendFactory::availableBackendNames().contains(nameB)); - QVERIFY(!QTlsBackendFactory::availableBackendNames().contains(nonExisting)); + QCOMPARE(QTlsBackend::supportedProtocols(nameA), protocols); + QCOMPARE(QTlsBackend::supportedFeatures(nameA), features); + QCOMPARE(QTlsBackend::implementedClasses(nameA), classes); - const std::unique_ptr<QTlsBackend> backendA(QTlsBackendFactory::create(nameA)); - QVERIFY(backendA.get()); - QCOMPARE(backendA->backendName(), nameA); + MockTlsBackend factoryB(nameB); + QVERIFY(QTlsBackend::availableBackendNames().contains(nameA)); + QVERIFY(QTlsBackend::availableBackendNames().contains(nameB)); + QVERIFY(!QTlsBackend::availableBackendNames().contains(nonExisting)); - const std::unique_ptr<QTlsBackend> nullBackend(QTlsBackendFactory::create(nonExisting)); - QCOMPARE(nullBackend.get(), nullptr); + const auto *nullBackend = QTlsBackend::findBackend(nonExisting); + QCOMPARE(nullBackend, nullptr); } - backendNames = QTlsBackendFactory::availableBackendNames(); + backendNames = QTlsBackend::availableBackendNames(); QCOMPARE(backendNames.size(), sizeBefore); // Check we cleaned up our factories: QVERIFY(!backendNames.contains(nameA)); |