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: */ andre@307: #include andre@307: #include andre@307: #include andre@307: andre@307: #include andre@307: #include andre@307: andre@304: #include "nsstest.h" andre@304: #include "nssstore.h" andre@304: #include "strhelp.h" andre@304: andre@304: #include aheinecke@330: #include aheinecke@330: aheinecke@330: #ifdef WIN32 aheinecke@330: #define endl "\r\n" aheinecke@330: #endif andre@304: andre@307: QList NSSTest::get_nss_certs (QTemporaryDir *nssDir) andre@307: { andre@307: CERTCertList *list; andre@307: CERTCertListNode *node; andre@307: QList retval; andre@304: andre@307: if (NSS_Initialize(nssDir->path().toLocal8Bit().constData(), andre@307: "", "", "secmod.db", NSS_INIT_READONLY) andre@307: == SECSuccess) andre@307: { andre@307: list = PK11_ListCerts(PK11CertListAll, NULL); andre@307: for (node = CERT_LIST_HEAD(list); !CERT_LIST_END(node, list); andre@307: node = CERT_LIST_NEXT(node)) { andre@307: retval << QByteArray((const char*)node->cert->derCert.data, andre@307: (int)node->cert->derCert.len); andre@307: } andre@307: CERT_DestroyCertList(list); andre@307: NSS_Shutdown(); andre@307: } andre@307: else andre@307: { andre@307: qDebug("Could not open nss certificate store!\n"); andre@307: } andre@307: return retval; andre@307: } andre@307: andre@307: void NSSTest::setupTestDir(QTemporaryDir *nssDir) andre@307: { andre@307: /* Copy the empty nss db in the temporary dir */ aheinecke@330: QVERIFY(QFile::copy(":/nss/cert8.db", nssDir->path() + "/" +"cert8.db")); aheinecke@330: QVERIFY(QFile::copy(":/nss/key3.db", nssDir->path() + "/" +"key3.db")); aheinecke@330: QVERIFY(QFile::copy(":/nss/secmod.db", nssDir->path() + "/" +"secmod.db")); andre@307: andre@307: QVERIFY(QFile::setPermissions(nssDir->path() + "/" +"cert8.db", andre@304: QFileDevice::ReadOwner | QFileDevice::WriteOwner)); andre@307: QVERIFY(QFile::setPermissions(nssDir->path() + "/" +"key3.db", andre@304: QFileDevice::ReadOwner | QFileDevice::WriteOwner)); andre@307: QVERIFY(QFile::setPermissions(nssDir->path() + "/" +"secmod.db", andre@304: QFileDevice::ReadOwner | QFileDevice::WriteOwner)); andre@346: // nssDir->setAutoRemove(false); andre@307: } andre@307: andre@307: void NSSTest::initTestCase() { aheinecke@330: QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8")); /* use system default */ andre@304: andre@304: /* Set up a temporary list */ andre@371: #ifdef RELEASE_BUILD andre@371: QFile res(":/list-valid-signed-release.txt"); andre@371: #else andre@304: QFile res(":/list-valid-signed.txt"); andre@371: #endif andre@304: res.open(QIODevice::ReadOnly); andre@304: validListFile.open(); andre@304: validListFile.write(res.readAll()); andre@304: validListFile.close(); andre@304: andre@307: setupTestDir(&ffNSSDir); andre@307: setupTestDir(&tbNSSDir); andre@304: andre@304: validList = CertificateList(validListFile.fileName().toLocal8Bit().data()); andre@304: andre@371: QVERIFY(validList.isValid()); andre@371: andre@304: /* Create the profiles.ini `s set environment variables*/ andre@346: // fakeHome.setAutoRemove(false); andre@304: #ifndef WIN32 andre@304: fakeFirefoxDir = QDir(fakeHome.path() + "/.mozilla/firefox"); andre@304: fakeThunderbirdDir = QDir(fakeHome.path() + "/.thunderbird"); aheinecke@492: aheinecke@492: /* Copy the current systems NSSSHARED db in the fake home for benchmark tests */ aheinecke@492: QDir fakeNSSSharedDir = fakeHome.path() + "/.pki/nssdb"; aheinecke@492: QVERIFY(fakeNSSSharedDir.mkpath(fakeNSSSharedDir.path())); andre@830: QVERIFY(QFile::copy(":/nss/pki-nssdb/cert9.db", aheinecke@492: fakeNSSSharedDir.path() + "cert9.db")); andre@830: QVERIFY(QFile::copy(":/nss/pki-nssdb/key4.db", aheinecke@492: fakeNSSSharedDir.path() + "key4.db")); andre@830: QFile pkcs11(":/nss/pki-nssdb/pkcs11.txt"); andre@830: pkcs11.open(QIODevice::ReadOnly); andre@830: andre@830: QString pkcs11content = pkcs11.readAll(); andre@830: pkcs11.close(); andre@830: pkcs11content.replace("TOREPLACE", fakeNSSSharedDir.path()); andre@830: QFile p11outfile (fakeNSSSharedDir.path() + "pkcs11.txt"); andre@830: p11outfile.open(QIODevice::WriteOnly); andre@830: p11outfile.write(pkcs11content.toUtf8()); andre@830: p11outfile.close(); aheinecke@492: aheinecke@492: QVERIFY(!setenv ("HOME", fakeHome.path().toLocal8Bit().constData(), 1)); andre@304: #else aheinecke@326: { aheinecke@326: char buf[fakeHome.path().toLocal8Bit().size() + 9]; aheinecke@326: snprintf(buf, fakeHome.path().toLocal8Bit().size() + 9, aheinecke@326: "APPDATA=%s",fakeHome.path().toLocal8Bit().constData()); aheinecke@326: QVERIFY(_putenv (buf) != -1); aheinecke@326: } andre@304: fakeFirefoxDir = QDir(fakeHome.path() + "/Mozilla/firefox"); andre@304: fakeThunderbirdDir = QDir(fakeHome.path() + "/Thunderbird"); andre@304: #endif andre@304: QVERIFY(fakeFirefoxDir.mkpath(fakeFirefoxDir.path())); andre@304: QVERIFY(fakeThunderbirdDir.mkpath(fakeThunderbirdDir.path())); andre@304: andre@304: QFile mozProfile(fakeFirefoxDir.absoluteFilePath("profiles.ini")); andre@304: QFile tbProfile(fakeThunderbirdDir.absoluteFilePath("profiles.ini")); andre@304: andre@304: /* Write profiles */ andre@304: QVERIFY(mozProfile.open(QIODevice::WriteOnly)); andre@304: QTextStream ffStream(&mozProfile); andre@304: ffStream << endl << "[General]"<< andre@304: "StartWithLastProfile=1" << endl << andre@304: "[Profile0]" << endl << andre@304: "Name=default" << endl << andre@304: "IsRelative=1" << endl << andre@307: "Path=" << fakeFirefoxDir.relativeFilePath(ffNSSDir.path()) << endl; andre@304: ffStream.flush(); andre@304: mozProfile.close(); andre@304: andre@304: QVERIFY(tbProfile.open(QIODevice::WriteOnly)); andre@304: QTextStream tbStream(&tbProfile); andre@304: tbStream << endl << "[General]"<< andre@304: "StartWithLastProfile=1" << endl << andre@304: "[Profile102]" << endl << andre@304: "Name=default" << endl << andre@304: "IsRelative=0" << endl << andre@307: "Path=" << tbNSSDir.path() << endl; andre@304: tbStream.flush(); andre@304: tbProfile.close(); andre@304: } andre@304: andre@304: void NSSTest::testInstRemove() { andre@304: char ** to_install = NULL, andre@304: ** to_remove = NULL; andre@304: andre@304: QList instList; andre@304: andre@307: /* Install all certificates */ andre@304: foreach (const Certificate &cert, validList.getCertificates()) { andre@304: if (!cert.isInstallCert()) andre@304: continue; andre@304: instList << cert; andre@304: strv_append (&to_install, cert.base64Line().toLatin1().constData() + 2, andre@304: cert.base64Line().size() - 2); andre@304: } andre@304: QVERIFY((size_t) instList.size() == strv_length(to_install)); andre@371: QVERIFY(strv_length(to_install) != 0); andre@304: andre@305: QVERIFY(write_stores_nss(to_install, to_remove) == 0); andre@305: andre@307: { andre@307: /* Verify that everything is installed */ andre@307: QList installedCertsFF = get_nss_certs(&ffNSSDir); andre@307: QList installedCertsTB = get_nss_certs(&tbNSSDir); andre@307: andre@307: QVERIFY(installedCertsFF.size() == instList.size()); andre@307: QVERIFY(installedCertsFF == installedCertsTB); andre@307: andre@307: for (int i = 0; to_install[i]; i++) { andre@307: QByteArray bai = QByteArray::fromBase64(to_install[i]); andre@307: QVERIFY(installedCertsFF.contains(bai)); andre@307: } andre@307: } andre@307: andre@307: { andre@307: /* Remove one certificate */ andre@307: QVERIFY(instList.size() > 2); andre@307: strv_append (&to_remove, to_install[1], qstrlen(to_install[1])); andre@307: aheinecke@477: QList beforeFF = get_nss_certs(&ffNSSDir); aheinecke@477: QVERIFY(strv_length(to_remove) == 1); andre@307: QVERIFY(write_stores_nss(NULL, to_remove) == 0); andre@307: andre@307: QList installedCertsFF = get_nss_certs(&ffNSSDir); andre@307: QList installedCertsTB = get_nss_certs(&tbNSSDir); aheinecke@477: QVERIFY(beforeFF.size() > 0); aheinecke@477: QVERIFY(beforeFF.size() - 1 == installedCertsFF.size()); andre@307: andre@307: QVERIFY(installedCertsFF == installedCertsTB); andre@307: andre@307: QByteArray bai = QByteArray::fromBase64(to_install[1]); andre@307: QVERIFY(!installedCertsTB.contains(bai)); andre@307: andre@307: QVERIFY((size_t)installedCertsTB.size() == strv_length(to_install) - 1); andre@307: andre@307: for (int i = 0; to_install[i]; i++) { andre@307: if (i == 1) { andre@307: continue; andre@307: } andre@307: QByteArray bai = QByteArray::fromBase64(to_install[i]); andre@307: QVERIFY(installedCertsTB.contains(bai)); andre@307: } andre@307: } andre@307: andre@307: { andre@307: /* Readd all certificates check for duplication*/ andre@307: QVERIFY(write_stores_nss(to_install, NULL) == 0); andre@307: andre@307: QList installedCertsFF = get_nss_certs(&ffNSSDir); andre@307: QList installedCertsTB = get_nss_certs(&tbNSSDir); andre@307: andre@307: QVERIFY(installedCertsFF == installedCertsTB); andre@307: andre@307: QVERIFY((size_t)installedCertsTB.size() == strv_length(to_install)); andre@307: andre@307: for (int i = 0; to_install[i]; i++) { andre@307: QByteArray bai = QByteArray::fromBase64(to_install[i]); andre@307: QVERIFY(installedCertsTB.contains(bai)); andre@307: } andre@307: } andre@307: andre@307: { andre@307: /* Remove all certificates */ andre@307: QVERIFY(write_stores_nss(NULL, to_install) == 0); andre@307: andre@307: QList installedCertsFF = get_nss_certs(&ffNSSDir); andre@307: QList installedCertsTB = get_nss_certs(&tbNSSDir); andre@307: andre@307: QVERIFY(installedCertsFF == installedCertsTB); andre@307: andre@307: QVERIFY(installedCertsTB.size() == 0); andre@307: } andre@304: } andre@304: aheinecke@492: void NSSTest::benchmarkInstall() aheinecke@492: { aheinecke@492: char ** to_install = NULL, aheinecke@492: ** to_remove = NULL; aheinecke@492: aheinecke@492: QList instList; aheinecke@492: aheinecke@492: /* Install all certificates */ aheinecke@492: foreach (const Certificate &cert, validList.getCertificates()) { aheinecke@492: if (!cert.isInstallCert()) aheinecke@492: continue; aheinecke@492: instList << cert; aheinecke@492: strv_append (&to_install, cert.base64Line().toLatin1().constData() + 2, aheinecke@492: cert.base64Line().size() - 2); aheinecke@492: } aheinecke@492: QVERIFY((size_t) instList.size() == strv_length(to_install)); aheinecke@492: QVERIFY(strv_length(to_install) != 0); aheinecke@492: aheinecke@534: QBENCHMARK_ONCE { aheinecke@492: write_stores_nss(to_install, to_remove); aheinecke@492: } aheinecke@492: } andre@1060: andre@1060: bool g_debug = true; andre@1060: andre@304: QTEST_GUILESS_MAIN (NSSTest);