changeset 990:2949f1842955

(issue90) Add possibility to force cipher suites in bare connection and test for this
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 01 Sep 2014 12:04:11 +0200
parents 1cd1bfe82fc2
children 6a3d284b9c16
files ui/CMakeLists.txt ui/downloader.cpp ui/downloader.h ui/sslconnection.cpp ui/sslconnection.h ui/sslconnection_bare.cpp ui/sslconnection_bare.h ui/tests/downloadertest.cpp ui/tests/downloadertest.h
diffstat 9 files changed, 132 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/ui/CMakeLists.txt	Fri Aug 29 19:18:31 2014 +0200
+++ b/ui/CMakeLists.txt	Mon Sep 01 12:04:11 2014 +0200
@@ -23,6 +23,7 @@
     ${CMAKE_CURRENT_SOURCE_DIR}/certificate.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/downloader.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/sslconnection_bare.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/sslconnection.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/sslhelp.cpp
 )
 
--- a/ui/downloader.cpp	Fri Aug 29 19:18:31 2014 +0200
+++ b/ui/downloader.cpp	Mon Sep 01 12:04:11 2014 +0200
@@ -25,6 +25,7 @@
 #include <polarssl/ctr_drbg.h>
 #include <polarssl/error.h>
 #include <polarssl/certs.h>
+#include <polarssl/ssl_ciphersuites.h>
 
 #define MAX_SW_SIZE 15728640
 #define MAX_LIST_SIZE 1048576
@@ -35,6 +36,25 @@
 #include "sslconnection_bare.h"
 #endif
 
+#ifdef RELEASE_BUILD
+static int accept_ciphers[] = {
+    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
+    TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+    TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
+    0
+};
+#else
+static int accept_ciphers[] = {
+    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
+    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+    TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
+    TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
+    TLS_RSA_WITH_AES_256_CBC_SHA,
+    0
+};
+#endif
+
 Downloader::Downloader(QObject* parent, const QString& url,
                        const QByteArray& certificate,
                        const QDateTime& newestSW,
@@ -66,13 +86,17 @@
 #else
     mSSLConnection = new SSLConnectionBare(url, certificate);
 #endif
+    setCiphersuites(accept_ciphers);
 }
 
-
 Downloader::~Downloader() {
     delete mSSLConnection;
 }
 
+void Downloader::setCiphersuites(int suites[]) {
+    mSSLConnection->setCiphersuites(suites);
+}
+
 QString Downloader::getDataDirectory()
 {
     QString candidate =
--- a/ui/downloader.h	Fri Aug 29 19:18:31 2014 +0200
+++ b/ui/downloader.h	Mon Sep 01 12:04:11 2014 +0200
@@ -71,6 +71,14 @@
      **/
     SSLConnection::ErrorCode getErrorState();
 
+
+    /**
+     * @brief forward the setCiphersuites call to the sslconnection
+     *
+     * see sslconnection.h for details.
+     */
+    void setCiphersuites(int suites[]);
+
 protected:
     void run();
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/sslconnection.cpp	Mon Sep 01 12:04:11 2014 +0200
@@ -0,0 +1,42 @@
+/* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik
+ * Software engineering by Intevation GmbH
+ *
+ * This file is Free Software under the GNU GPL (v>=2)
+ * and comes with ABSOLUTELY NO WARRANTY!
+ * See LICENSE.txt for details.
+ */
+
+/**@file base implemetation of sslconnection. */
+
+#include "sslconnection.h"
+
+#include <QFile>
+
+SSLConnection::SSLConnection(const QString& url,
+              const QByteArray& certificate) :
+    mUrl(url),
+    mPinnedCert(certificate),
+    mInitialized(false),
+    mConnected(false),
+    mNeedsReset(false),
+    mServerFD(-1),
+    mErrorState(NoError)
+{
+    if (certificate.isEmpty()) {
+#ifdef RELEASE_BUILD
+        /* TODO Change certificate here in case of release build */
+        QFile certResource(":certs/intevation.de");
+#else
+        QFile certResource(":certs/intevation.de");
+#endif
+        certResource.open(QFile::ReadOnly);
+        mPinnedCert = certResource.readAll();
+        certResource.close();
+    }
+}
+
+void SSLConnection::setProxy(const QUrl &proxyUrl)
+{
+    Q_UNUSED(proxyUrl);
+    qWarning() << "Set proxy not supported";
+}
--- a/ui/sslconnection.h	Fri Aug 29 19:18:31 2014 +0200
+++ b/ui/sslconnection.h	Mon Sep 01 12:04:11 2014 +0200
@@ -40,14 +40,7 @@
      * @param[in] certificate optional certificate to validate https connection
      */
     SSLConnection(const QString& url,
-                  const QByteArray& certificate = QByteArray()) :
-        mUrl(url),
-        mPinnedCert(certificate),
-        mInitialized(false),
-        mConnected(false),
-        mNeedsReset(false),
-        mServerFD(-1),
-        mErrorState(NoError) {};
+                  const QByteArray& certificate = QByteArray());
 
     virtual ~SSLConnection() {};
 
@@ -91,9 +84,14 @@
      *
      * @param [in] proxyUrl theo URL of the proxy to use.
      */
-    virtual void setProxy(const QUrl &proxyUrl) {
-        qWarning() << "Set proxy not supported";
-    }
+    virtual void setProxy(const QUrl &proxyUrl);
+
+    /** @brief Set acceptable ciphersuites.
+     *
+     * @param [in] cipers a zero terminated list of ciphers as defined in 
+     * polarssl/ssl_ciphersuites.h
+     */
+    virtual void setCiphersuites(int ciphers[]) = 0;
 
 protected:
     QUrl mUrl;
--- a/ui/sslconnection_bare.cpp	Fri Aug 29 19:18:31 2014 +0200
+++ b/ui/sslconnection_bare.cpp	Mon Sep 01 12:04:11 2014 +0200
@@ -35,13 +35,6 @@
     memset(&mSSL, 0, sizeof(ssl_context));
     memset(&mSavedSession, 0, sizeof( ssl_session ) );
 
-    if (certificate.isEmpty()) {
-        QFile certResource(":certs/intevation.de");
-        certResource.open(QFile::ReadOnly);
-        mPinnedCert = certResource.readAll();
-        certResource.close();
-    }
-
     ret = init();
     if (ret == 0) {
         mInitialized = true;
@@ -475,3 +468,8 @@
     return outputFile.commit();
 }
 
+void SSLConnectionBare::setCiphersuites(int ciphers[]) {
+    if (mInitialized) {
+        ssl_set_ciphersuites(&mSSL, ciphers);
+    }
+}
--- a/ui/sslconnection_bare.h	Fri Aug 29 19:18:31 2014 +0200
+++ b/ui/sslconnection_bare.h	Mon Sep 01 12:04:11 2014 +0200
@@ -39,6 +39,8 @@
     bool downloadFile(const QString &resource, const QString &filename,
                       size_t maxSize);
 
+    void setCiphersuites(int ciphers[]);
+
 private:
     x509_crt mX509PinnedCert;
     entropy_context mEntropy;
--- a/ui/tests/downloadertest.cpp	Fri Aug 29 19:18:31 2014 +0200
+++ b/ui/tests/downloadertest.cpp	Mon Sep 01 12:04:11 2014 +0200
@@ -9,6 +9,7 @@
 #include "downloader.h"
 #include "common.h"
 
+#include <polarssl/ssl_ciphersuites.h>
 #include <QTextStream>
 #include <QFile>
 #include <QVariant>
@@ -148,6 +149,44 @@
     QVERIFY(error == SSLConnection::NoConnection);
 }
 
+void DownloaderTest::testForcedCiphers()
+{
+    Downloader* downloader = new Downloader(this,
+            QString::fromLatin1("https://files.intevation.de:443"),
+            QByteArray(), /* Use default testing certificate */
+            QDateTime::currentDateTime(),
+            QDateTime::fromString("2010", "YYYY"),
+            "/users/aheinecke/development/TrustBridge-development.exe",
+            "/users/aheinecke/development/zertifikatsliste.txt");
+    int accept_ciphers[] = {
+        TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
+        TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+        TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
+        0
+    };
+
+    downloader->setCiphersuites(accept_ciphers);
+
+    SETUP_SPY
+
+    downloader->start();
+
+    int waited = 0;
+    while (errors.count() == 0  && waited < MAX_WAIT) {
+        QTest::qWait(200);
+        waited++;
+    }
+    QVERIFY(waited != MAX_WAIT);
+    QVERIFY(newListAvailable.count() == 0);
+    QVERIFY(newSoftwareAvailable.count() == 0);
+
+    QList<QVariant> arguments = errors.takeFirst();
+
+    int error = arguments.at(1).toInt();
+
+    QVERIFY(error == SSLConnection::SSLHandshakeFailed);
+}
+
 void DownloaderTest::testNewSoftware()
 {
     QFile validCert(QString::fromLatin1(SOURCE_DIR) +
--- a/ui/tests/downloadertest.h	Fri Aug 29 19:18:31 2014 +0200
+++ b/ui/tests/downloadertest.h	Mon Sep 01 12:04:11 2014 +0200
@@ -36,6 +36,7 @@
     void testNoConnection();
     void testOtherCertificate();
     void testNewSoftware();
+    void testForcedCiphers();
 };
 #endif
 

http://wald.intevation.org/projects/trustbridge/