summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Schmertmann <Lars.Schmertmann@governikus.de>2017-05-23 14:47:14 +0200
committerLars Schmertmann <lars.schmertmann@governikus.de>2018-01-26 11:34:02 +0000
commitf55c73ede28d4455f555a28e401407326ac9b954 (patch)
treec6c0836be78ba465051225cd38e7ec602aeeec8b
parentdcfb6f9d18beb397517ecc31ad462f1f4ebb8859 (diff)
Introduce QSslConfiguration::backendConfig
With this change it is possible to use all supported configurations in different backends without any new interfaces. Change-Id: Ib233539a970681d30ae3907258730e491f8d3531 Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
-rw-r--r--src/network/ssl/qsslconfiguration.cpp56
-rw-r--r--src/network/ssl/qsslconfiguration.h5
-rw-r--r--src/network/ssl/qsslconfiguration_p.h3
-rw-r--r--src/network/ssl/qsslcontext_openssl.cpp71
-rw-r--r--src/network/ssl/qsslcontext_openssl11.cpp4
-rw-r--r--src/network/ssl/qsslcontext_openssl_p.h1
-rw-r--r--src/network/ssl/qsslcontext_opensslpre11.cpp4
-rw-r--r--src/network/ssl/qsslsocket.cpp2
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols.cpp16
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols_p.h8
-rw-r--r--tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp130
11 files changed, 300 insertions, 0 deletions
diff --git a/src/network/ssl/qsslconfiguration.cpp b/src/network/ssl/qsslconfiguration.cpp
index 75a880f115..cbbbac85fe 100644
--- a/src/network/ssl/qsslconfiguration.cpp
+++ b/src/network/ssl/qsslconfiguration.cpp
@@ -221,6 +221,7 @@ bool QSslConfiguration::operator==(const QSslConfiguration &other) const
d->peerVerifyMode == other.d->peerVerifyMode &&
d->peerVerifyDepth == other.d->peerVerifyDepth &&
d->allowRootCertOnDemandLoading == other.d->allowRootCertOnDemandLoading &&
+ d->backendConfig == other.d->backendConfig &&
d->sslOptions == other.d->sslOptions &&
d->sslSession == other.d->sslSession &&
d->sslSessionTicketLifeTimeHint == other.d->sslSessionTicketLifeTimeHint &&
@@ -263,6 +264,7 @@ bool QSslConfiguration::isNull() const
d->privateKey.isNull() &&
d->peerCertificate.isNull() &&
d->peerCertificateChain.count() == 0 &&
+ d->backendConfig.isEmpty() &&
d->sslOptions == QSslConfigurationPrivate::defaultSslOptions &&
d->sslSession.isNull() &&
d->sslSessionTicketLifeTimeHint == -1 &&
@@ -870,6 +872,60 @@ void QSslConfiguration::setDiffieHellmanParameters(const QSslDiffieHellmanParame
}
/*!
+ \since 5.11
+
+ Returns the backend-specific configuration.
+
+ Only options set by addBackendConfig() or setBackendConfig() will be
+ returned. The internal standard configuration of the backend is not reported.
+
+ \sa setBackendConfigOption(), setBackendConfig()
+ */
+QMap<QByteArray, QVariant> QSslConfiguration::backendConfig() const
+{
+ return d->backendConfig;
+}
+
+/*!
+ \since 5.11
+
+ Sets an option in the backend-specific configuration.
+
+ Options supported by the OpenSSL (>= 1.0.2) backend are available in the \l
+ {https://www.openssl.org/docs/manmaster/man3/SSL_CONF_cmd.html#SUPPORTED-CONFIGURATION-FILE-COMMANDS}
+ {supported configuration file commands} documentation. The expected type for
+ the \a value parameter is a QByteArray for all options. The \l
+ {https://www.openssl.org/docs/manmaster/man3/SSL_CONF_cmd.html#EXAMPLES}{examples}
+ show how to use some of the options.
+
+ \note The backend-specific configuration will be applied after the general
+ configuration. Using the backend-specific configuration to set a general
+ configuration option again will overwrite the general configuration option.
+
+ \sa backendConfig(), setBackendConfig()
+ */
+void QSslConfiguration::setBackendConfigOption(const QByteArray &name, const QVariant &value)
+{
+ d->backendConfig[name] = value;
+}
+
+/*!
+ \since 5.11
+
+ Sets or clears the backend-specific configuration.
+
+ Without a \a backendConfig parameter this function will clear the
+ backend-specific configuration. More information about the supported
+ options is available in the documentation of addBackendConfig().
+
+ \sa backendConfig(), setBackendConfigOption()
+ */
+void QSslConfiguration::setBackendConfig(const QMap<QByteArray, QVariant> &backendConfig)
+{
+ d->backendConfig = backendConfig;
+}
+
+/*!
\since 5.3
This function returns the protocol negotiated with the server
diff --git a/src/network/ssl/qsslconfiguration.h b/src/network/ssl/qsslconfiguration.h
index 1c57bebd65..b3264126dd 100644
--- a/src/network/ssl/qsslconfiguration.h
+++ b/src/network/ssl/qsslconfiguration.h
@@ -57,6 +57,7 @@
#define QSSLCONFIGURATION_H
#include <QtNetwork/qtnetworkglobal.h>
+#include <QtCore/qmap.h>
#include <QtCore/qshareddata.h>
#include <QtNetwork/qsslsocket.h>
#include <QtNetwork/qssl.h>
@@ -149,6 +150,10 @@ public:
QSslDiffieHellmanParameters diffieHellmanParameters() const;
void setDiffieHellmanParameters(const QSslDiffieHellmanParameters &dhparams);
+ QMap<QByteArray, QVariant> backendConfig() const;
+ void setBackendConfigOption(const QByteArray &name, const QVariant &value);
+ void setBackendConfig(const QMap<QByteArray, QVariant> &backendConfig = QMap<QByteArray, QVariant>());
+
static QSslConfiguration defaultConfiguration();
static void setDefaultConfiguration(const QSslConfiguration &configuration);
diff --git a/src/network/ssl/qsslconfiguration_p.h b/src/network/ssl/qsslconfiguration_p.h
index 6adf2c9b54..38a98239db 100644
--- a/src/network/ssl/qsslconfiguration_p.h
+++ b/src/network/ssl/qsslconfiguration_p.h
@@ -67,6 +67,7 @@
// We mean it.
//
+#include <QtCore/qmap.h>
#include <QtNetwork/private/qtnetworkglobal_p.h>
#include "qsslconfiguration.h"
#include "qlist.h"
@@ -123,6 +124,8 @@ public:
QSslDiffieHellmanParameters dhParams;
+ QMap<QByteArray, QVariant> backendConfig;
+
QByteArray sslSession;
int sslSessionTicketLifeTimeHint;
diff --git a/src/network/ssl/qsslcontext_openssl.cpp b/src/network/ssl/qsslcontext_openssl.cpp
index cef503710c..386c280659 100644
--- a/src/network/ssl/qsslcontext_openssl.cpp
+++ b/src/network/ssl/qsslcontext_openssl.cpp
@@ -49,6 +49,11 @@
QT_BEGIN_NAMESPACE
+static inline QString msgErrorSettingBackendConfig(const QString &why)
+{
+ return QSslSocket::tr("Error when setting the OpenSSL configuration (%1)").arg(why);
+}
+
QSslContext::QSslContext()
: ctx(0),
pkey(0),
@@ -237,4 +242,70 @@ QString QSslContext::errorString() const
return errorStr;
}
+// static
+void QSslContext::applyBackendConfig(QSslContext *sslContext)
+{
+ if (sslContext->sslConfiguration.backendConfig().isEmpty())
+ return;
+
+#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);
+
+ const auto &backendConfig = sslContext->sslConfiguration.backendConfig();
+ for (auto i = backendConfig.constBegin(); i != backendConfig.constEnd(); ++i) {
+ 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;
+
+ 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;
+ }
+ }
+
+ 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;
+ }
+ } else
+#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
+ {
+ // specific algorithms requested, but not possible to set
+ sslContext->errorCode = QSslError::UnspecifiedError;
+ sslContext->errorStr = msgErrorSettingBackendConfig(
+ QSslSocket::tr("OpenSSL version too old, need at least v1.0.2"));
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/network/ssl/qsslcontext_openssl11.cpp b/src/network/ssl/qsslcontext_openssl11.cpp
index 787b6ae3f5..7be7be46b8 100644
--- a/src/network/ssl/qsslcontext_openssl11.cpp
+++ b/src/network/ssl/qsslcontext_openssl11.cpp
@@ -260,6 +260,7 @@ init_context:
#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;
@@ -269,9 +270,12 @@ init_context:
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
diff --git a/src/network/ssl/qsslcontext_openssl_p.h b/src/network/ssl/qsslcontext_openssl_p.h
index 06a31af5e5..48beebf134 100644
--- a/src/network/ssl/qsslcontext_openssl_p.h
+++ b/src/network/ssl/qsslcontext_openssl_p.h
@@ -107,6 +107,7 @@ protected:
private:
static void initSslContext(QSslContext* sslContext, QSslSocket::SslMode mode, const QSslConfiguration &configuration,
bool allowRootCertOnDemandLoading);
+ static void applyBackendConfig(QSslContext *sslContext);
private:
SSL_CTX* ctx;
diff --git a/src/network/ssl/qsslcontext_opensslpre11.cpp b/src/network/ssl/qsslcontext_opensslpre11.cpp
index 9c01c2f2dc..eea821804f 100644
--- a/src/network/ssl/qsslcontext_opensslpre11.cpp
+++ b/src/network/ssl/qsslcontext_opensslpre11.cpp
@@ -340,6 +340,7 @@ init_context:
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)
@@ -347,8 +348,11 @@ init_context:
// 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
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index 9f07b53e4b..833d676192 100644
--- a/src/network/ssl/qsslsocket.cpp
+++ b/src/network/ssl/qsslsocket.cpp
@@ -922,6 +922,7 @@ void QSslSocket::setSslConfiguration(const QSslConfiguration &configuration)
d->configuration.peerVerifyDepth = configuration.peerVerifyDepth();
d->configuration.peerVerifyMode = configuration.peerVerifyMode();
d->configuration.protocol = configuration.protocol();
+ d->configuration.backendConfig = configuration.backendConfig();
d->configuration.sslOptions = configuration.d->sslOptions;
d->configuration.sslSession = configuration.sessionTicket();
d->configuration.sslSessionTicketLifeTimeHint = configuration.sessionTicketLifeTimeHint();
@@ -2256,6 +2257,7 @@ void QSslConfigurationPrivate::deepCopyDefaultConfiguration(QSslConfigurationPri
ptr->peerVerifyDepth = global->peerVerifyDepth;
ptr->sslOptions = global->sslOptions;
ptr->ellipticCurves = global->ellipticCurves;
+ ptr->backendConfig = global->backendConfig;
}
/*!
diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp
index 1b73135935..9bb67771fd 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols.cpp
+++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp
@@ -402,6 +402,14 @@ 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 0, return)
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
+DEFINEFUNC(SSL_CONF_CTX *, SSL_CONF_CTX_new, DUMMYARG, DUMMYARG, return 0, 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 0, return)
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
@@ -1105,6 +1113,14 @@ 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)
diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h
index 4cad0231cd..be67f38b64 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols_p.h
+++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h
@@ -352,6 +352,14 @@ 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);
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
index 01a7465564..f77afd2364 100644
--- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
+++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
@@ -238,6 +238,8 @@ private slots:
void allowedProtocolNegotiation();
void pskServer();
void forwardReadChannelFinished();
+ void signatureAlgorithm_data();
+ void signatureAlgorithm();
#endif
void setEmptyDefaultConfiguration(); // this test should be last
@@ -3908,6 +3910,134 @@ void tst_QSslSocket::pskServer()
QCOMPARE(disconnectedSpy.count(), 1);
}
+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");
+
+ QTest::addColumn<QByteArrayList>("serverSigAlgPairs");
+ QTest::addColumn<QSsl::SslProtocol>("serverProtocol");
+ QTest::addColumn<QByteArrayList>("clientSigAlgPairs");
+ QTest::addColumn<QSsl::SslProtocol>("clientProtocol");
+ QTest::addColumn<QAbstractSocket::SocketState>("state");
+
+ const QByteArray dsaSha1("DSA+SHA1");
+ const QByteArray ecdsaSha1("ECDSA+SHA1");
+ const QByteArray ecdsaSha512("ECDSA+SHA512");
+ const QByteArray rsaSha256("RSA+SHA256");
+ const QByteArray rsaSha384("RSA+SHA384");
+ const QByteArray rsaSha512("RSA+SHA512");
+
+ QTest::newRow("match_TlsV1_2")
+ << QByteArrayList({rsaSha256})
+ << QSsl::TlsV1_2
+ << QByteArrayList({rsaSha256})
+ << QSsl::AnyProtocol
+ << QAbstractSocket::ConnectedState;
+ QTest::newRow("no_hashalg_match_TlsV1_2")
+ << QByteArrayList({rsaSha256})
+ << QSsl::TlsV1_2
+ << QByteArrayList({rsaSha512})
+ << QSsl::AnyProtocol
+ << QAbstractSocket::UnconnectedState;
+ QTest::newRow("no_sigalg_match_TlsV1_2")
+ << QByteArrayList({ecdsaSha512})
+ << QSsl::TlsV1_2
+ << QByteArrayList({rsaSha512})
+ << QSsl::AnyProtocol
+ << QAbstractSocket::UnconnectedState;
+ QTest::newRow("no_cipher_match_AnyProtocol")
+ << QByteArrayList({rsaSha512})
+ << QSsl::AnyProtocol
+ << QByteArrayList({ecdsaSha512})
+ << QSsl::AnyProtocol
+ << QAbstractSocket::UnconnectedState;
+ QTest::newRow("match_multiple-choice")
+ << QByteArrayList({dsaSha1, rsaSha256, rsaSha384, rsaSha512})
+ << QSsl::AnyProtocol
+ << QByteArrayList({ecdsaSha1, rsaSha384, rsaSha512, ecdsaSha512})
+ << QSsl::AnyProtocol
+ << QAbstractSocket::ConnectedState;
+ QTest::newRow("match_client_longer")
+ << QByteArrayList({dsaSha1, rsaSha256})
+ << QSsl::AnyProtocol
+ << QByteArrayList({ecdsaSha1, ecdsaSha512, rsaSha256})
+ << QSsl::AnyProtocol
+ << QAbstractSocket::ConnectedState;
+ QTest::newRow("match_server_longer")
+ << QByteArrayList({ecdsaSha1, ecdsaSha512, rsaSha256})
+ << QSsl::AnyProtocol
+ << QByteArrayList({dsaSha1, rsaSha256})
+ << QSsl::AnyProtocol
+ << QAbstractSocket::ConnectedState;
+
+ // signature algorithms do not match, but are ignored because the tls version is not v1.2
+ QTest::newRow("client_ignore_TlsV1_1")
+ << QByteArrayList({rsaSha256})
+ << QSsl::TlsV1_1
+ << QByteArrayList({rsaSha512})
+ << QSsl::AnyProtocol
+ << QAbstractSocket::ConnectedState;
+ QTest::newRow("server_ignore_TlsV1_1")
+ << QByteArrayList({rsaSha256})
+ << QSsl::AnyProtocol
+ << QByteArrayList({rsaSha512})
+ << QSsl::TlsV1_1
+ << QAbstractSocket::ConnectedState;
+ QTest::newRow("client_ignore_TlsV1_0")
+ << QByteArrayList({rsaSha256})
+ << QSsl::TlsV1_0
+ << QByteArrayList({rsaSha512})
+ << QSsl::AnyProtocol
+ << QAbstractSocket::ConnectedState;
+ QTest::newRow("server_ignore_TlsV1_0")
+ << QByteArrayList({rsaSha256})
+ << QSsl::AnyProtocol
+ << QByteArrayList({rsaSha512})
+ << QSsl::TlsV1_0
+ << QAbstractSocket::ConnectedState;
+}
+
+void tst_QSslSocket::signatureAlgorithm()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ QSKIP("Test not adapted for use with proxying");
+
+ QFETCH(QByteArrayList, serverSigAlgPairs);
+ QFETCH(QSsl::SslProtocol, serverProtocol);
+ QFETCH(QByteArrayList, clientSigAlgPairs);
+ QFETCH(QSsl::SslProtocol, clientProtocol);
+ QFETCH(QAbstractSocket::SocketState, state);
+
+ SslServer server;
+ server.protocol = serverProtocol;
+ server.config.setCiphers({QSslCipher("ECDHE-RSA-AES256-SHA")});
+ server.config.setBackendConfigOption(QByteArrayLiteral("SignatureAlgorithms"), serverSigAlgPairs.join(':'));
+ QVERIFY(server.listen());
+
+ QSslConfiguration clientConfig = QSslConfiguration::defaultConfiguration();
+ clientConfig.setProtocol(clientProtocol);
+ clientConfig.setBackendConfigOption(QByteArrayLiteral("SignatureAlgorithms"), clientSigAlgPairs.join(':'));
+ QSslSocket client;
+ client.setSslConfiguration(clientConfig);
+ socket = &client;
+
+ QEventLoop loop;
+ QTimer::singleShot(5000, &loop, &QEventLoop::quit);
+ connect(socket, QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error), &loop, &QEventLoop::quit);
+ connect(socket, QOverload<const QList<QSslError> &>::of(&QSslSocket::sslErrors), this, &tst_QSslSocket::ignoreErrorSlot);
+ connect(socket, &QSslSocket::encrypted, &loop, &QEventLoop::quit);
+
+ client.connectToHostEncrypted(QHostAddress(QHostAddress::LocalHost).toString(), server.serverPort());
+ loop.exec();
+ socket = nullptr;
+ QCOMPARE(client.state(), state);
+}
+
void tst_QSslSocket::forwardReadChannelFinished()
{
if (!QSslSocket::supportsSsl())