[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [kio] src/core: - Add support for TLSv1.1 and TLSv1.2 protocols.
From:       Dawit Alemayehu <adawit () kde ! org>
Date:       2015-01-18 12:43:23
Message-ID: E1YCpCN-00012d-8S () scm ! kde ! org
[Download RAW message or body]

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::SslProtocol 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 >= 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 >= 0x040800
+    validVersions |= KTcpSocket::TlsV1_1;
+    validVersions |= KTcpSocket::TlsV1_2;
     validVersions |= KTcpSocket::TlsV1SslV3;
     validVersions |= 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 >= 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::SslVersion \
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 &fileName, \
QSsl::EncodingForm  
 void KTcpSocket::setVerificationPeerName(const QString &hostName)
 {
-#if QT_VERSION >= 0x040800
     d->sock.setPeerVerifyName(hostName);
-#else
-    Q_UNUSED(hostName);
-#endif
 }
 
 void KTcpSocket::setPrivateKey(const KSslKey &key)
@@ -805,7 +824,12 @@ KTcpSocket::SslVersion KTcpSocket::negotiatedSslVersion() const
     if (!d->sock.isEncrypted()) {
         return UnknownSslVersion;
     }
+
+#if QT_VERSION >= 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 >= 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 = 0x08,
         TlsV1SslV3 = 0x10,
         SecureProtocols = 0x20,
+        TlsV1_0 = TlsV1,
+        TlsV1_1 = 0x40,
+        TlsV1_2 = 0x80,
         AnySslVersion = SslV2 | SslV3 | TlsV1
     };
     Q_DECLARE_FLAGS(SslVersions, SslVersion)
+
     enum Error {
         UnknownError = 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 = QSslConfiguration(),
                                int waitForEncryptedTimeout = -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 order shown:
+       SSL handshake is attempted in the following order:
 
-       1.) Protocol: KTcpSocket::SecureProtocols   SSL compression: OFF (DEFAULT)
-       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 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();
+       Note that we indivially attempt connection with each TLS version
+       because some sites don't support SSL negotiation. #275524
 
-#if QT_VERSION >= 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 = config()->readEntry("LastUsedSslVersion", \
                static_cast<int>(KTcpSocket::SecureProtocols));
     KTcpSocket::SslVersion trySslVersion = static_cast<KTcpSocket::SslVersion>(lastSslVerson);
@@ -394,7 +390,7 @@ int TCPSlaveBase::connectToHost(const QString &host, quint16 port, QString \
*erro  d->port = d->socket.peerPort();
 
         if (d->autoSSL) {
-            SslResult res = d->startTLSInternal(trySslVersion, sslConfig, timeout);
+            SslResult res = d->startTLSInternal(trySslVersion, timeout);
             if ((res & ResultFailed) && (res & ResultFailedEarly)) {
                 if (!(alreadyTriedSslVersions & KTcpSocket::SecureProtocols)) {
                     trySslVersion = 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 = KTcpSocket::TlsV1;
                     alreadyTriedSslVersions |= trySslVersion;
                     continue;
                 }
 
-                if (!(alreadyTriedSslVersions & KTcpSocket::SslV3)) {
-                    trySslVersion = KTcpSocket::SslV3;
+                if (!(alreadyTriedSslVersions & KTcpSocket::TlsV1_1)) {
+                    trySslVersion = KTcpSocket::TlsV1;
+                    alreadyTriedSslVersions |= trySslVersion;
+                    continue;
+                }
+
+                if (!(alreadyTriedSslVersions & KTcpSocket::TlsV1_0)) {
+                    trySslVersion = KTcpSocket::TlsV1_0;
                     alreadyTriedSslVersions |= trySslVersion;
                     continue;
                 }
@@ -493,26 +495,17 @@ bool TCPSlaveBase::startSsl()
 }
 
 TCPSlaveBase::SslResult \
                TCPSlaveBase::TcpSlaveBasePrivate::startTLSInternal(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 = true;
-#if QT_VERSION >= 0x040800
-    /*qDebug() << "Trying SSL handshake with protocol:" << version
-      << ", SSL compression ON:" << \
                sslConfig.testSslOption(QSsl::SslOptionDisableCompression);*/
-#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 the sslErrors()
        signal but that would mess up the flow of control. We will check for errors
        anyway to decide if we want to continue connecting. Otherwise ignoreSslErrors()


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic