aheinecke@404: /* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik aheinecke@404: * Software engineering by Intevation GmbH aheinecke@404: * aheinecke@404: * This file is Free Software under the GNU GPL (v>=2) aheinecke@404: * and comes with ABSOLUTELY NO WARRANTY! aheinecke@404: * See LICENSE.txt for details. aheinecke@404: */ aheinecke@43: #include "downloadertest.h" aheinecke@43: #include "downloader.h" aheinecke@240: #include "common.h" aheinecke@43: andre@990: #include aheinecke@43: #include aheinecke@43: #include aheinecke@48: #include aheinecke@240: #include aheinecke@43: aheinecke@51: #define MAX_WAIT 20 aheinecke@51: aheinecke@51: #define SETUP_SPY \ aheinecke@51: QSignalSpy newListAvailable(downloader, \ aheinecke@51: SIGNAL(newListAvailable(const QString&, const QDateTime&))); \ aheinecke@51: QSignalSpy newSoftwareAvailable(downloader, \ aheinecke@51: SIGNAL(newSoftwareAvailable(const QString&, const QDateTime&))); \ aheinecke@51: QSignalSpy errors(downloader, SIGNAL(error(const QString &, \ aheinecke@51: SSLConnection::ErrorCode))); \ aheinecke@51: aheinecke@43: void DownloaderTest::startServer(QString additionalOptions) aheinecke@43: { aheinecke@43: QFile serverConfig(serverConfigDir.path() + "/" + "hiawatha.conf"); aheinecke@43: QFile mimeConfig(serverConfigDir.path() + "/" + "mimetype.conf"); aheinecke@43: if (serverProc.state() == QProcess::Running) { aheinecke@43: serverProc.close(); aheinecke@43: } aheinecke@43: serverConfig.open(QIODevice::WriteOnly); aheinecke@43: mimeConfig.open(QIODevice::WriteOnly); aheinecke@43: mimeConfig.close(); /* just an empty file */ aheinecke@43: aheinecke@43: QTextStream configStream(&serverConfig); aheinecke@43: configStream << aheinecke@43: "Binding { " << endl << aheinecke@43: "Port = 44443 " << endl << aheinecke@43: "SSLcertFile = " << SOURCE_DIR << aheinecke@43: "/data/valid_ssl_bp_priv.pem" << endl << aheinecke@43: "Interface = 127.0.0.1" << endl << aheinecke@43: "}" << endl << aheinecke@43: "Hostname = 127.0.0.1" << endl << aheinecke@240: "WebsiteRoot = " << serverConfigDir.path() << endl; aheinecke@43: configStream.flush(); aheinecke@43: aheinecke@43: serverConfig.close(); aheinecke@43: serverProc.start(); aheinecke@43: serverProc.waitForStarted(); aheinecke@43: } aheinecke@43: aheinecke@43: void DownloaderTest::initTestCase() { aheinecke@43: QStringList arguments; aheinecke@43: serverProc.setProgram(HIAWATHA_EXECUTABLE); aheinecke@43: arguments << "-d" << "-c" << serverConfigDir.path(); aheinecke@43: serverProc.setArguments(arguments); aheinecke@45: qRegisterMetaType("SSLConnection::ErrorCode"); aheinecke@43: startServer(); aheinecke@240: garbageInfo = QFileInfo(getRandomDataFile(2 * 1024, serverConfigDir.path())); aheinecke@240: QVERIFY(QFile::copy(QString::fromLocal8Bit(SOURCE_DIR"/data/list-valid.txt"), aheinecke@240: serverConfigDir.path() + "/" + "list-valid.txt")); aheinecke@240: aheinecke@43: QTest::qWait(1000); /* Wait for the server to settle */ aheinecke@43: } aheinecke@43: aheinecke@45: void DownloaderTest::downloaderError(const QString &message, SSLConnection::ErrorCode error) aheinecke@43: { aheinecke@43: qDebug() << "Downloader Error: " << error << " Msg: " << message; aheinecke@43: } aheinecke@43: aheinecke@47: bool filesEqual(QString filename1, QString filename2) aheinecke@47: { aheinecke@47: bool retval = false; aheinecke@47: QFile file1(filename1); aheinecke@47: QFile file2(filename2); aheinecke@47: file1.open(QIODevice::ReadOnly); aheinecke@47: file2.open(QIODevice::ReadOnly); aheinecke@47: aheinecke@47: retval = (file1.readAll() == file2.readAll()); aheinecke@47: file1.close(); aheinecke@47: file2.close(); aheinecke@47: return retval; aheinecke@47: } aheinecke@47: aheinecke@52: void DownloaderTest::testOtherCertificate() aheinecke@52: { aheinecke@52: QFile otherCert(QString::fromLatin1(SOURCE_DIR) + aheinecke@52: "/data/valid_ssl_rsa.pem"); aheinecke@52: otherCert.open(QIODevice::ReadOnly); aheinecke@52: aheinecke@240: QFileInfo fi(getRandomDataFile(200)); aheinecke@240: aheinecke@52: Downloader* downloader = new Downloader(this, andre@910: QString::fromLatin1("https://127.0.0.1:44443"), aheinecke@52: otherCert.readAll(), aheinecke@52: QDateTime::currentDateTime(), // Last installed SW aheinecke@52: QDateTime::fromString("2010", "YYYY"), aheinecke@240: "/" + garbageInfo.fileName(), aheinecke@52: "/list-valid.txt"); aheinecke@52: otherCert.close(); aheinecke@52: aheinecke@52: SETUP_SPY aheinecke@52: aheinecke@52: downloader->start(); aheinecke@52: aheinecke@52: int waited = 0; aheinecke@52: while (errors.count() == 0 && waited < MAX_WAIT) { aheinecke@52: QTest::qWait(200); aheinecke@52: waited++; aheinecke@52: } aheinecke@52: QVERIFY(waited != MAX_WAIT); aheinecke@52: QVERIFY(newListAvailable.count() == 0); aheinecke@52: QVERIFY(newSoftwareAvailable.count() == 0); aheinecke@52: aheinecke@52: QList arguments = errors.takeFirst(); aheinecke@52: aheinecke@52: int error = arguments.at(1).toInt(); aheinecke@52: aheinecke@52: QVERIFY(error == SSLConnection::InvalidCertificate); aheinecke@52: } aheinecke@52: aheinecke@48: void DownloaderTest::testNoConnection() aheinecke@48: { aheinecke@48: Downloader* downloader = new Downloader(this, aheinecke@48: QString::fromLatin1("https://foobar.intevation.de")); aheinecke@51: aheinecke@51: SETUP_SPY aheinecke@51: aheinecke@48: downloader->start(); aheinecke@48: aheinecke@48: int waited = 0; aheinecke@48: while (newListAvailable.count() == 0 && aheinecke@51: errors.count() == 0 && waited < MAX_WAIT) { aheinecke@48: QTest::qWait(200); aheinecke@48: waited++; aheinecke@48: } aheinecke@51: QVERIFY(waited != MAX_WAIT); aheinecke@51: QVERIFY(newListAvailable.count() == 0); aheinecke@51: QVERIFY(newSoftwareAvailable.count() == 0); aheinecke@48: aheinecke@48: QList arguments = errors.takeFirst(); aheinecke@48: aheinecke@48: int error = arguments.at(1).toInt(); aheinecke@48: aheinecke@48: QVERIFY(error == SSLConnection::NoConnection); aheinecke@48: } aheinecke@48: andre@990: void DownloaderTest::testForcedCiphers() andre@990: { andre@990: Downloader* downloader = new Downloader(this, andre@990: QString::fromLatin1("https://files.intevation.de:443"), andre@990: QByteArray(), /* Use default testing certificate */ andre@990: QDateTime::currentDateTime(), andre@990: QDateTime::fromString("2010", "YYYY"), andre@990: "/users/aheinecke/development/TrustBridge-development.exe", andre@990: "/users/aheinecke/development/zertifikatsliste.txt"); andre@990: int accept_ciphers[] = { andre@990: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, andre@990: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, andre@990: TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, andre@990: 0 andre@990: }; andre@990: andre@990: downloader->setCiphersuites(accept_ciphers); andre@990: andre@990: SETUP_SPY andre@990: andre@990: downloader->start(); andre@990: andre@990: int waited = 0; andre@990: while (errors.count() == 0 && waited < MAX_WAIT) { andre@990: QTest::qWait(200); andre@990: waited++; andre@990: } andre@990: QVERIFY(waited != MAX_WAIT); andre@990: QVERIFY(newListAvailable.count() == 0); andre@990: QVERIFY(newSoftwareAvailable.count() == 0); andre@990: andre@990: QList arguments = errors.takeFirst(); andre@990: andre@990: int error = arguments.at(1).toInt(); andre@990: andre@990: QVERIFY(error == SSLConnection::SSLHandshakeFailed); andre@990: } andre@990: aheinecke@55: void DownloaderTest::testNewSoftware() aheinecke@55: { aheinecke@55: QFile validCert(QString::fromLatin1(SOURCE_DIR) + aheinecke@55: "/data/valid_ssl_bp.pem"); aheinecke@55: validCert.open(QIODevice::ReadOnly); aheinecke@55: aheinecke@55: Downloader* downloader = new Downloader(this, andre@910: QString::fromLatin1("https://127.0.0.1:44443"), aheinecke@55: validCert.readAll(), aheinecke@55: QDateTime::fromString("2010", "YYYY"), aheinecke@55: QDateTime::currentDateTime(), aheinecke@240: "/" + garbageInfo.fileName(), aheinecke@55: "/list-valid.txt"); aheinecke@55: validCert.close(); aheinecke@55: aheinecke@55: SETUP_SPY aheinecke@55: aheinecke@55: connect(downloader, SIGNAL(error(const QString &, SSLConnection::ErrorCode)), aheinecke@55: this, SLOT(downloaderError(const QString &, SSLConnection::ErrorCode))); aheinecke@55: aheinecke@55: downloader->start(); aheinecke@55: aheinecke@55: int waited = 0; aheinecke@55: while (newSoftwareAvailable.count() == 0 && aheinecke@55: errors.count() == 0 && waited < 20) { aheinecke@55: QTest::qWait(200); aheinecke@55: waited++; aheinecke@55: } aheinecke@55: QVERIFY(waited != 20); aheinecke@55: QVERIFY(newListAvailable.count() == 0); aheinecke@55: QVERIFY(newSoftwareAvailable.count() == 1); aheinecke@55: QVERIFY(errors.count() == 0); aheinecke@55: aheinecke@55: QList arguments = newSoftwareAvailable.takeFirst(); aheinecke@55: aheinecke@240: QVERIFY(filesEqual(serverConfigDir.path() + "/" + garbageInfo.fileName(), aheinecke@55: arguments.at(0).toString())); aheinecke@55: aheinecke@55: delete downloader; aheinecke@55: } aheinecke@55: andre@994: void DownloaderTest::testDefaultUrl() andre@994: { andre@994: /* This test might fail if SERVER_URL is configured differently andre@994: * and needs to be adapted once there is a public download server. andre@994: * This test also needs internet connectivity. */ andre@994: Downloader* downloader = new Downloader(this, andre@994: QString::fromLatin1(SERVER_URL), andre@994: QByteArray(), andre@994: QDateTime::currentDateTime(), // Last installed SW andre@994: QDateTime::fromString("2010", "YYYY"), andre@994: QString("/users/aheinecke/zertifikatsliste.txt"), andre@994: QString("/users/aheinecke/zertifikatsliste.txt")); andre@994: andre@994: SETUP_SPY andre@994: andre@994: connect(downloader, SIGNAL(error(const QString &, SSLConnection::ErrorCode)), andre@994: this, SLOT(downloaderError(const QString &, SSLConnection::ErrorCode))); andre@994: andre@994: downloader->start(); andre@994: andre@994: int waited = 0; andre@994: while (newListAvailable.count() == 0 && andre@994: errors.count() == 0 && waited < 20) { andre@994: QTest::qWait(200); andre@994: waited++; andre@994: } andre@994: QVERIFY(waited != 20); andre@994: QVERIFY(newListAvailable.count() == 1); andre@994: QVERIFY(newSoftwareAvailable.count() == 0); andre@994: QVERIFY(errors.count() == 0); andre@994: andre@994: delete downloader; andre@994: } andre@994: aheinecke@43: void DownloaderTest::testNewList() aheinecke@43: { aheinecke@43: QFile validCert(QString::fromLatin1(SOURCE_DIR) + aheinecke@43: "/data/valid_ssl_bp.pem"); aheinecke@43: validCert.open(QIODevice::ReadOnly); aheinecke@43: aheinecke@43: Downloader* downloader = new Downloader(this, andre@910: QString::fromLatin1("https://127.0.0.1:44443"), aheinecke@43: validCert.readAll(), aheinecke@43: QDateTime::currentDateTime(), // Last installed SW aheinecke@43: QDateTime::fromString("2010", "YYYY"), aheinecke@240: "/" + garbageInfo.fileName(), aheinecke@46: "/list-valid.txt"); aheinecke@43: validCert.close(); aheinecke@43: aheinecke@51: SETUP_SPY aheinecke@51: aheinecke@45: connect(downloader, SIGNAL(error(const QString &, SSLConnection::ErrorCode)), aheinecke@45: this, SLOT(downloaderError(const QString &, SSLConnection::ErrorCode))); aheinecke@43: aheinecke@43: downloader->start(); aheinecke@43: aheinecke@43: int waited = 0; aheinecke@43: while (newListAvailable.count() == 0 && aheinecke@43: errors.count() == 0 && waited < 20) { aheinecke@48: QTest::qWait(200); aheinecke@43: waited++; aheinecke@43: } aheinecke@43: QVERIFY(waited != 20); aheinecke@43: QVERIFY(newListAvailable.count() == 1); aheinecke@43: QVERIFY(newSoftwareAvailable.count() == 0); aheinecke@43: QVERIFY(errors.count() == 0); aheinecke@47: aheinecke@47: QList arguments = newListAvailable.takeFirst(); aheinecke@47: aheinecke@47: QVERIFY(filesEqual(QString::fromLatin1(SOURCE_DIR) + "/data/list-valid.txt", aheinecke@47: arguments.at(0).toString())); aheinecke@47: aheinecke@43: delete downloader; aheinecke@43: } aheinecke@43: aheinecke@43: void DownloaderTest::cleanupTestCase() { aheinecke@43: if (serverProc.state() == QProcess::Running) { aheinecke@43: serverProc.close(); aheinecke@43: } aheinecke@43: } aheinecke@43: aheinecke@43: QTEST_GUILESS_MAIN (DownloaderTest); aheinecke@43: