QSslSocket (OpenSSL 1.1) - respect requested protocol version
Properly handle single protocol TLS configurations. Previously, due to the use of generic (non version-specific) client/server method they worked as ranges of protocols instead. This also fixes a couple of previously broken tests. Task-number: QTBUG-67584 Change-Id: Ied23113a4fab6b407a34c953e3bd33eab153bb67 Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
parent
4b6542c9ff
commit
e3cea2a7b9
@ -117,7 +117,7 @@ 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
|
||||
\value SslV2 SSLv2. Note, SSLv2 support was removed in OpenSSL 1.1.
|
||||
\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
|
||||
@ -126,8 +126,8 @@ Q_LOGGING_CATEGORY(lcSsl, "qt.network.ssl");
|
||||
\value TlsV1_2 TLSv1.2. When using the WinRT backend this option will also enable TLSv1.0 and TLSv1.1.
|
||||
\value TlsV1_2OrLater TLSv1.2 and later versions. This option is not available when using the WinRT backend due to platform limitations.
|
||||
\value UnknownProtocol The cipher's protocol cannot be determined.
|
||||
\value AnyProtocol The socket understands SSLv2, SSLv3, and TLSv1.0. This
|
||||
value is used by QSslSocket only.
|
||||
\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.
|
||||
|
@ -100,6 +100,68 @@ init_context:
|
||||
return;
|
||||
}
|
||||
|
||||
long minVersion = TLS_ANY_VERSION;
|
||||
long maxVersion = TLS_ANY_VERSION;
|
||||
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;
|
||||
break;
|
||||
case QSsl::TlsV1_1:
|
||||
minVersion = TLS1_1_VERSION;
|
||||
maxVersion = TLS1_1_VERSION;
|
||||
break;
|
||||
case QSsl::TlsV1_2:
|
||||
minVersion = TLS1_2_VERSION;
|
||||
maxVersion = TLS1_2_VERSION;
|
||||
break;
|
||||
// Ranges:
|
||||
case QSsl::TlsV1SslV3:
|
||||
case QSsl::AnyProtocol:
|
||||
minVersion = SSL3_VERSION;
|
||||
maxVersion = TLS_MAX_VERSION;
|
||||
break;
|
||||
case QSsl::SecureProtocols:
|
||||
case QSsl::TlsV1_0OrLater:
|
||||
minVersion = TLS1_VERSION;
|
||||
maxVersion = TLS_MAX_VERSION;
|
||||
break;
|
||||
case QSsl::TlsV1_1OrLater:
|
||||
minVersion = TLS1_1_VERSION;
|
||||
maxVersion = TLS_MAX_VERSION;
|
||||
break;
|
||||
case QSsl::TlsV1_2OrLater:
|
||||
minVersion = TLS1_2_VERSION;
|
||||
maxVersion = TLS_MAX_VERSION;
|
||||
break;
|
||||
case QSsl::SslV2:
|
||||
// This protocol is not supported by OpenSSL 1.1 and we handle
|
||||
// it as an error (see the code above).
|
||||
Q_UNREACHABLE();
|
||||
break;
|
||||
case QSsl::UnknownProtocol:
|
||||
break;
|
||||
}
|
||||
|
||||
if (minVersion != TLS_ANY_VERSION
|
||||
&& !q_SSL_CTX_set_min_proto_version(sslContext->ctx, minVersion)) {
|
||||
sslContext->errorStr = QSslSocket::tr("Error while setting the minimal protocol version");
|
||||
sslContext->errorCode = QSslError::UnspecifiedError;
|
||||
return;
|
||||
}
|
||||
|
||||
if (maxVersion != TLS_ANY_VERSION
|
||||
&& !q_SSL_CTX_set_max_proto_version(sslContext->ctx, maxVersion)) {
|
||||
sslContext->errorStr = QSslSocket::tr("Error while setting the maximum protocol version");
|
||||
sslContext->errorCode = QSslError::UnspecifiedError;
|
||||
return;
|
||||
}
|
||||
|
||||
// Enable bug workarounds.
|
||||
long options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions);
|
||||
q_SSL_CTX_set_options(sslContext->ctx, options);
|
||||
|
@ -129,4 +129,10 @@ const char *q_OpenSSL_version(int type);
|
||||
|
||||
unsigned long q_SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *session);
|
||||
|
||||
#define q_SSL_CTX_set_min_proto_version(ctx, version) \
|
||||
q_SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MIN_PROTO_VERSION, version, nullptr)
|
||||
|
||||
#define q_SSL_CTX_set_max_proto_version(ctx, version) \
|
||||
q_SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MAX_PROTO_VERSION, version, nullptr)
|
||||
|
||||
#endif
|
||||
|
@ -1188,13 +1188,7 @@ void tst_QSslSocket::protocolServerSide_data()
|
||||
#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
|
||||
// A client using our OpenSSL1.1 backend will negotiate up from TLS 1.0 or 1.1
|
||||
// to TLS 1.2 if the server asks for it, where our older backend fails to compromise.
|
||||
// So some tests that fail for the old pass with the new.
|
||||
const bool willUseTLS12 = true;
|
||||
#else
|
||||
const bool willUseTLS12 = false;
|
||||
#endif // OPENSSL_NO_SSL2
|
||||
#endif // opensslv11
|
||||
|
||||
#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT)
|
||||
@ -1290,7 +1284,7 @@ void tst_QSslSocket::protocolServerSide_data()
|
||||
QTest::newRow("tls1.1orlater-ssl3") << QSsl::TlsV1_1OrLater << QSsl::SslV3 << false;
|
||||
#endif
|
||||
|
||||
QTest::newRow("tls1.1orlater-tls1.0") << QSsl::TlsV1_1OrLater << QSsl::TlsV1_0 << willUseTLS12;
|
||||
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;
|
||||
|
||||
@ -1300,8 +1294,8 @@ void tst_QSslSocket::protocolServerSide_data()
|
||||
#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 << willUseTLS12;
|
||||
QTest::newRow("tls1.2orlater-tls1.1") << QSsl::TlsV1_2OrLater << QSsl::TlsV1_1 << willUseTLS12;
|
||||
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;
|
||||
|
||||
QTest::newRow("any-tls1.0") << QSsl::AnyProtocol << QSsl::TlsV1_0 << true;
|
||||
|
Loading…
Reference in New Issue
Block a user