[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#914211: [src:kio] please remove insecure TLS version fall-back mechanism



Package: src:kio
Version: 5.49.0-1
Severity: important
Tags: patch
Control: found -1 5.28.0-2

Hi,

Until recently KDE kio had a custom TLS version fall-back mechanism which made 
it possible to downgrade a TLS connection to TLSv1.0 even if the server and 
client support a higher TLS version. This has been fixed upstream in [1], [2] 
and is also included in KDE Frameworks 5.52.0 [3].

Please consider backporting the patch from [2] or shipping a newer KDE 
Frameworks version, so this fix can be included in buster.

Attached you also find a backported version of [2] for the version in stretch. 
Please consider also fixing this in stretch.

[1] https://phabricator.kde.org/D16344
[2] https://cgit.kde.org/kio.git/commit/src/core/tcpslavebase.cpp?
id=e11d4d18f66ad1c6927b058be84e11d46d9de55a
[3] https://www.kde.org/announcements/kde-frameworks-5.52.0.php

Thanks for your work on Debian!
backport https://cgit.kde.org/kio.git/commit/src/core/tcpslavebase.cpp?id=e11d4d18f66ad1c6927b058be84e11d46d9de55a
to stretch.
--- a/src/core/tcpslavebase.cpp
+++ b/src/core/tcpslavebase.cpp
@@ -335,111 +335,51 @@
         }
     }
 
-    /*
-       SSL handshake is attempted in the following order:
+    const int timeout = (connectTimeout() * 1000); // 20 sec timeout value
 
-       1.) KTcpSocket::SecureProtocols
-       2.) KTcpSocket::TlsV1_2
-       3.) KTcpSocket::TlsV1_1
-       4.) KTcpSocket::TlsV1_0
-
-       Note that we indivially attempt connection with each TLS version
-       because some sites don't support SSL negotiation. #275524
-
-       The version used to successfully make encrypted connection with the
-       remote server is cached within the process to make subsequent
-       connection requests to the same server faster.
-     */
-
-    const int lastSslVerson = config()->readEntry("LastUsedSslVersion", static_cast<int>(KTcpSocket::SecureProtocols));
-    KTcpSocket::SslVersion trySslVersion = static_cast<KTcpSocket::SslVersion>(lastSslVerson);
-    KTcpSocket::SslVersions alreadyTriedSslVersions = trySslVersion;
+    disconnectFromHost();  //Reset some state, even if we are already disconnected
+    d->host = host;
 
-    const int timeout = (connectTimeout() * 1000); // 20 sec timeout value
-    while (true) {
-        disconnectFromHost();  //Reset some state, even if we are already disconnected
-        d->host = host;
-
-        d->socket.connectToHost(host, port);
-        /*const bool connectOk = */d->socket.waitForConnected(timeout > -1 ? timeout : -1);
-
-        /*qDebug() << "Socket: state=" << d->socket.state()
-          << ", error=" << d->socket.error()
-          << ", connected?" << connectOk;*/
+    d->socket.connectToHost(host, port);
+    /*const bool connectOk = */d->socket.waitForConnected(timeout > -1 ? timeout : -1);
 
-        if (d->socket.state() != KTcpSocket::ConnectedState) {
-            if (errorString) {
-                *errorString = host + QLatin1String(": ") + d->socket.errorString();
-            }
-            switch (d->socket.error()) {
-            case KTcpSocket::UnsupportedSocketOperationError:
-                return ERR_UNSUPPORTED_ACTION;
-            case KTcpSocket::RemoteHostClosedError:
-                return ERR_CONNECTION_BROKEN;
-            case KTcpSocket::SocketTimeoutError:
-                return ERR_SERVER_TIMEOUT;
-            case KTcpSocket::HostNotFoundError:
-                return ERR_UNKNOWN_HOST;
-            default:
-                return ERR_CANNOT_CONNECT;
-            }
+    /*qDebug() << "Socket: state=" << d->socket.state()
+        << ", error=" << d->socket.error()
+        << ", connected?" << connectOk;*/
+
+    if (d->socket.state() != KTcpSocket::ConnectedState) {
+        if (errorString) {
+            *errorString = host + QLatin1String(": ") + d->socket.errorString();
         }
+        switch (d->socket.error()) {
+        case KTcpSocket::UnsupportedSocketOperationError:
+            return ERR_UNSUPPORTED_ACTION;
+        case KTcpSocket::RemoteHostClosedError:
+            return ERR_CONNECTION_BROKEN;
+        case KTcpSocket::SocketTimeoutError:
+            return ERR_SERVER_TIMEOUT;
+        case KTcpSocket::HostNotFoundError:
+            return ERR_UNKNOWN_HOST;
+        default:
+            return ERR_CANNOT_CONNECT;
+        }
+    }
 
-        //### check for proxyAuthenticationRequiredError
+    //### check for proxyAuthenticationRequiredError
 
-        d->ip = d->socket.peerAddress().toString();
-        d->port = d->socket.peerPort();
+    d->ip = d->socket.peerAddress().toString();
+    d->port = d->socket.peerPort();
 
-        if (d->autoSSL) {
-            SslResult res = d->startTLSInternal(trySslVersion, timeout);
-            if ((res & ResultFailed) && (res & ResultFailedEarly)) {
-                if (!(alreadyTriedSslVersions & KTcpSocket::SecureProtocols)) {
-                    trySslVersion = KTcpSocket::SecureProtocols;
-                    alreadyTriedSslVersions |= trySslVersion;
-                    continue;
-                }
-
-                if (!(alreadyTriedSslVersions & KTcpSocket::TlsV1_2)) {
-                    trySslVersion = KTcpSocket::TlsV1;
-                    alreadyTriedSslVersions |= trySslVersion;
-                    continue;
-                }
-
-                if (!(alreadyTriedSslVersions & KTcpSocket::TlsV1_1)) {
-                    trySslVersion = KTcpSocket::TlsV1;
-                    alreadyTriedSslVersions |= trySslVersion;
-                    continue;
-                }
-
-                if (!(alreadyTriedSslVersions & KTcpSocket::TlsV1_0)) {
-                    trySslVersion = KTcpSocket::TlsV1_0;
-                    alreadyTriedSslVersions |= trySslVersion;
-                    continue;
-                }
-            }
+    if (d->autoSSL) {
+        const SslResult res = d->startTLSInternal(KTcpSocket::SecureProtocols, timeout);
 
-            //### SSL 2.0 is (close to) dead and it's a good thing, too.
-            if (res & ResultFailed) {
-                if (errorString) {
-                    *errorString = i18nc("%1 is a host name", "%1: SSL negotiation failed", host);
-                }
-                return ERR_CANNOT_CONNECT;
+        if (res & ResultFailed) {
+            if (errorString) {
+                *errorString = i18nc("%1 is a host name", "%1: SSL negotiation failed", host);
             }
+            return ERR_CANNOT_CONNECT;
         }
-        // If the SSL handshake was done with anything protocol other than the default,
-        // save that information so that any subsequent requests do not have to do thesame thing.
-        if (trySslVersion != KTcpSocket::SecureProtocols && lastSslVerson == KTcpSocket::SecureProtocols) {
-            setMetaData(QStringLiteral("{internal~currenthost}LastUsedSslVersion"),
-                        QString::number(trySslVersion));
-        }
-        return 0;
     }
-    Q_ASSERT(false);
-    // Code flow never gets here but let's make the compiler happy.
-    // More: the stack allocation of QSslSettings seems to be confusing the compiler;
-    //       in fact, any non-POD allocation does.
-    //       even a 'return 0;' directly after the allocation (so before the while(true))
-    //       is ignored. definitely seems to be a compiler bug? - aseigo
     return 0;
 }
 

Attachment: signature.asc
Description: This is a digitally signed message part.


Reply to: