Package: libkio5 Version: 4:4.14.26-2 Severity: important Tags: patch 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]. I backported the patch from [2] for the kio code in kde4libs. Please also consider 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/kio/kio/tcpslavebase.cpp +++ b/kio/kio/tcpslavebase.cpp @@ -349,106 +349,50 @@ } } - /* - By default the SSL handshake attempt uses these settings in the order shown: - - 1.) Protocol: KTcpSocket::SecureProtocols SSL compression: OFF (DEFAULT) - 2.) Protocol: KTcpSocket::TlsV1 SSL compression: OFF - 3.) Protocol: KTcpSocket::SslV3 SSL compression: OFF - - If any combination other than the one marked DEFAULT is used to complete - the SSL handshake, then that combination will be cached using KIO's internal - meta-data mechanism in order to speed up future connections to the same host. - */ - QSslConfiguration sslConfig = d->socket.sslConfiguration(); + const int timeout = (connectTimeout() * 1000); // 20 sec timeout value -#if QT_VERSION >= 0x040800 - // NOTE: Due to 'CRIME' SSL attacks, compression is always disabled. - sslConfig.setSslOption(QSsl::SslOptionDisableCompression, true); -#endif - - 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); - - kDebug(7027) << "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_COULD_NOT_CONNECT; - } + kDebug(7027) << "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_COULD_NOT_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, sslConfig, timeout); - if ((res & ResultFailed) && (res & ResultFailedEarly)) { - if (!(alreadyTriedSslVersions & KTcpSocket::SecureProtocols)) { - trySslVersion = KTcpSocket::SecureProtocols; - alreadyTriedSslVersions |= trySslVersion; - continue; - } - - if (!(alreadyTriedSslVersions & KTcpSocket::TlsV1)) { - trySslVersion = KTcpSocket::TlsV1; - alreadyTriedSslVersions |= trySslVersion; - continue; - } - - if (!(alreadyTriedSslVersions & KTcpSocket::SslV3)) { - trySslVersion = KTcpSocket::SslV3; - alreadyTriedSslVersions |= trySslVersion; - continue; - } - } - - //### 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_COULD_NOT_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(QLatin1String("{internal~currenthost}LastUsedSslVersion"), - QString::number(trySslVersion)); + if (d->autoSSL) { + SslResult res = d->startTLSInternal(KTcpSocket::SecureProtocols, sslConfig, timeout); + + if (res & ResultFailed) { + if (errorString) + *errorString = i18nc("%1 is a host name", "%1: SSL negotiation failed", host); + return ERR_COULD_NOT_CONNECT; } - 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; }
signature.asc
Description: This is a digitally signed message part.