QSsl - delete all mentions of SslV2 and SslV3

Also, change the notion of 'unsupported protocol' for QSslSocket,
previously it was SslV2 and SslV3, now instead it's all versions
of DTLS and UnknownProtocol:
- makes no sense at all to connect using TCP socket and then
  suddenly start using DTLS_client/server_method
- UnknownProtocol is not to be set in a configuration,
  unknown means that some ciphersuite's protocol version
  cannot be established.
- 'disabledProtocols' auto-test becomes 'unsupportedProtocols'
  and tests that QSslSocket fails to start encryption if the
  protocol version is wrong.

Handling these enumerators (SslV2 and SslV2) as errors
not needed anymore. Removed from QSslContext and our
existing backends (qsslsocket_whatever).

TlsV1SslV3 enumerator is not making any sense at all (previously
was [SSL v3, TLS 1.0], then became "the same as TLS v. 1.0", but
now this name is very confusing. Removed.

Task-number: QTBUG-75638
Task-number: QTBUG-76501
Change-Id: I2781ba1c3051a7791b476266d4561d956948974a
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
bb10
Timur Pocheptsov 2019-11-13 10:37:36 +01:00
parent 43f341a137
commit cd200ad7ae
9 changed files with 68 additions and 182 deletions

View File

@ -120,8 +120,6 @@ Q_LOGGING_CATEGORY(lcSsl, "qt.network.ssl");
Describes the protocol of the cipher.
\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
@ -137,7 +135,6 @@ Q_LOGGING_CATEGORY(lcSsl, "qt.network.ssl");
\value TlsV1_3OrLater TLSv1.3 and later versions. (Since Qt 5.12)
\value UnknownProtocol The cipher's protocol cannot be determined.
\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

@ -77,20 +77,10 @@ namespace QSsl {
#endif
enum SslProtocol {
#if QT_DEPRECATED_SINCE(5, 15)
SslV3,
SslV2,
#endif
TlsV1_0 = 2,
#if QT_DEPRECATED_SINCE(5,0)
TlsV1 = TlsV1_0,
#endif
TlsV1_1,
TlsV1_2,
AnyProtocol,
#if QT_DEPRECATED_SINCE(5, 15)
TlsV1SslV3,
#endif
SecureProtocols = AnyProtocol + 2,
TlsV1_0OrLater,

View File

@ -286,42 +286,31 @@ void QSslContext::initSslContext(QSslContext *sslContext, QSslSocket::SslMode mo
bool unsupportedProtocol = false;
bool isDtls = false;
init_context:
if (sslContext->sslConfiguration.protocol() == QSsl::SslV2) {
// SSL 2 is no longer supported, but chosen deliberately -> error
sslContext->ctx = nullptr;
unsupportedProtocol = true;
} else if (sslContext->sslConfiguration.protocol() == QSsl::SslV3) {
// SSL 3 is no longer supported, but chosen deliberately -> error
sslContext->ctx = nullptr;
unsupportedProtocol = true;
} else {
switch (sslContext->sslConfiguration.protocol()) {
case QSsl::DtlsV1_0:
case QSsl::DtlsV1_0OrLater:
case QSsl::DtlsV1_2:
case QSsl::DtlsV1_2OrLater:
switch (sslContext->sslConfiguration.protocol()) {
case QSsl::DtlsV1_0:
case QSsl::DtlsV1_0OrLater:
case QSsl::DtlsV1_2:
case QSsl::DtlsV1_2OrLater:
#if QT_CONFIG(dtls)
isDtls = true;
sslContext->ctx = q_SSL_CTX_new(client ? q_DTLS_client_method() : q_DTLS_server_method());
isDtls = true;
sslContext->ctx = q_SSL_CTX_new(client ? q_DTLS_client_method() : q_DTLS_server_method());
#else // dtls
sslContext->ctx = nullptr;
unsupportedProtocol = true;
qCWarning(lcSsl, "DTLS protocol requested, but feature 'dtls' is disabled");
sslContext->ctx = nullptr;
unsupportedProtocol = true;
qCWarning(lcSsl, "DTLS protocol requested, but feature 'dtls' is disabled");
#endif // dtls
break;
case QSsl::TlsV1_3:
case QSsl::TlsV1_3OrLater:
break;
case QSsl::TlsV1_3:
case QSsl::TlsV1_3OrLater:
#if !defined(TLS1_3_VERSION)
qCWarning(lcSsl, "TLS 1.3 is not supported");
sslContext->ctx = nullptr;
unsupportedProtocol = true;
break;
qCWarning(lcSsl, "TLS 1.3 is not supported");
sslContext->ctx = nullptr;
unsupportedProtocol = true;
break;
#endif // TLS1_3_VERSION
default:
// The ssl options will actually control the supported methods
sslContext->ctx = q_SSL_CTX_new(client ? q_TLS_client_method() : q_TLS_server_method());
}
default:
// The ssl options will actually control the supported methods
sslContext->ctx = q_SSL_CTX_new(client ? q_TLS_client_method() : q_TLS_server_method());
}
if (!sslContext->ctx) {
@ -373,7 +362,6 @@ init_context:
#endif // TLS1_3_VERSION
break;
// Ranges:
case QSsl::TlsV1SslV3:
case QSsl::AnyProtocol:
case QSsl::SecureProtocols:
case QSsl::TlsV1_0OrLater:
@ -415,12 +403,6 @@ init_context:
Q_UNREACHABLE();
break;
#endif // TLS1_3_VERSION
case QSsl::SslV2:
case QSsl::SslV3:
// These protocols are not supported, and we handle
// them as an error (see the code above).
Q_UNREACHABLE();
break;
case QSsl::UnknownProtocol:
break;
}

View File

@ -2217,13 +2217,24 @@ void QSslSocketPrivate::init()
*/
bool QSslSocketPrivate::verifyProtocolSupported(const char *where)
{
if (configuration.protocol == QSsl::SslV2 || configuration.protocol == QSsl::SslV3) {
qCWarning(lcSsl) << where << "Attempted to use an unsupported protocol.";
QLatin1String protocolName("DTLS");
switch (configuration.protocol) {
case QSsl::UnknownProtocol:
// UnknownProtocol, according to our docs, is for cipher whose protocol is unknown.
// Should not be used when configuring QSslSocket.
protocolName = QLatin1String("UnknownProtocol");
Q_FALLTHROUGH();
case QSsl::DtlsV1_0:
case QSsl::DtlsV1_2:
case QSsl::DtlsV1_0OrLater:
case QSsl::DtlsV1_2OrLater:
qCWarning(lcSsl) << where << "QSslConfiguration with unexpected protocol" << protocolName;
setErrorAndEmit(QAbstractSocket::SslInvalidUserDataError,
QSslSocket::tr("Attempted to use an unsupported protocol."));
return false;
default:
return true;
}
return true;
}
/*!

View File

@ -496,10 +496,6 @@ QSsl::SslProtocol QSslSocketBackendPrivate::sessionProtocol() const
}
switch (protocol) {
case kSSLProtocol2:
return QSsl::SslV2;
case kSSLProtocol3:
return QSsl::SslV3;
case kTLSProtocol1:
return QSsl::TlsV1_0;
case kTLSProtocol11:
@ -657,23 +653,6 @@ QSslCipher QSslSocketBackendPrivate::QSslCipher_from_SSLCipherSuite(SSLCipherSui
QSslCipher ciph;
switch (cipher) {
// Sorted as in CipherSuite.h (and groupped by their RFC)
case SSL_RSA_WITH_NULL_MD5:
ciph.d->name = QLatin1String("NULL-MD5");
ciph.d->protocol = QSsl::SslV3;
break;
case SSL_RSA_WITH_NULL_SHA:
ciph.d->name = QLatin1String("NULL-SHA");
ciph.d->protocol = QSsl::SslV3;
break;
case SSL_RSA_WITH_RC4_128_MD5:
ciph.d->name = QLatin1String("RC4-MD5");
ciph.d->protocol = QSsl::SslV3;
break;
case SSL_RSA_WITH_RC4_128_SHA:
ciph.d->name = QLatin1String("RC4-SHA");
ciph.d->protocol = QSsl::SslV3;
break;
// TLS addenda using AES, per RFC 3268
case TLS_RSA_WITH_AES_128_CBC_SHA:
ciph.d->name = QLatin1String("AES128-SHA");
@ -822,12 +801,8 @@ QSslCipher QSslSocketBackendPrivate::QSslCipher_from_SSLCipherSuite(SSLCipherSui
ciph.d->isNull = false;
// protocol
if (ciph.d->protocol == QSsl::SslV3) {
ciph.d->protocolString = QLatin1String("SSLv3");
} else {
ciph.d->protocol = QSsl::TlsV1_2;
ciph.d->protocolString = QLatin1String("TLSv1.2");
}
ciph.d->protocol = QSsl::TlsV1_2;
ciph.d->protocolString = QLatin1String("TLSv1.2");
const auto bits = ciph.d->name.splitRef(QLatin1Char('-'));
if (bits.size() >= 2) {
@ -1106,22 +1081,6 @@ bool QSslSocketBackendPrivate::setSessionProtocol()
{
Q_ASSERT_X(context, Q_FUNC_INFO, "invalid SSL context (null)");
// QSsl::SslV2 == kSSLProtocol2 is disabled in Secure Transport and
// always fails with errSSLIllegalParam:
// if (version < MINIMUM_STREAM_VERSION || version > MAXIMUM_STREAM_VERSION)
// return errSSLIllegalParam;
// where MINIMUM_STREAM_VERSION is SSL_Version_3_0, MAXIMUM_STREAM_VERSION is TLS_Version_1_2.
if (configuration.protocol == QSsl::SslV2) {
qCDebug(lcSsl) << "protocol QSsl::SslV2 is disabled";
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
@ -1162,13 +1121,6 @@ bool QSslSocketBackendPrivate::setSessionProtocol()
qCDebug(lcSsl) << plainSocket << "requesting : any";
#endif
err = SSLSetProtocolVersionMin(context, kTLSProtocol1);
} else if (configuration.protocol == QSsl::TlsV1SslV3) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << plainSocket << "requesting : SSLv3 - TLSv1.2";
#endif
err = SSLSetProtocolVersionMin(context, kTLSProtocol1);
if (err == errSecSuccess)
err = SSLSetProtocolVersionMax(context, kTLSProtocol1);
} else if (configuration.protocol == QSsl::SecureProtocols) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << plainSocket << "requesting : TLSv1 - TLSv1.2";
@ -1213,8 +1165,6 @@ bool QSslSocketBackendPrivate::verifySessionProtocol() const
bool protocolOk = false;
if (configuration.protocol == QSsl::AnyProtocol)
protocolOk = true;
else if (configuration.protocol == QSsl::TlsV1SslV3)
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

@ -249,11 +249,7 @@ QSslCipher QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(const SSL_CIPHER
QString protoString = descriptionList.at(1).toString();
ciph.d->protocolString = protoString;
ciph.d->protocol = QSsl::UnknownProtocol;
if (protoString == QLatin1String("SSLv3"))
ciph.d->protocol = QSsl::SslV3;
else if (protoString == QLatin1String("SSLv2"))
ciph.d->protocol = QSsl::SslV2;
else if (protoString == QLatin1String("TLSv1"))
if (protoString == QLatin1String("TLSv1"))
ciph.d->protocol = QSsl::TlsV1_0;
else if (protoString == QLatin1String("TLSv1.1"))
ciph.d->protocol = QSsl::TlsV1_1;
@ -459,20 +455,23 @@ void q_setDefaultDtlsCiphers(const QList<QSslCipher> &ciphers);
long QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions)
{
long options;
if (protocol == QSsl::TlsV1SslV3)
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)
options = SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3;
else if (protocol == QSsl::TlsV1_1OrLater)
options = SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1;
else if (protocol == QSsl::TlsV1_2OrLater)
options = SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1;
else if (protocol == QSsl::TlsV1_3OrLater)
options = SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2;
else
switch (protocol) {
case QSsl::SecureProtocols:
case QSsl::TlsV1_0OrLater:
options = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
break;
case QSsl::TlsV1_1OrLater:
options = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1;
break;
case QSsl::TlsV1_2OrLater:
options = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1;
break;
case QSsl::TlsV1_3OrLater:
options = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2;
break;
default:
options = SSL_OP_ALL;
}
// This option is disabled by default, so we need to be able to clear it
if (sslOptions & QSsl::SslOptionDisableEmptyFragments)
@ -530,10 +529,7 @@ bool QSslSocketBackendPrivate::initSslContext()
return false;
}
if (configuration.protocol != QSsl::SslV2 &&
configuration.protocol != QSsl::SslV3 &&
configuration.protocol != QSsl::UnknownProtocol &&
mode == QSslSocket::SslClientMode) {
if (configuration.protocol != QSsl::UnknownProtocol && mode == QSslSocket::SslClientMode) {
// Set server hostname on TLS extension. RFC4366 section 3.1 requires it in ACE format.
QString tlsHostName = verificationPeerName.isEmpty() ? q->peerName() : verificationPeerName;
if (tlsHostName.isEmpty())
@ -1746,10 +1742,6 @@ QSsl::SslProtocol QSslSocketBackendPrivate::sessionProtocol() const
int ver = q_SSL_version(ssl);
switch (ver) {
case 0x2:
return QSsl::SslV2;
case 0x300:
return QSsl::SslV3;
case 0x301:
return QSsl::TlsV1_0;
case 0x302:

View File

@ -226,12 +226,6 @@ DWORD toSchannelProtocol(QSsl::SslProtocol protocol)
protocols = SP_PROT_TLS1_0 | SP_PROT_TLS1_1 | SP_PROT_TLS1_2;
// @future Add TLS 1.3 when supported by Windows!
break;
case QSsl::SslV2:
case QSsl::SslV3:
return DWORD(-1); // Not supported
case QSsl::TlsV1SslV3:
protocols = SP_PROT_TLS1_0;
break;
case QSsl::TlsV1_0:
protocols = SP_PROT_TLS1_0;
break;

View File

@ -230,13 +230,7 @@ void QSslSocketBackendPrivate::startClientEncryption()
QSsl::SslProtocol protocol = q->protocol();
switch (q->protocol()) {
case QSsl::SslV2:
case QSsl::SslV3:
setErrorAndEmit(QAbstractSocket::SslInvalidUserDataError,
QStringLiteral("unsupported protocol"));
return;
case QSsl::AnyProtocol:
case QSsl::TlsV1SslV3:
protectionLevel = SocketProtectionLevel_Tls10;
break;
case QSsl::TlsV1_0:

View File

@ -259,8 +259,8 @@ private slots:
void signatureAlgorithm();
#endif
void disabledProtocols_data();
void disabledProtocols();
void unsupportedProtocols_data();
void unsupportedProtocols();
void oldErrorsOnSocketReuse();
@ -1179,25 +1179,6 @@ void tst_QSslSocket::protocol()
QCOMPARE(socket->protocol(), QSsl::AnyProtocol);
socket->abort();
}
{
// qt-test-server allows TlsV1, so it allows TlsV1SslV3
socket->setProtocol(QSsl::TlsV1SslV3);
QCOMPARE(socket->protocol(), QSsl::TlsV1SslV3);
socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
if (setProxy && !socket->waitForEncrypted())
QSKIP("Skipping flaky test - See QTBUG-29941");
QCOMPARE(socket->protocol(), QSsl::TlsV1SslV3);
socket->abort();
QCOMPARE(socket->protocol(), QSsl::TlsV1SslV3);
socket->connectToHost(QtNetworkSettings::httpServerName(), 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");
QCOMPARE(socket->protocol(), QSsl::TlsV1SslV3);
socket->abort();
}
}
class SslServer : public QTcpServer
@ -1303,20 +1284,13 @@ void tst_QSslSocket::protocolServerSide_data()
QTest::addColumn<bool>("works");
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;
QTest::newRow("tls1-tls1ssl3") << QSsl::TlsV1_0 << QSsl::TlsV1SslV3 << true;
QTest::newRow("tls1.0-secure") << QSsl::TlsV1_0 << QSsl::SecureProtocols << true;
QTest::newRow("tls1.0-any") << QSsl::TlsV1_0 << QSsl::AnyProtocol << true;
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;
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;
QTest::newRow("tls1.0orlater-tls1.0") << QSsl::TlsV1_0OrLater << QSsl::TlsV1_0 << true;
@ -1348,7 +1322,6 @@ void tst_QSslSocket::protocolServerSide_data()
#endif // TLS1_3_VERSION
QTest::newRow("any-tls1.0") << QSsl::AnyProtocol << QSsl::TlsV1_0 << true;
QTest::newRow("any-tls1ssl3") << QSsl::AnyProtocol << QSsl::TlsV1SslV3 << true;
QTest::newRow("any-secure") << QSsl::AnyProtocol << QSsl::SecureProtocols << true;
}
@ -4325,27 +4298,30 @@ void tst_QSslSocket::forwardReadChannelFinished()
#endif // QT_NO_OPENSSL
void tst_QSslSocket::disabledProtocols_data()
void tst_QSslSocket::unsupportedProtocols_data()
{
QTest::addColumn<QSsl::SslProtocol>("disabledProtocol");
QTest::newRow("SslV2") << QSsl::SslV2;
QTest::newRow("SslV3") << QSsl::SslV3;
QTest::addColumn<QSsl::SslProtocol>("unsupportedProtocol");
QTest::newRow("DtlsV1_0") << QSsl::DtlsV1_0;
QTest::newRow("DtlsV1_2") << QSsl::DtlsV1_2;
QTest::newRow("DtlsV1_0OrLater") << QSsl::DtlsV1_0OrLater;
QTest::newRow("DtlsV1_2OrLater") << QSsl::DtlsV1_2OrLater;
QTest::newRow("UnknownProtocol") << QSsl::UnknownProtocol;
}
void tst_QSslSocket::disabledProtocols()
void tst_QSslSocket::unsupportedProtocols()
{
QFETCH_GLOBAL(const bool, setProxy);
if (setProxy)
return;
QFETCH(const QSsl::SslProtocol, disabledProtocol);
QFETCH(const QSsl::SslProtocol, unsupportedProtocol);
const int timeoutMS = 500;
// Test a client socket.
{
// 0. connectToHostEncrypted: client-side, non-blocking API, error is discovered
// early, preventing any real connection from ever starting.
QSslSocket socket;
socket.setProtocol(disabledProtocol);
socket.setProtocol(unsupportedProtocol);
QCOMPARE(socket.error(), QAbstractSocket::UnknownSocketError);
socket.connectToHostEncrypted(QStringLiteral("doesnotmatter.org"), 1010);
QCOMPARE(socket.error(), QAbstractSocket::SslInvalidUserDataError);
@ -4363,7 +4339,7 @@ void tst_QSslSocket::disabledProtocols()
socket.connectToHost(QHostAddress::LocalHost, server.serverPort());
QVERIFY(socket.waitForConnected(timeoutMS));
socket.setProtocol(disabledProtocol);
socket.setProtocol(unsupportedProtocol);
socket.startClientEncryption();
QCOMPARE(socket.error(), QAbstractSocket::SslInvalidUserDataError);
}
@ -4377,7 +4353,7 @@ void tst_QSslSocket::disabledProtocols()
// and then calls startServerEncryption() (which must fall).
{
SslServer server;
server.protocol = disabledProtocol;
server.protocol = unsupportedProtocol;
QVERIFY(server.listen());
QTestEventLoop loop;