view ui/tests/cinstprocesstest.cpp @ 1400:e18fccc081f1

(issue182) Document applying the patch for CVE-2015-1182
author Andre Heinecke <andre.heinecke@intevation.de>
date Tue, 27 Jan 2015 15:15:19 +0100
parents c8f698ca6355
children
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 "cinstprocesstest.h"
#include "certificatelist.h"
#include "errorcodes.h"
#include "common.h"

#include <QDebug>
#include <QDir>
#include <QFile>
#include <QProcess>

#include <stdlib.h>

#define CINST_PATH_CANDIDATES "../../cinst/trustbridge-certificate-installer" << \
    "trustbridge-certificate-installer" << \
    "../../cinst/trustbridge-certificate-installer.exe" \
    << "trustbridge-certificate-installer.exe";

QProcess *CinstProcessTest::startCinstProcess(const QStringList& args) {
    QStringList cinstCandidates;
    cinstCandidates << CINST_PATH_CANDIDATES;
    QString processPath;
    foreach (const QString& candidate, cinstCandidates) {
        QFileInfo fi(candidate);
        if (fi.isExecutable()) {
            processPath = candidate;
            break;
        }
    }

    QStringList newArgs = args;
    newArgs << "--debug";

    QProcess *installerProcess = new QProcess();
    installerProcess->setArguments(newArgs);
    installerProcess->setProgram(processPath);
    installerProcess->start();
    installerProcess->waitForStarted();
    return installerProcess;
}

#define VERIFY_PROC_DEBUG(x) \
    if (! x ) { \
        qDebug() << "Stdout:" << proc->readAllStandardOutput(); \
        qDebug() << "Stderr:" << proc->readAllStandardError(); \
        qDebug() << "Exit code: " << proc->exitCode(); \
        qDebug() << "Exit status: " << proc->exitStatus(); \
    } \
    QVERIFY(x)

void finishVerify(QProcess *proc, int exitCode) {
    proc->closeWriteChannel();
    proc->waitForFinished();
    VERIFY_PROC_DEBUG(proc->exitStatus() == QProcess::NormalExit);
    VERIFY_PROC_DEBUG(proc->exitCode() == exitCode);
    delete proc;
}

void CinstProcessTest::testValidInput() {
    QStringList args;
    args << "list=" + validListFile.fileName();

    QTemporaryFile instructions;
    instructions.open();
    foreach (const Certificate &cert, validList.getCertificates()) {
        instructions.write(cert.base64Line().toLatin1());
        instructions.write("\n");
    }
    instructions.close();

    args << "choices=" + instructions.fileName();

    QProcess* installerProcess = startCinstProcess(args);
    finishVerify(installerProcess, ERR_NO_ERROR);
}

void CinstProcessTest::initTestCase() {
    QFile valid(":/list-valid-signed.txt");
    valid.open(QIODevice::ReadOnly);
    validListFile.open();
    validListFile.write(valid.readAll());
    valid.close();
    validListFile.close();
    validList = CertificateList(validListFile.fileName().toLocal8Bit().data());

    QVERIFY(validList.isValid());

    QFile invalid(":/list-invalid-signed.txt");
    invalid.open(QIODevice::ReadOnly);
    invalidListFile.open();
    invalidListFile.write(invalid.readAll());
    invalid.close();
    invalidListFile.close();
    invalidList = CertificateList(invalidListFile.fileName().toLocal8Bit().data());

    QVERIFY(!invalidList.isValid());

    QFile other(":/list-valid-other-signature.txt");
    other.open(QIODevice::ReadOnly);
    otherListFile.open();
    otherListFile.write(other.readAll());
    other.close();
    otherListFile.close();
    otherList = CertificateList(otherListFile.fileName().toLocal8Bit().data());

    QVERIFY(!otherList.isValid());

/* Set HOME or APPDATA so that nss stores are not touched
 * see nsstest for the real test of that code */
#ifdef WIN32
    {
        char buf[fakeHome.path().toLocal8Bit().size() + 9];
        snprintf(buf, fakeHome.path().toLocal8Bit().size() + 9,
                "APPDATA=%s",fakeHome.path().toLocal8Bit().constData());
        QVERIFY(_putenv (buf) != -1);
    }
#else
    QVERIFY(!setenv ("HOME", fakeHome.path().toLocal8Bit().constData(), 1));
#endif
}

void CinstProcessTest::testNoList() {
    /* No list */
    QTemporaryFile emptyFile;
    emptyFile.open();
    emptyFile.close();

    QStringList args;
    args << "list=" + emptyFile.fileName();

    QTemporaryFile instructions;
    instructions.open();
    foreach (const Certificate &cert, validList.getCertificates()) {
        instructions.write(cert.base64Line().toLatin1());
        instructions.write("\n");
    }
    instructions.close();

    args << "choices=" + instructions.fileName();

    QProcess* installerProcess = startCinstProcess(args);
    finishVerify(installerProcess, ERR_INVALID_INPUT_NO_LIST);
}

void CinstProcessTest::testGarbageInput() {
    QStringList args;

    QString garbage = getRandomDataFile(21*1024*1024);
    args << "list=" + garbage;

    QTemporaryFile instructions;
    instructions.open();
    foreach (const Certificate &cert, validList.getCertificates()) {
        instructions.write(cert.base64Line().toLatin1());
        instructions.write("\n");
    }
    instructions.close();

    args << "choices=" + instructions.fileName();

    QProcess* installerProcess = startCinstProcess(args);
    /* If the following failed there may be leftovers in /tmp */
    finishVerify(installerProcess, ERR_INVALID_INPUT_NO_LIST);
    QVERIFY(QFile::remove(garbage));
}

void CinstProcessTest::testNoInput() {
    QStringList args;
    args << "list=foobazbuf";
    args << "choices=bazbuffoo";
    QProcess* installerProcess;
    installerProcess = startCinstProcess(args);
    finishVerify(installerProcess, ERR_INVALID_INPUT_NO_LIST);
}


void CinstProcessTest::testNoInstructions() {
    /* No instructions */
    QTemporaryFile emptyFile;
    emptyFile.open();
    emptyFile.close();

    QStringList args;
    args << "list=" + validListFile.fileName();
    args << "choices=" + emptyFile.fileName();

    QProcess* installerProcess = startCinstProcess(args);
    finishVerify(installerProcess, ERR_NO_INSTRUCTIONS);
}

void CinstProcessTest::testInvalidInstruction() {
    QStringList args;
    args << "list=" + validListFile.fileName();

    QTemporaryFile instructions;
    instructions.open();
    foreach (const Certificate &cert, validList.getCertificates()) {
        instructions.write(cert.base64Line().toLatin1());
        instructions.write("\n");
    }
    instructions.write("I:ABCDEF\n");
    instructions.close();

    args << "choices=" + instructions.fileName();

    QProcess* installerProcess = startCinstProcess(args);

    finishVerify(installerProcess, ERR_INVALID_INSTRUCTIONS);
}

void CinstProcessTest::testUninstall() {
    QStringList args;
    args << "list=" + validListFile.fileName();
    args << "choices=uninstall";

    QProcess* installerProcess = startCinstProcess(args);

    finishVerify(installerProcess, ERR_NO_ERROR);
}

bool g_debug = true;

QTEST_GUILESS_MAIN (CinstProcessTest);

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