view ui/tests/nsstest.cpp @ 1088:508c96e72f62

(issue124) Switch server URL and remove some RELEASE_BUILD options As the test server speaks ECDSA we do not need so much #ifndef RELEASE_BUILD options anymore.
author Andre Heinecke <andre.heinecke@intevation.de>
date Fri, 12 Sep 2014 15:38:42 +0200
parents 317ee9dc4684
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 <cert.h>
#include <certdb.h>
#include <certt.h>

#include <nss.h>
#include <pk11pub.h>

#include "nsstest.h"
#include "nssstore.h"
#include "strhelp.h"

#include <QTest>
#include <QTextCodec>

#ifdef WIN32
#define endl "\r\n"
#endif

QList<QByteArray> NSSTest::get_nss_certs (QTemporaryDir *nssDir)
{
  CERTCertList *list;
  CERTCertListNode *node;
  QList<QByteArray> retval;

  if (NSS_Initialize(nssDir->path().toLocal8Bit().constData(),
              "", "", "secmod.db", NSS_INIT_READONLY)
      == SECSuccess)
    {
      list = PK11_ListCerts(PK11CertListAll, NULL);
      for (node = CERT_LIST_HEAD(list); !CERT_LIST_END(node, list);
           node = CERT_LIST_NEXT(node)) {
        retval << QByteArray((const char*)node->cert->derCert.data,
                (int)node->cert->derCert.len);
      }
      CERT_DestroyCertList(list);
      NSS_Shutdown();
    }
  else
    {
      qDebug("Could not open nss certificate store!\n");
    }
  return retval;
}

void NSSTest::setupTestDir(QTemporaryDir *nssDir)
{
    /* Copy the empty nss db in the temporary dir */
    QVERIFY(QFile::copy(":/nss/cert8.db", nssDir->path() + "/" +"cert8.db"));
    QVERIFY(QFile::copy(":/nss/key3.db", nssDir->path() + "/" +"key3.db"));
    QVERIFY(QFile::copy(":/nss/secmod.db", nssDir->path() + "/" +"secmod.db"));

    QVERIFY(QFile::setPermissions(nssDir->path() + "/" +"cert8.db",
                QFileDevice::ReadOwner | QFileDevice::WriteOwner));
    QVERIFY(QFile::setPermissions(nssDir->path() + "/" +"key3.db",
                QFileDevice::ReadOwner | QFileDevice::WriteOwner));
    QVERIFY(QFile::setPermissions(nssDir->path() + "/" +"secmod.db",
                QFileDevice::ReadOwner | QFileDevice::WriteOwner));
//    nssDir->setAutoRemove(false);
}

void NSSTest::initTestCase() {
    QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8")); /* use system default */

    /* Set up a temporary list */
#ifdef RELEASE_BUILD
    QFile res(":/list-valid-signed-release.txt");
#else
    QFile res(":/list-valid-signed.txt");
#endif
    res.open(QIODevice::ReadOnly);
    validListFile.open();
    validListFile.write(res.readAll());
    validListFile.close();

    setupTestDir(&ffNSSDir);
    setupTestDir(&tbNSSDir);

    validList = CertificateList(validListFile.fileName().toLocal8Bit().data());

    QVERIFY(validList.isValid());

    /* Create the profiles.ini `s set environment variables*/
//    fakeHome.setAutoRemove(false);
#ifndef WIN32
    fakeFirefoxDir = QDir(fakeHome.path() + "/.mozilla/firefox");
    fakeThunderbirdDir = QDir(fakeHome.path() + "/.thunderbird");

    /* Copy the current systems NSSSHARED db in the fake home for benchmark tests */
    QDir fakeNSSSharedDir = fakeHome.path() + "/.pki/nssdb";
    QVERIFY(fakeNSSSharedDir.mkpath(fakeNSSSharedDir.path()));
    QVERIFY(QFile::copy(":/nss/pki-nssdb/cert9.db",
            fakeNSSSharedDir.path() + "cert9.db"));
    QVERIFY(QFile::copy(":/nss/pki-nssdb/key4.db",
            fakeNSSSharedDir.path() + "key4.db"));
    QFile pkcs11(":/nss/pki-nssdb/pkcs11.txt");
    pkcs11.open(QIODevice::ReadOnly);

    QString pkcs11content = pkcs11.readAll();
    pkcs11.close();
    pkcs11content.replace("TOREPLACE", fakeNSSSharedDir.path());
    QFile p11outfile (fakeNSSSharedDir.path() + "pkcs11.txt");
    p11outfile.open(QIODevice::WriteOnly);
    p11outfile.write(pkcs11content.toUtf8());
    p11outfile.close();

    QVERIFY(!setenv ("HOME", fakeHome.path().toLocal8Bit().constData(), 1));
#else
    {
        char buf[fakeHome.path().toLocal8Bit().size() + 9];
        snprintf(buf, fakeHome.path().toLocal8Bit().size() + 9,
                "APPDATA=%s",fakeHome.path().toLocal8Bit().constData());
        QVERIFY(_putenv (buf) != -1);
    }
    fakeFirefoxDir = QDir(fakeHome.path() + "/Mozilla/firefox");
    fakeThunderbirdDir = QDir(fakeHome.path() + "/Thunderbird");
#endif
    QVERIFY(fakeFirefoxDir.mkpath(fakeFirefoxDir.path()));
    QVERIFY(fakeThunderbirdDir.mkpath(fakeThunderbirdDir.path()));

    QFile mozProfile(fakeFirefoxDir.absoluteFilePath("profiles.ini"));
    QFile tbProfile(fakeThunderbirdDir.absoluteFilePath("profiles.ini"));

    /* Write profiles */
    QVERIFY(mozProfile.open(QIODevice::WriteOnly));
    QTextStream ffStream(&mozProfile);
    ffStream << endl << "[General]"<<
        "StartWithLastProfile=1" << endl <<
        "[Profile0]" << endl <<
        "Name=default" << endl <<
        "IsRelative=1" << endl <<
        "Path=" << fakeFirefoxDir.relativeFilePath(ffNSSDir.path()) << endl;
    ffStream.flush();
    mozProfile.close();

    QVERIFY(tbProfile.open(QIODevice::WriteOnly));
    QTextStream tbStream(&tbProfile);
    tbStream << endl << "[General]"<<
        "StartWithLastProfile=1" << endl <<
        "[Profile102]" << endl <<
        "Name=default" << endl <<
        "IsRelative=0" << endl <<
        "Path=" << tbNSSDir.path() << endl;
    tbStream.flush();
    tbProfile.close();
}

void NSSTest::testInstRemove() {
    char ** to_install = NULL,
         ** to_remove = NULL;

    QList<Certificate> instList;

    /* Install all certificates */
    foreach (const Certificate &cert, validList.getCertificates()) {
        if (!cert.isInstallCert())
            continue;
        instList << cert;
        strv_append (&to_install, cert.base64Line().toLatin1().constData() + 2,
                cert.base64Line().size() - 2);
    }
    QVERIFY((size_t) instList.size() == strv_length(to_install));
    QVERIFY(strv_length(to_install) != 0);

    QVERIFY(write_stores_nss(to_install, to_remove) == 0);

    {
        /* Verify that everything is installed */
        QList<QByteArray> installedCertsFF = get_nss_certs(&ffNSSDir);
        QList<QByteArray> installedCertsTB = get_nss_certs(&tbNSSDir);

        QVERIFY(installedCertsFF.size() == instList.size());
        QVERIFY(installedCertsFF == installedCertsTB);

        for (int i = 0; to_install[i]; i++) {
            QByteArray bai = QByteArray::fromBase64(to_install[i]);
            QVERIFY(installedCertsFF.contains(bai));
        }
    }

    {
        /* Remove one certificate */
        QVERIFY(instList.size() > 2);
        strv_append (&to_remove, to_install[1], qstrlen(to_install[1]));

        QList<QByteArray> beforeFF = get_nss_certs(&ffNSSDir);
        QVERIFY(strv_length(to_remove) == 1);
        QVERIFY(write_stores_nss(NULL, to_remove) == 0);

        QList<QByteArray> installedCertsFF = get_nss_certs(&ffNSSDir);
        QList<QByteArray> installedCertsTB = get_nss_certs(&tbNSSDir);
        QVERIFY(beforeFF.size() > 0);
        QVERIFY(beforeFF.size() - 1 == installedCertsFF.size());

        QVERIFY(installedCertsFF == installedCertsTB);

        QByteArray bai = QByteArray::fromBase64(to_install[1]);
        QVERIFY(!installedCertsTB.contains(bai));

        QVERIFY((size_t)installedCertsTB.size() == strv_length(to_install) - 1);

        for (int i = 0; to_install[i]; i++) {
            if (i == 1) {
                continue;
            }
            QByteArray bai = QByteArray::fromBase64(to_install[i]);
            QVERIFY(installedCertsTB.contains(bai));
        }
    }

    {
        /* Readd all certificates check for duplication*/
        QVERIFY(write_stores_nss(to_install, NULL) == 0);

        QList<QByteArray> installedCertsFF = get_nss_certs(&ffNSSDir);
        QList<QByteArray> installedCertsTB = get_nss_certs(&tbNSSDir);

        QVERIFY(installedCertsFF == installedCertsTB);

        QVERIFY((size_t)installedCertsTB.size() == strv_length(to_install));

        for (int i = 0; to_install[i]; i++) {
            QByteArray bai = QByteArray::fromBase64(to_install[i]);
            QVERIFY(installedCertsTB.contains(bai));
        }
    }

    {
        /* Remove all certificates */
        QVERIFY(write_stores_nss(NULL, to_install) == 0);

        QList<QByteArray> installedCertsFF = get_nss_certs(&ffNSSDir);
        QList<QByteArray> installedCertsTB = get_nss_certs(&tbNSSDir);

        QVERIFY(installedCertsFF == installedCertsTB);

        QVERIFY(installedCertsTB.size() == 0);
    }
}

void NSSTest::benchmarkInstall()
{
    char ** to_install = NULL,
         ** to_remove = NULL;

    QList<Certificate> instList;

    /* Install all certificates */
    foreach (const Certificate &cert, validList.getCertificates()) {
        if (!cert.isInstallCert())
            continue;
        instList << cert;
        strv_append (&to_install, cert.base64Line().toLatin1().constData() + 2,
                cert.base64Line().size() - 2);
    }
    QVERIFY((size_t) instList.size() == strv_length(to_install));
    QVERIFY(strv_length(to_install) != 0);

    QBENCHMARK_ONCE {
        write_stores_nss(to_install, to_remove);
    }
}

bool g_debug = true;

QTEST_GUILESS_MAIN (NSSTest);

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