OpenSSL: drop support for SSLv2 and SSLv3

As per RFC 6176 (2011) and RFC 7568 (2015).

Code-wise, we're left with the decision of what to do with a few
enumerators in QSsl::Protocol; I've made TlsV1SslV3 act as TlsV1,
and adjusted the description of AnyProtocol.
A new test was introduced - deprecatedProtocol() - to test that
we, indeed, do not allow use of SSL v2 and v3. protocol() and
protocolServerSide() were reduced to exclude the (now) no-op
and meaningless tests - neither client nor server side can
start a handshake now, since we bail out early in initSslContext().

[ChangeLog][QtNetwork][SSL] Support for SSLv2 and SSLv3
sockets has been dropped, as per RFC 6176 (2011)
and RFC 7568 (2015).

Change-Id: I2fe4e8c3e82adf7aa10d4bdc9e3f7b8c299f77b6
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
bb10
Giuseppe D'Angelo 2018-11-29 02:57:15 +01:00 committed by Timur Pocheptsov
parent 3364be7859
commit 455951f590
9 changed files with 97 additions and 247 deletions

View File

@ -117,8 +117,8 @@ Q_LOGGING_CATEGORY(lcSsl, "qt.network.ssl");
Describes the protocol of the cipher.
\value SslV3 SSLv3. When using the WinRT backend this option will also enable TLSv1.0
\value SslV2 SSLv2. Note, SSLv2 support was removed in OpenSSL 1.1.
\value SslV3 SSLv3; not supported by QSslSocket.
\value SslV2 SSLv2; not supported by QSslSocket.
\value TlsV1_0 TLSv1.0
\value TlsV1_0OrLater TLSv1.0 and later versions. This option is not available when using the WinRT backend due to platform limitations.
\value TlsV1 Obsolete, means the same as TlsV1_0
@ -133,19 +133,9 @@ Q_LOGGING_CATEGORY(lcSsl, "qt.network.ssl");
\value TlsV1_3 TLSv1.3. (Since Qt 5.12)
\value TlsV1_3OrLater TLSv1.3 and later versions. (Since Qt 5.12)
\value UnknownProtocol The cipher's protocol cannot be determined.
\value AnyProtocol The socket understands SSLv2, SSLv3, TLSv1.0 and all
supported later versions of TLS. This value is used by QSslSocket only.
\value TlsV1SslV3 On the client side, this will send
a TLS 1.0 Client Hello, enabling TLSv1_0 and SSLv3 connections.
On the server side, this will enable both SSLv3 and TLSv1_0 connections.
\value SecureProtocols The default option, using protocols known to be secure;
currently behaves similar to TlsV1Ssl3 except denying SSLv3 connections that does
not upgrade to TLS.
\note most servers understand both SSL and TLS, but it is recommended to use
TLS only for security reasons. However, SSL and TLS are not compatible with
each other: if you get unexpected handshake failures, verify that you chose
the correct setting for your protocol.
\value AnyProtocol Any supported protocol. This value is used by QSslSocket only.
\value TlsV1SslV3 Same as TlsV1_0.
\value SecureProtocols The default option, using protocols known to be secure.
*/
/*!

View File

@ -95,6 +95,10 @@ init_context:
// 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:
@ -151,11 +155,6 @@ init_context:
long maxVersion = anyVersion;
switch (sslContext->sslConfiguration.protocol()) {
// The single-protocol versions first:
case QSsl::SslV3:
minVersion = SSL3_VERSION;
maxVersion = SSL3_VERSION;
break;
case QSsl::TlsV1_0:
minVersion = TLS1_VERSION;
maxVersion = TLS1_VERSION;
@ -181,9 +180,6 @@ init_context:
// Ranges:
case QSsl::TlsV1SslV3:
case QSsl::AnyProtocol:
minVersion = SSL3_VERSION;
maxVersion = 0;
break;
case QSsl::SecureProtocols:
case QSsl::TlsV1_0OrLater:
minVersion = TLS1_VERSION;
@ -227,8 +223,9 @@ init_context:
break;
#endif // TLS1_3_VERSION
case QSsl::SslV2:
// This protocol is not supported by OpenSSL 1.1 and we handle
// it as an error (see the code above).
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:

View File

@ -115,32 +115,19 @@ init_context:
break;
#endif // dtls
case QSsl::SslV2:
#ifndef OPENSSL_NO_SSL2
sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv2_client_method() : q_SSLv2_server_method());
#else
// SSL 2 not supported by the system, but chosen deliberately -> error
sslContext->ctx = 0;
unsupportedProtocol = true;
#endif
break;
case QSsl::SslV3:
#ifndef OPENSSL_NO_SSL3_METHOD
sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv3_client_method() : q_SSLv3_server_method());
#else
// SSL 3 not supported by the system, but chosen deliberately -> error
// We don't support SSLv2 / SSLv3.
sslContext->ctx = 0;
unsupportedProtocol = true;
#endif
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::TlsV1SslV3:
// SSLv2 will will be disabled by SSL options
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;

View File

@ -1107,6 +1107,12 @@ bool QSslSocketBackendPrivate::setSessionProtocol()
return false;
}
// SslV3 is unsupported.
if (configuration.protocol == QSsl::SslV3) {
qCDebug(lcSsl) << "protocol QSsl::SslV3 is disabled";
return false;
}
// SecureTransport has kTLSProtocol13 constant and also, kTLSProtocolMaxSupported.
// Calling SSLSetProtocolVersionMax/Min with any of these two constants results
// in errInvalidParam and a failure to set the protocol version. This means
@ -1121,14 +1127,7 @@ bool QSslSocketBackendPrivate::setSessionProtocol()
OSStatus err = errSecSuccess;
if (configuration.protocol == QSsl::SslV3) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << plainSocket << "requesting : SSLv3";
#endif
err = SSLSetProtocolVersionMin(context, kSSLProtocol3);
if (err == errSecSuccess)
err = SSLSetProtocolVersionMax(context, kSSLProtocol3);
} else if (configuration.protocol == QSsl::TlsV1_0) {
if (configuration.protocol == QSsl::TlsV1_0) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.0";
#endif
@ -1153,17 +1152,16 @@ bool QSslSocketBackendPrivate::setSessionProtocol()
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << plainSocket << "requesting : any";
#endif
// kSSLProtocol3, since kSSLProtocol2 is disabled:
err = SSLSetProtocolVersionMin(context, kSSLProtocol3);
err = SSLSetProtocolVersionMin(context, kTLSProtocol1);
if (err == errSecSuccess)
err = SSLSetProtocolVersionMax(context, kTLSProtocol12);
} else if (configuration.protocol == QSsl::TlsV1SslV3) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << plainSocket << "requesting : SSLv3 - TLSv1.2";
#endif
err = SSLSetProtocolVersionMin(context, kSSLProtocol3);
err = SSLSetProtocolVersionMin(context, kTLSProtocol1);
if (err == errSecSuccess)
err = SSLSetProtocolVersionMax(context, kTLSProtocol12);
err = SSLSetProtocolVersionMax(context, kTLSProtocol1);
} else if (configuration.protocol == QSsl::SecureProtocols) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << plainSocket << "requesting : TLSv1 - TLSv1.2";
@ -1217,7 +1215,7 @@ bool QSslSocketBackendPrivate::verifySessionProtocol() const
if (configuration.protocol == QSsl::AnyProtocol)
protocolOk = true;
else if (configuration.protocol == QSsl::TlsV1SslV3)
protocolOk = (sessionProtocol() >= QSsl::SslV3);
protocolOk = (sessionProtocol() == QSsl::TlsV1_0);
else if (configuration.protocol == QSsl::SecureProtocols)
protocolOk = (sessionProtocol() >= QSsl::TlsV1_0);
else if (configuration.protocol == QSsl::TlsV1_0OrLater)

View File

@ -395,7 +395,7 @@ long QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SslProtocol protocol, Q
{
long options;
if (protocol == QSsl::TlsV1SslV3)
options = SSL_OP_ALL|SSL_OP_NO_SSLv2;
options = SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3;
else if (protocol == QSsl::SecureProtocols)
options = SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3;
else if (protocol == QSsl::TlsV1_0OrLater)

View File

@ -285,24 +285,12 @@ DEFINEFUNC5(int, SSL_get_ex_new_index, long argl, argl, void *argp, argp, CRYPTO
#endif // OPENSSL_VERSION_NUMBER >= 0x10001000L
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
#ifndef OPENSSL_NO_SSL2
DEFINEFUNC(const SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
#endif
#ifndef OPENSSL_NO_SSL3_METHOD
DEFINEFUNC(const SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
#endif
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
#ifndef OPENSSL_NO_SSL2
DEFINEFUNC(const SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
#endif
#ifndef OPENSSL_NO_SSL3_METHOD
DEFINEFUNC(const SSL_METHOD *, SSLv3_server_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
@ -310,20 +298,8 @@ DEFINEFUNC(const SSL_METHOD *, TLSv1_1_server_method, DUMMYARG, DUMMYARG, return
DEFINEFUNC(const SSL_METHOD *, TLSv1_2_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
#endif
#else
#ifndef OPENSSL_NO_SSL2
DEFINEFUNC(SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
#endif
#ifndef OPENSSL_NO_SSL3_METHOD
DEFINEFUNC(SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
#endif
DEFINEFUNC(SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
DEFINEFUNC(SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
#ifndef OPENSSL_NO_SSL2
DEFINEFUNC(SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
#endif
#ifndef OPENSSL_NO_SSL3_METHOD
DEFINEFUNC(SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
#endif
DEFINEFUNC(SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
DEFINEFUNC(SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
#endif
@ -1129,24 +1105,12 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(SSL_load_error_strings)
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
RESOLVEFUNC(SSL_get_ex_new_index)
#endif
#ifndef OPENSSL_NO_SSL2
RESOLVEFUNC(SSLv2_client_method)
#endif
#ifndef OPENSSL_NO_SSL3_METHOD
RESOLVEFUNC(SSLv3_client_method)
#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
#ifndef OPENSSL_NO_SSL2
RESOLVEFUNC(SSLv2_server_method)
#endif
#ifndef OPENSSL_NO_SSL3_METHOD
RESOLVEFUNC(SSLv3_server_method)
#endif
RESOLVEFUNC(SSLv23_server_method)
RESOLVEFUNC(TLSv1_server_method)

View File

@ -136,43 +136,19 @@ int q_SSL_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, CRYPT
#endif
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
#ifndef OPENSSL_NO_SSL2
const SSL_METHOD *q_SSLv2_client_method();
#endif
#ifndef OPENSSL_NO_SSL3_METHOD
const SSL_METHOD *q_SSLv3_client_method();
#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();
#ifndef OPENSSL_NO_SSL2
const SSL_METHOD *q_SSLv2_server_method();
#endif
#ifndef OPENSSL_NO_SSL3_METHOD
const SSL_METHOD *q_SSLv3_server_method();
#endif
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();
#else
#ifndef OPENSSL_NO_SSL2
SSL_METHOD *q_SSLv2_client_method();
#endif
#ifndef OPENSSL_NO_SSL3_METHOD
SSL_METHOD *q_SSLv3_client_method();
#endif
SSL_METHOD *q_SSLv23_client_method();
SSL_METHOD *q_TLSv1_client_method();
SSL_METHOD *q_TLSv1_1_client_method();
SSL_METHOD *q_TLSv1_2_client_method();
#ifndef OPENSSL_NO_SSL2
SSL_METHOD *q_SSLv2_server_method();
#endif
#ifndef OPENSSL_NO_SSL3_METHOD
SSL_METHOD *q_SSLv3_server_method();
#endif
SSL_METHOD *q_SSLv23_server_method();
SSL_METHOD *q_TLSv1_server_method();
SSL_METHOD *q_TLSv1_1_server_method();

View File

@ -207,9 +207,9 @@ void QSslSocketPrivate::resetDefaultCiphers()
QList<QSslCipher> QSslSocketBackendPrivate::defaultCiphers()
{
QList<QSslCipher> ciphers;
const QString protocolStrings[] = { QStringLiteral("SSLv3"), QStringLiteral("TLSv1"),
const QString protocolStrings[] = { QStringLiteral("TLSv1"),
QStringLiteral("TLSv1.1"), QStringLiteral("TLSv1.2") };
const QSsl::SslProtocol protocols[] = { QSsl::SslV3, QSsl::TlsV1_0, QSsl::TlsV1_1, QSsl::TlsV1_2 };
const QSsl::SslProtocol protocols[] = { QSsl::TlsV1_0, QSsl::TlsV1_1, QSsl::TlsV1_2 };
const int size = static_cast<int>(ARRAYSIZE(protocols));
ciphers.reserve(size);
for (int i = 0; i < size; ++i) {
@ -234,10 +234,14 @@ void QSslSocketBackendPrivate::startClientEncryption()
QSsl::SslProtocol protocol = q->protocol();
switch (q->protocol()) {
case QSsl::AnyProtocol:
case QSsl::SslV2:
case QSsl::SslV3:
setErrorAndEmit(QAbstractSocket::SslInvalidUserDataError,
QStringLiteral("unsupported protocol"));
return;
case QSsl::AnyProtocol:
case QSsl::TlsV1SslV3:
protectionLevel = SocketProtectionLevel_Ssl; // Only use this value if weak cipher support is required
protectionLevel = SocketProtectionLevel_Tls10;
break;
case QSsl::TlsV1_0:
protectionLevel = SocketProtectionLevel_Tls10;

View File

@ -245,6 +245,9 @@ private slots:
void signatureAlgorithm();
#endif
void deprecatedProtocols_data();
void deprecatedProtocols();
void setEmptyDefaultConfiguration(); // this test should be last
protected slots:
@ -951,24 +954,6 @@ void tst_QSslSocket::protocol()
QCOMPARE(socket->protocol(), QSsl::SecureProtocols);
QFETCH_GLOBAL(bool, setProxy);
{
// qt-test-server allows SSLv3.
socket->setProtocol(QSsl::SslV3);
QCOMPARE(socket->protocol(), QSsl::SslV3);
socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
if (setProxy && !socket->waitForEncrypted())
QSKIP("Skipping flaky test - See QTBUG-29941");
QCOMPARE(socket->protocol(), QSsl::SslV3);
socket->abort();
QCOMPARE(socket->protocol(), QSsl::SslV3);
socket->connectToHost(QtNetworkSettings::serverName(), 443);
QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString()));
socket->startClientEncryption();
if (setProxy && !socket->waitForEncrypted())
QSKIP("Skipping flaky test - See QTBUG-29941");
QCOMPARE(socket->protocol(), QSsl::SslV3);
socket->abort();
}
{
// qt-test-server allows TLSV1.
socket->setProtocol(QSsl::TlsV1_0);
@ -1045,26 +1030,6 @@ void tst_QSslSocket::protocol()
socket->abort();
}
#endif // TLS1_3_VERSION
#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT)
{
// qt-test-server allows SSLV2.
socket->setProtocol(QSsl::SslV2);
QCOMPARE(socket->protocol(), QSsl::SslV2);
socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
if (setProxy && !socket->waitForEncrypted())
QSKIP("Skipping flaky test - See QTBUG-29941");
QCOMPARE(socket->protocol(), QSsl::SslV2);
socket->abort();
QCOMPARE(socket->protocol(), QSsl::SslV2);
socket->connectToHost(QtNetworkSettings::serverName(), 443);
if (setProxy && !socket->waitForConnected())
QSKIP("Skipping flaky test - See QTBUG-29941");
socket->startClientEncryption();
if (setProxy && !socket->waitForEncrypted())
QSKIP("Skipping flaky test - See QTBUG-29941");
socket->abort();
}
#endif
{
// qt-test-server allows SSLV3, so it allows AnyProtocol.
socket->setProtocol(QSsl::AnyProtocol);
@ -1084,7 +1049,7 @@ void tst_QSslSocket::protocol()
socket->abort();
}
{
// qt-test-server allows SSLV3, so it allows NoSslV2
// qt-test-server allows TlsV1, so it allows TlsV1SslV3
socket->setProtocol(QSsl::TlsV1SslV3);
QCOMPARE(socket->protocol(), QSsl::TlsV1SslV3);
socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
@ -1207,120 +1172,38 @@ void tst_QSslSocket::protocolServerSide_data()
QTest::addColumn<QSsl::SslProtocol>("clientProtocol");
QTest::addColumn<bool>("works");
#if QT_CONFIG(opensslv11)
#if !defined(OPENSSL_NO_SSL2)
// OpenSSL 1.1 has removed SSL2 support. But there is no OPENSSL_NO_SSL2 macro ...
#define OPENSSL_NO_SSL2
#endif // OPENSSL_NO_SSL2
#endif // opensslv11
#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT)
QTest::newRow("ssl2-ssl2") << QSsl::SslV2 << QSsl::SslV2 << false; // no idea why it does not work, but we don't care about SSL 2
#endif
#if !defined(OPENSSL_NO_SSL3)
QTest::newRow("ssl3-ssl3") << QSsl::SslV3 << QSsl::SslV3 << true;
#endif
QTest::newRow("tls1.0-tls1.0") << QSsl::TlsV1_0 << QSsl::TlsV1_0 << true;
QTest::newRow("tls1ssl3-tls1ssl3") << QSsl::TlsV1SslV3 << QSsl::TlsV1SslV3 << true;
QTest::newRow("any-any") << QSsl::AnyProtocol << QSsl::AnyProtocol << true;
QTest::newRow("secure-secure") << QSsl::SecureProtocols << QSsl::SecureProtocols << true;
#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT)
QTest::newRow("ssl2-ssl3") << QSsl::SslV2 << QSsl::SslV3 << false;
QTest::newRow("ssl2-tls1.0") << QSsl::SslV2 << QSsl::TlsV1_0 << false;
QTest::newRow("ssl2-tls1ssl3") << QSsl::SslV2 << QSsl::TlsV1SslV3 << false;
QTest::newRow("ssl2-secure") << QSsl::SslV2 << QSsl::SecureProtocols << false;
QTest::newRow("ssl2-any") << QSsl::SslV2 << QSsl::AnyProtocol << false; // no idea why it does not work, but we don't care about SSL 2
#endif
#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT) && !defined(OPENSSL_NO_SSL3)
QTest::newRow("ssl3-ssl2") << QSsl::SslV3 << QSsl::SslV2 << false;
#endif
#if !defined(OPENSSL_NO_SSL3)
QTest::newRow("ssl3-tls1.0") << QSsl::SslV3 << QSsl::TlsV1_0 << false;
QTest::newRow("ssl3-tls1ssl3") << QSsl::SslV3 << QSsl::TlsV1SslV3 << true;
QTest::newRow("ssl3-secure") << QSsl::SslV3 << QSsl::SecureProtocols << false;
#endif
#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT) && !defined(OPENSSL_NO_SSL3)
QTest::newRow("ssl3-any") << QSsl::SslV3 << QSsl::AnyProtocol << false; // we won't set a SNI header here because we connect to a
// numerical IP, so OpenSSL will send a SSL 2 handshake
#elif !defined(OPENSSL_NO_SSL3)
QTest::newRow("ssl3-any") << QSsl::SslV3 << QSsl::AnyProtocol << true;
#endif
#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT)
QTest::newRow("tls1.0-ssl2") << QSsl::TlsV1_0 << QSsl::SslV2 << false;
#endif
#if !defined(OPENSSL_NO_SSL3)
QTest::newRow("tls1.0-ssl3") << QSsl::TlsV1_0 << QSsl::SslV3 << false;
#endif
QTest::newRow("tls1-tls1ssl3") << QSsl::TlsV1_0 << QSsl::TlsV1SslV3 << true;
QTest::newRow("tls1.0-secure") << QSsl::TlsV1_0 << QSsl::SecureProtocols << true;
#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT)
QTest::newRow("tls1.0-any") << QSsl::TlsV1_0 << QSsl::AnyProtocol << false; // we won't set a SNI header here because we connect to a
// numerical IP, so OpenSSL will send a SSL 2 handshake
#else
QTest::newRow("tls1.0-any") << QSsl::TlsV1_0 << QSsl::AnyProtocol << true;
#endif
#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT)
QTest::newRow("tls1ssl3-ssl2") << QSsl::TlsV1SslV3 << QSsl::SslV2 << false;
#endif
#if !defined(OPENSSL_NO_SSL3)
QTest::newRow("tls1ssl3-ssl3") << QSsl::TlsV1SslV3 << QSsl::SslV3 << true;
#endif
QTest::newRow("tls1ssl3-tls1.0") << QSsl::TlsV1SslV3 << QSsl::TlsV1_0 << true;
QTest::newRow("tls1ssl3-secure") << QSsl::TlsV1SslV3 << QSsl::SecureProtocols << true;
QTest::newRow("tls1ssl3-any") << QSsl::TlsV1SslV3 << QSsl::AnyProtocol << true;
#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT)
QTest::newRow("secure-ssl2") << QSsl::SecureProtocols << QSsl::SslV2 << false;
#endif
#if !defined(OPENSSL_NO_SSL3)
QTest::newRow("secure-ssl3") << QSsl::SecureProtocols << QSsl::SslV3 << false;
#endif
QTest::newRow("secure-tls1.0") << QSsl::SecureProtocols << QSsl::TlsV1_0 << true;
QTest::newRow("secure-tls1ssl3") << QSsl::SecureProtocols << QSsl::TlsV1SslV3 << true;
QTest::newRow("secure-any") << QSsl::SecureProtocols << QSsl::AnyProtocol << true;
#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT)
QTest::newRow("any-ssl2") << QSsl::AnyProtocol << QSsl::SslV2 << false; // no idea why it does not work, but we don't care about SSL 2
#endif
#if !defined(OPENSSL_NO_SSL3)
QTest::newRow("any-ssl3") << QSsl::AnyProtocol << QSsl::SslV3 << true;
#endif
#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT)
QTest::newRow("tls1.0orlater-ssl2") << QSsl::TlsV1_0OrLater << QSsl::SslV2 << false;
#endif
#if !defined(OPENSSL_NO_SSL3)
QTest::newRow("tls1.0orlater-ssl3") << QSsl::TlsV1_0OrLater << QSsl::SslV3 << false;
#endif
QTest::newRow("tls1.0orlater-tls1.0") << QSsl::TlsV1_0OrLater << QSsl::TlsV1_0 << true;
QTest::newRow("tls1.0orlater-tls1.1") << QSsl::TlsV1_0OrLater << QSsl::TlsV1_1 << true;
QTest::newRow("tls1.0orlater-tls1.2") << QSsl::TlsV1_0OrLater << QSsl::TlsV1_2 << true;
#ifdef TLS1_3_VERSION
QTest::newRow("tls1.0orlater-tls1.3") << QSsl::TlsV1_0OrLater << QSsl::TlsV1_3 << true;
#endif
#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT)
QTest::newRow("tls1.1orlater-ssl2") << QSsl::TlsV1_1OrLater << QSsl::SslV2 << false;
#endif
#if !defined(OPENSSL_NO_SSL3)
QTest::newRow("tls1.1orlater-ssl3") << QSsl::TlsV1_1OrLater << QSsl::SslV3 << false;
#endif
QTest::newRow("tls1.1orlater-tls1.0") << QSsl::TlsV1_1OrLater << QSsl::TlsV1_0 << false;
QTest::newRow("tls1.1orlater-tls1.1") << QSsl::TlsV1_1OrLater << QSsl::TlsV1_1 << true;
QTest::newRow("tls1.1orlater-tls1.2") << QSsl::TlsV1_1OrLater << QSsl::TlsV1_2 << true;
#ifdef TLS1_3_VERSION
QTest::newRow("tls1.1orlater-tls1.3") << QSsl::TlsV1_1OrLater << QSsl::TlsV1_3 << true;
#endif
#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT)
QTest::newRow("tls1.2orlater-ssl2") << QSsl::TlsV1_2OrLater << QSsl::SslV2 << false;
#endif
#if !defined(OPENSSL_NO_SSL3)
QTest::newRow("tls1.2orlater-ssl3") << QSsl::TlsV1_2OrLater << QSsl::SslV3 << false;
#endif
QTest::newRow("tls1.2orlater-tls1.0") << QSsl::TlsV1_2OrLater << QSsl::TlsV1_0 << false;
QTest::newRow("tls1.2orlater-tls1.1") << QSsl::TlsV1_2OrLater << QSsl::TlsV1_1 << false;
QTest::newRow("tls1.2orlater-tls1.2") << QSsl::TlsV1_2OrLater << QSsl::TlsV1_2 << true;
@ -1328,12 +1211,6 @@ void tst_QSslSocket::protocolServerSide_data()
QTest::newRow("tls1.2orlater-tls1.3") << QSsl::TlsV1_2OrLater << QSsl::TlsV1_3 << true;
#endif
#ifdef TLS1_3_VERSION
#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT)
QTest::newRow("tls1.3orlater-ssl2") << QSsl::TlsV1_3OrLater << QSsl::SslV2 << false;
#endif
#if !defined(OPENSSL_NO_SSL3)
QTest::newRow("tls1.3orlater-ssl3") << QSsl::TlsV1_3OrLater << QSsl::SslV3 << false;
#endif
QTest::newRow("tls1.3orlater-tls1.0") << QSsl::TlsV1_3OrLater << QSsl::TlsV1_0 << false;
QTest::newRow("tls1.3orlater-tls1.1") << QSsl::TlsV1_3OrLater << QSsl::TlsV1_1 << false;
QTest::newRow("tls1.3orlater-tls1.2") << QSsl::TlsV1_3OrLater << QSsl::TlsV1_2 << false;
@ -4174,6 +4051,63 @@ void tst_QSslSocket::forwardReadChannelFinished()
#endif // QT_NO_OPENSSL
void tst_QSslSocket::deprecatedProtocols_data()
{
QTest::addColumn<QSsl::SslProtocol>("protocol");
QTest::addColumn<bool>("succeeds");
QTest::newRow("SecureProtocols") << QSsl::SecureProtocols << true;
QTest::newRow("SslV2") << QSsl::SslV2 << false;
QTest::newRow("SslV3") << QSsl::SslV3 << false;
}
void tst_QSslSocket::deprecatedProtocols()
{
QFETCH_GLOBAL(bool, setProxy);
if (setProxy)
QSKIP("This test does not work under a proxy");
QFETCH(QSsl::SslProtocol, protocol);
QFETCH(bool, succeeds);
QSslSocket socket;
socket.setProtocol(protocol);
QSignalSpy connectedSpy(&socket, &QSslSocket::connected);
QVERIFY(connectedSpy.isValid());
QSignalSpy encryptedSpy(&socket, &QSslSocket::encrypted);
QVERIFY(encryptedSpy.isValid());
QSignalSpy errorSpy(&socket, QOverload<QAbstractSocket::SocketError>::of(&QSslSocket::error));
QVERIFY(errorSpy.isValid());
connect(&socket, QOverload<const QList<QSslError> &>::of(&QSslSocket::sslErrors),
&socket, QOverload<>::of(&QSslSocket::ignoreSslErrors));
SslServer server;
QVERIFY(server.listen());
socket.connectToHost(server.serverAddress(), server.serverPort());
// Can't use waitForConnected / waitForEncrypted as they wait forever,
// so do this asynchronously via QTRY_ macros (QTBUG-72179)
QTRY_COMPARE(connectedSpy.size(), 1);
QCOMPARE(encryptedSpy.size(), 0);
QCOMPARE(errorSpy.size(), 0);
socket.startClientEncryption();
if (succeeds) {
QTRY_COMPARE(encryptedSpy.size(), 1);
QCOMPARE(errorSpy.size(), 0);
} else {
// The various backends differ in the errors fired here (QTBUG-72196),
// so just check that we did get an error (and we're not encrypted)
QTRY_VERIFY(errorSpy.size() > 0);
QCOMPARE(encryptedSpy.size(), 0);
}
}
#endif // QT_NO_SSL
QTEST_MAIN(tst_QSslSocket)