From kde-commits Sun Jan 18 12:43:23 2015 From: Dawit Alemayehu Date: Sun, 18 Jan 2015 12:43:23 +0000 To: kde-commits Subject: [kio] src/core: - Add support for TLSv1.1 and TLSv1.2 protocols. Message-Id: X-MARC-Message: https://marc.info/?l=kde-commits&m=142158501505416 Git commit a1be52944f8b7dc99afb1d906b055d5c27863d55 by Dawit Alemayehu. Committed on 12/01/2015 at 03:13. Pushed by adawit into branch 'master'. - Add support for TLSv1.1 and TLSv1.2 protocols. - Fix negotiatedSslVersion and negotiatedSslVersionName to return the actual negotiated protocol. Prior to v5.4, Qt did not provide a means to obtain the actual negotiated protocol. - Removed SSLv3 from manual renegotiation and added TLSv1.1 and TLSv1.2. - Removed explicit disabling of SSL compression since it has been defauled to off in Qt since 4.8.4. REVIEW: 122007 M +40 -11 src/core/ktcpsocket.cpp M +4 -0 src/core/ktcpsocket.h M +23 -30 src/core/tcpslavebase.cpp http://commits.kde.org/kio/a1be52944f8b7dc99afb1d906b055d5c27863d55 diff --git a/src/core/ktcpsocket.cpp b/src/core/ktcpsocket.cpp index f223986..fde35a7 100644 --- a/src/core/ktcpsocket.cpp +++ b/src/core/ktcpsocket.cpp @@ -40,14 +40,16 @@ static KTcpSocket::SslVersion kSslVersionFromQ(QSsl::Ss= lProtocol protocol) return KTcpSocket::SslV3; case QSsl::TlsV1_0: return KTcpSocket::TlsV1; + case QSsl::TlsV1_1: + return KTcpSocket::TlsV1_1; + case QSsl::TlsV1_2: + return KTcpSocket::TlsV1_2; case QSsl::AnyProtocol: return KTcpSocket::AnySslVersion; -#if QT_VERSION >=3D 0x040800 case QSsl::TlsV1SslV3: return KTcpSocket::TlsV1SslV3; case QSsl::SecureProtocols: return KTcpSocket::SecureProtocols; -#endif default: return KTcpSocket::UnknownSslVersion; } @@ -61,10 +63,11 @@ static QSsl::SslProtocol qSslProtocolFromK(KTcpSocket::= SslVersion sslVersion) } //does it contain any valid protocol? KTcpSocket::SslVersions validVersions(KTcpSocket::SslV2 | KTcpSocket::= SslV3 | KTcpSocket::TlsV1); -#if QT_VERSION >=3D 0x040800 + validVersions |=3D KTcpSocket::TlsV1_1; + validVersions |=3D KTcpSocket::TlsV1_2; validVersions |=3D KTcpSocket::TlsV1SslV3; validVersions |=3D KTcpSocket::SecureProtocols; -#endif + if (!(sslVersion & validVersions)) { return QSsl::UnknownProtocol; } @@ -74,14 +77,16 @@ static QSsl::SslProtocol qSslProtocolFromK(KTcpSocket::= SslVersion sslVersion) return QSsl::SslV2; case KTcpSocket::SslV3: return QSsl::SslV3; - case KTcpSocket::TlsV1: + case KTcpSocket::TlsV1_0: return QSsl::TlsV1_0; -#if QT_VERSION >=3D 0x040800 + case KTcpSocket::TlsV1_1: + return QSsl::TlsV1_1; + case KTcpSocket::TlsV1_2: + return QSsl::TlsV1_2; case KTcpSocket::TlsV1SslV3: return QSsl::TlsV1SslV3; case KTcpSocket::SecureProtocols: return QSsl::SecureProtocols; -#endif = default: //QSslSocket doesn't really take arbitrary combinations. It's one = or all. @@ -89,6 +94,24 @@ static QSsl::SslProtocol qSslProtocolFromK(KTcpSocket::S= slVersion sslVersion) } } = +static QString protocolString(QSsl::SslProtocol protocol) +{ + switch (protocol) { + case QSsl::SslV2: + return QLatin1String("SSLv2"); + case QSsl::SslV3: + return QLatin1String("SSLv3"); + case QSsl::TlsV1_0: + return QLatin1String("TLSv1.0"); + case QSsl::TlsV1_1: + return QLatin1String("TLSv1.1"); + case QSsl::TlsV1_2: + return QLatin1String("TLSv1.2"); + default: + return QLatin1String("Unknown");; + } +} + //cipher class converter KSslCipher -> QSslCipher class CipherCc { @@ -702,11 +725,7 @@ void KTcpSocket::setLocalCertificate(const QString &fi= leName, QSsl::EncodingForm = void KTcpSocket::setVerificationPeerName(const QString &hostName) { -#if QT_VERSION >=3D 0x040800 d->sock.setPeerVerifyName(hostName); -#else - Q_UNUSED(hostName); -#endif } = void KTcpSocket::setPrivateKey(const KSslKey &key) @@ -805,7 +824,12 @@ KTcpSocket::SslVersion KTcpSocket::negotiatedSslVersio= n() const if (!d->sock.isEncrypted()) { return UnknownSslVersion; } + +#if QT_VERSION >=3D QT_VERSION_CHECK(5, 4, 0) + return kSslVersionFromQ(d->sock.sessionProtocol()); +#else return kSslVersionFromQ(d->sock.protocol()); +#endif } = QString KTcpSocket::negotiatedSslVersionName() const @@ -813,7 +837,12 @@ QString KTcpSocket::negotiatedSslVersionName() const if (!d->sock.isEncrypted()) { return QString(); } + +#if QT_VERSION >=3D QT_VERSION_CHECK(5, 4, 0) + return protocolString(d->sock.sessionProtocol()); +#else return d->sock.sessionCipher().protocolString(); +#endif } = ////////////////////////////// KSslKey diff --git a/src/core/ktcpsocket.h b/src/core/ktcpsocket.h index d59b180..2faf35c 100644 --- a/src/core/ktcpsocket.h +++ b/src/core/ktcpsocket.h @@ -160,9 +160,13 @@ public: SslV3_1 =3D 0x08, TlsV1SslV3 =3D 0x10, SecureProtocols =3D 0x20, + TlsV1_0 =3D TlsV1, + TlsV1_1 =3D 0x40, + TlsV1_2 =3D 0x80, AnySslVersion =3D SslV2 | SslV3 | TlsV1 }; Q_DECLARE_FLAGS(SslVersions, SslVersion) + enum Error { UnknownError =3D 0, ConnectionRefusedError, diff --git a/src/core/tcpslavebase.cpp b/src/core/tcpslavebase.cpp index e62e72a..751c153 100644 --- a/src/core/tcpslavebase.cpp +++ b/src/core/tcpslavebase.cpp @@ -150,7 +150,6 @@ public: } = SslResult startTLSInternal(KTcpSocket::SslVersion sslVersion, - const QSslConfiguration &configuration =3D = QSslConfiguration(), int waitForEncryptedTimeout =3D -1); = TCPSlaveBase *q; @@ -336,23 +335,20 @@ int TCPSlaveBase::connectToHost(const QString &host, = quint16 port, QString *erro } = /* - By default the SSL handshake attempt uses these settings in the ord= er shown: + SSL handshake is attempted in the following order: = - 1.) Protocol: KTcpSocket::SecureProtocols SSL compression: OFF (D= EFAULT) - 2.) Protocol: KTcpSocket::TlsV1 SSL compression: OFF - 3.) Protocol: KTcpSocket::SslV3 SSL compression: OFF + 1.) KTcpSocket::SecureProtocols + 2.) KTcpSocket::TlsV1_2 + 3.) KTcpSocket::TlsV1_1 + 4.) KTcpSocket::TlsV1_0 = - If any combination other than the one marked DEFAULT is used to com= plete - 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 =3D d->socket.sslConfiguration(); + Note that we indivially attempt connection with each TLS version + because some sites don't support SSL negotiation. #275524 = -#if QT_VERSION >=3D 0x040800 - // NOTE: Due to 'CRIME' SSL attacks, compression is always disabled. - sslConfig.setSslOption(QSsl::SslOptionDisableCompression, true); -#endif + 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 =3D config()->readEntry("LastUsedSslVersion", = static_cast(KTcpSocket::SecureProtocols)); KTcpSocket::SslVersion trySslVersion =3D static_cast(lastSslVerson); @@ -394,7 +390,7 @@ int TCPSlaveBase::connectToHost(const QString &host, qu= int16 port, QString *erro d->port =3D d->socket.peerPort(); = if (d->autoSSL) { - SslResult res =3D d->startTLSInternal(trySslVersion, sslConfig= , timeout); + SslResult res =3D d->startTLSInternal(trySslVersion, timeout); if ((res & ResultFailed) && (res & ResultFailedEarly)) { if (!(alreadyTriedSslVersions & KTcpSocket::SecureProtocol= s)) { trySslVersion =3D KTcpSocket::SecureProtocols; @@ -402,14 +398,20 @@ int TCPSlaveBase::connectToHost(const QString &host, = quint16 port, QString *erro continue; } = - if (!(alreadyTriedSslVersions & KTcpSocket::TlsV1)) { + if (!(alreadyTriedSslVersions & KTcpSocket::TlsV1_2)) { trySslVersion =3D KTcpSocket::TlsV1; alreadyTriedSslVersions |=3D trySslVersion; continue; } = - if (!(alreadyTriedSslVersions & KTcpSocket::SslV3)) { - trySslVersion =3D KTcpSocket::SslV3; + if (!(alreadyTriedSslVersions & KTcpSocket::TlsV1_1)) { + trySslVersion =3D KTcpSocket::TlsV1; + alreadyTriedSslVersions |=3D trySslVersion; + continue; + } + + if (!(alreadyTriedSslVersions & KTcpSocket::TlsV1_0)) { + trySslVersion =3D KTcpSocket::TlsV1_0; alreadyTriedSslVersions |=3D trySslVersion; continue; } @@ -493,26 +495,17 @@ bool TCPSlaveBase::startSsl() } = TCPSlaveBase::SslResult TCPSlaveBase::TcpSlaveBasePrivate::startTLSInterna= l(KTcpSocket::SslVersion version, - const QSslConfiguration &sslConfig, - int waitForEncryptedTimeout) + = int waitForEncryptedTimeout) { q->selectClientCertificate(); = //setMetaData("ssl_session_id", d->kssl->session()->toString()); //### we don't support session reuse for now... usingSSL =3D true; -#if QT_VERSION >=3D 0x040800 - /*qDebug() << "Trying SSL handshake with protocol:" << version - << ", SSL compression ON:" << sslConfig.testSslOption(QSsl::SslOptio= nDisableCompression);*/ -#endif + // Set the SSL version to use... socket.setAdvertisedSslVersion(version); = - // Set SSL configuration information - if (!sslConfig.isNull()) { - socket.setSslConfiguration(sslConfig); - } - /* Usually ignoreSslErrors() would be called in the slot invoked by th= e sslErrors() signal but that would mess up the flow of control. We will check fo= r errors anyway to decide if we want to continue connecting. Otherwise ignor= eSslErrors()