# HG changeset patch # User Andre Heinecke # Date 1409565851 -7200 # Node ID 2949f18429553f5894689cf5e9b26c4aa1ab0b3a # Parent 1cd1bfe82fc2e1a8a1602d3201449639e6fbc2cd (issue90) Add possibility to force cipher suites in bare connection and test for this diff -r 1cd1bfe82fc2 -r 2949f1842955 ui/CMakeLists.txt --- 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 ) diff -r 1cd1bfe82fc2 -r 2949f1842955 ui/downloader.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 #include #include +#include #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 = diff -r 1cd1bfe82fc2 -r 2949f1842955 ui/downloader.h --- 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(); diff -r 1cd1bfe82fc2 -r 2949f1842955 ui/sslconnection.cpp --- /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 + +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"; +} diff -r 1cd1bfe82fc2 -r 2949f1842955 ui/sslconnection.h --- 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; diff -r 1cd1bfe82fc2 -r 2949f1842955 ui/sslconnection_bare.cpp --- 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); + } +} diff -r 1cd1bfe82fc2 -r 2949f1842955 ui/sslconnection_bare.h --- 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; diff -r 1cd1bfe82fc2 -r 2949f1842955 ui/tests/downloadertest.cpp --- 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 #include #include #include @@ -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 arguments = errors.takeFirst(); + + int error = arguments.at(1).toInt(); + + QVERIFY(error == SSLConnection::SSLHandshakeFailed); +} + void DownloaderTest::testNewSoftware() { QFile validCert(QString::fromLatin1(SOURCE_DIR) + diff -r 1cd1bfe82fc2 -r 2949f1842955 ui/tests/downloadertest.h --- 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