[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