Mercurial > trustbridge
view ui/tests/downloadertest.cpp @ 999:daa9448b64f5
(issue90) Use certificate pinning and forced ciphersuites for curl
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 01 Sep 2014 19:49:54 +0200 |
parents | 8fb1b912fd8e |
children | fe2c6666b462 |
line wrap: on
line source
/* 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. */ #include "downloadertest.h" #include "downloader.h" #include "common.h" #include <polarssl/ssl_ciphersuites.h> #include <QTextStream> #include <QFile> #include <QVariant> #include <unistd.h> #define MAX_WAIT 20 #define SETUP_SPY \ QSignalSpy newListAvailable(downloader, \ SIGNAL(newListAvailable(const QString&, const QDateTime&))); \ QSignalSpy newSoftwareAvailable(downloader, \ SIGNAL(newSoftwareAvailable(const QString&, const QDateTime&))); \ QSignalSpy errors(downloader, SIGNAL(error(const QString &, \ SSLConnection::ErrorCode))); \ void DownloaderTest::startServer(QString additionalOptions) { QFile serverConfig(serverConfigDir.path() + "/" + "hiawatha.conf"); QFile mimeConfig(serverConfigDir.path() + "/" + "mimetype.conf"); if (serverProc.state() == QProcess::Running) { serverProc.close(); } serverConfig.open(QIODevice::WriteOnly); mimeConfig.open(QIODevice::WriteOnly); mimeConfig.close(); /* just an empty file */ QTextStream configStream(&serverConfig); configStream << "Binding { " << endl << "Port = 44443 " << endl << "SSLcertFile = " << SOURCE_DIR << "/data/valid_ssl_bp_priv.pem" << endl << "Interface = 127.0.0.1" << endl << "}" << endl << "Hostname = 127.0.0.1" << endl << "WebsiteRoot = " << serverConfigDir.path() << endl; configStream.flush(); serverConfig.close(); serverProc.start(); serverProc.waitForStarted(); } void DownloaderTest::initTestCase() { QStringList arguments; serverProc.setProgram(HIAWATHA_EXECUTABLE); arguments << "-d" << "-c" << serverConfigDir.path(); serverProc.setArguments(arguments); qRegisterMetaType<SSLConnection::ErrorCode>("SSLConnection::ErrorCode"); startServer(); garbageInfo = QFileInfo(getRandomDataFile(2 * 1024, serverConfigDir.path())); QVERIFY(QFile::copy(QString::fromLocal8Bit(SOURCE_DIR"/data/list-valid.txt"), serverConfigDir.path() + "/" + "list-valid.txt")); QTest::qWait(1000); /* Wait for the server to settle */ } void DownloaderTest::downloaderError(const QString &message, SSLConnection::ErrorCode error) { qDebug() << "Downloader Error: " << error << " Msg: " << message; } bool filesEqual(QString filename1, QString filename2) { bool retval = false; QFile file1(filename1); QFile file2(filename2); file1.open(QIODevice::ReadOnly); file2.open(QIODevice::ReadOnly); retval = (file1.readAll() == file2.readAll()); file1.close(); file2.close(); return retval; } void DownloaderTest::testOtherCertificate() { QFile otherCert(QString::fromLatin1(SOURCE_DIR) + "/data/valid_ssl_rsa.pem"); otherCert.open(QIODevice::ReadOnly); QFileInfo fi(getRandomDataFile(200)); Downloader* downloader = new Downloader(this, QString::fromLatin1("https://127.0.0.1:44443"), otherCert.readAll(), QDateTime::currentDateTime(), // Last installed SW QDateTime::fromString("2010", "YYYY"), "/" + garbageInfo.fileName(), "/list-valid.txt"); otherCert.close(); 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::InvalidCertificate); } void DownloaderTest::testNoConnection() { Downloader* downloader = new Downloader(this, QString::fromLatin1("https://foobar.intevation.de")); SETUP_SPY downloader->start(); int waited = 0; while (newListAvailable.count() == 0 && 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::NoConnection); } 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 }; void DownloaderTest::testForcedCiphers() { Downloader* downloader = new Downloader(this, QString::fromLatin1(SERVER_URL), QByteArray(), /* Use default testing certificate */ QDateTime::currentDateTime(), QDateTime::fromString("2010", "YYYY"), "/users/aheinecke/development/TrustBridge-development.exe", "/users/aheinecke/development/zertifikatsliste.txt"); 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) + "/data/valid_ssl_bp.pem"); validCert.open(QIODevice::ReadOnly); Downloader* downloader = new Downloader(this, QString::fromLatin1("https://127.0.0.1:44443"), validCert.readAll(), QDateTime::fromString("2010", "YYYY"), QDateTime::currentDateTime(), "/" + garbageInfo.fileName(), "/list-valid.txt"); validCert.close(); SETUP_SPY connect(downloader, SIGNAL(error(const QString &, SSLConnection::ErrorCode)), this, SLOT(downloaderError(const QString &, SSLConnection::ErrorCode))); downloader->start(); int waited = 0; while (newSoftwareAvailable.count() == 0 && errors.count() == 0 && waited < 20) { QTest::qWait(200); waited++; } QVERIFY(waited != 20); QVERIFY(newListAvailable.count() == 0); QVERIFY(newSoftwareAvailable.count() == 1); QVERIFY(errors.count() == 0); QList<QVariant> arguments = newSoftwareAvailable.takeFirst(); QVERIFY(filesEqual(serverConfigDir.path() + "/" + garbageInfo.fileName(), arguments.at(0).toString())); delete downloader; } void DownloaderTest::testDefaultUrl() { /* This test might fail if SERVER_URL is configured differently * and needs to be adapted once there is a public download server. * This test also needs internet connectivity. */ Downloader* downloader = new Downloader(this, QString::fromLatin1(SERVER_URL), QByteArray(), QDateTime::currentDateTime(), // Last installed SW QDateTime::fromString("2010", "YYYY"), QString("/users/aheinecke/zertifikatsliste.txt"), QString("/users/aheinecke/zertifikatsliste.txt")); SETUP_SPY connect(downloader, SIGNAL(error(const QString &, SSLConnection::ErrorCode)), this, SLOT(downloaderError(const QString &, SSLConnection::ErrorCode))); downloader->start(); int waited = 0; while (newListAvailable.count() == 0 && errors.count() == 0 && waited < 20) { QTest::qWait(200); waited++; } QVERIFY(waited != 20); QVERIFY(newListAvailable.count() == 1); QVERIFY(newSoftwareAvailable.count() == 0); QVERIFY(errors.count() == 0); delete downloader; } void DownloaderTest::testNewList() { QFile validCert(QString::fromLatin1(SOURCE_DIR) + "/data/valid_ssl_bp.pem"); validCert.open(QIODevice::ReadOnly); Downloader* downloader = new Downloader(this, QString::fromLatin1("https://127.0.0.1:44443"), validCert.readAll(), QDateTime::currentDateTime(), // Last installed SW QDateTime::fromString("2010", "YYYY"), "/" + garbageInfo.fileName(), "/list-valid.txt"); validCert.close(); SETUP_SPY connect(downloader, SIGNAL(error(const QString &, SSLConnection::ErrorCode)), this, SLOT(downloaderError(const QString &, SSLConnection::ErrorCode))); downloader->start(); int waited = 0; while (newListAvailable.count() == 0 && errors.count() == 0 && waited < 20) { QTest::qWait(200); waited++; } QVERIFY(waited != 20); QVERIFY(newListAvailable.count() == 1); QVERIFY(newSoftwareAvailable.count() == 0); QVERIFY(errors.count() == 0); QList<QVariant> arguments = newListAvailable.takeFirst(); QVERIFY(filesEqual(QString::fromLatin1(SOURCE_DIR) + "/data/list-valid.txt", arguments.at(0).toString())); delete downloader; } void DownloaderTest::cleanupTestCase() { if (serverProc.state() == QProcess::Running) { serverProc.close(); } } QTEST_GUILESS_MAIN (DownloaderTest);