Blame lang/qt/tests/t-tofuinfo.cpp

Packit Service 672cf4
/* t-tofuinfo.cpp
Packit Service 672cf4
Packit Service 672cf4
    This file is part of qgpgme, the Qt API binding for gpgme
Packit Service 672cf4
    Copyright (c) 2016 by Bundesamt für Sicherheit in der Informationstechnik
Packit Service 672cf4
    Software engineering by Intevation GmbH
Packit Service 672cf4
Packit Service 672cf4
    QGpgME is free software; you can redistribute it and/or
Packit Service 672cf4
    modify it under the terms of the GNU General Public License as
Packit Service 672cf4
    published by the Free Software Foundation; either version 2 of the
Packit Service 672cf4
    License, or (at your option) any later version.
Packit Service 672cf4
Packit Service 672cf4
    QGpgME is distributed in the hope that it will be useful,
Packit Service 672cf4
    but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 672cf4
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 672cf4
    General Public License for more details.
Packit Service 672cf4
Packit Service 672cf4
    You should have received a copy of the GNU General Public License
Packit Service 672cf4
    along with this program; if not, write to the Free Software
Packit Service 672cf4
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
Packit Service 672cf4
Packit Service 672cf4
    In addition, as a special exception, the copyright holders give
Packit Service 672cf4
    permission to link the code of this program with any edition of
Packit Service 672cf4
    the Qt library by Trolltech AS, Norway (or with modified versions
Packit Service 672cf4
    of Qt that use the same license as Qt), and distribute linked
Packit Service 672cf4
    combinations including the two.  You must obey the GNU General
Packit Service 672cf4
    Public License in all respects for all of the code used other than
Packit Service 672cf4
    Qt.  If you modify this file, you may extend this exception to
Packit Service 672cf4
    your version of the file, but you are not obligated to do so.  If
Packit Service 672cf4
    you do not wish to do so, delete this exception statement from
Packit Service 672cf4
    your version.
Packit Service 672cf4
*/
Packit Service 672cf4
#ifdef HAVE_CONFIG_H
Packit Service 672cf4
 #include "config.h"
Packit Service 672cf4
#endif
Packit Service 672cf4
Packit Service 672cf4
#include <QDebug>
Packit Service 672cf4
#include <QTest>
Packit Service 672cf4
#include <QTemporaryDir>
Packit Service 672cf4
#include <QSignalSpy>
Packit Service 672cf4
Packit Service 672cf4
#include "protocol.h"
Packit Service 672cf4
#include "tofuinfo.h"
Packit Service 672cf4
#include "tofupolicyjob.h"
Packit Service 672cf4
#include "verifyopaquejob.h"
Packit Service 672cf4
#include "verificationresult.h"
Packit Service 672cf4
#include "signingresult.h"
Packit Service 672cf4
#include "importjob.h"
Packit Service 672cf4
#include "importresult.h"
Packit Service 672cf4
#include "keylistjob.h"
Packit Service 672cf4
#include "keylistresult.h"
Packit Service 672cf4
#include "signjob.h"
Packit Service 672cf4
#include "key.h"
Packit Service 672cf4
#include "t-support.h"
Packit Service 672cf4
#include "engineinfo.h"
Packit Service 672cf4
#include "context.h"
Packit Service 672cf4
#include <iostream>
Packit Service 672cf4
Packit Service 672cf4
using namespace QGpgME;
Packit Service 672cf4
using namespace GpgME;
Packit Service 672cf4
Packit Service 672cf4
static const char testMsg1[] =
Packit Service 672cf4
"-----BEGIN PGP MESSAGE-----\n"
Packit Service 672cf4
"\n"
Packit Service 672cf4
"owGbwMvMwCSoW1RzPCOz3IRxjXQSR0lqcYleSUWJTZOvjVdpcYmCu1+oQmaJIleH\n"
Packit Service 672cf4
"GwuDIBMDGysTSIqBi1MApi+nlGGuwDeHao53HBr+FoVGP3xX+kvuu9fCMJvl6IOf\n"
Packit Service 672cf4
"y1kvP4y+8D5a11ang0udywsA\n"
Packit Service 672cf4
"=Crq6\n"
Packit Service 672cf4
"-----END PGP MESSAGE-----\n";
Packit Service 672cf4
Packit Service 672cf4
static const char conflictKey1[] = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n"
Packit Service 672cf4
"\n"
Packit Service 6c01f9
"mDMEWG+w/hYJKwYBBAHaRw8BAQdAiq1oStvDYg8ZfFs5DgisYJo8dJxD+C/AA21O\n"
Packit Service 6c01f9
"K/aif0O0GXRvZnVfY29uZmxpY3RAZXhhbXBsZS5jb22IlgQTFggAPhYhBHoJBLaV\n"
Packit Service 6c01f9
"DamYAgoa1L5BwMOl/x88BQJYb7D+AhsDBQkDwmcABQsJCAcCBhUICQoLAgQWAgMB\n"
Packit Service 6c01f9
"Ah4BAheAAAoJEL5BwMOl/x88GvwA/0SxkbLyAcshGm2PRrPsFQsSVAfwaSYFVmS2\n"
Packit Service 6c01f9
"cMVIw1PfAQDclRH1Z4MpufK07ju4qI33o4s0UFpVRBuSxt7A4P2ZD7g4BFhvsP4S\n"
Packit Service 6c01f9
"CisGAQQBl1UBBQEBB0AmVrgaDNJ7K2BSalsRo2EkRJjHGqnp5bBB0tapnF81CQMB\n"
Packit Service 6c01f9
"CAeIeAQYFggAIBYhBHoJBLaVDamYAgoa1L5BwMOl/x88BQJYb7D+AhsMAAoJEL5B\n"
Packit Service 6c01f9
"wMOl/x88OR0BAMq4/vmJUORRTmzjHcv/DDrQB030DSq666rlckGIKTShAPoDXM9N\n"
Packit Service 6c01f9
"0gZK+YzvrinSKZXHmn0aSwmC1/hyPybJPEljBw==\n"
Packit Service 6c01f9
"=p2Oj\n"
Packit Service 672cf4
"-----END PGP PUBLIC KEY BLOCK-----\n";
Packit Service 672cf4
Packit Service 672cf4
static const char conflictKey2[] = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n"
Packit Service 672cf4
"\n"
Packit Service 6c01f9
"mDMEWG+xShYJKwYBBAHaRw8BAQdA567gPEPJRpqKnZjlFJMRNUqruRviYMyygfF6\n"
Packit Service 6c01f9
"6Ok+ygu0GXRvZnVfY29uZmxpY3RAZXhhbXBsZS5jb22IlgQTFggAPhYhBJ5kRh7E\n"
Packit Service 6c01f9
"I98w8kgUcmkAfYFvqqHsBQJYb7FKAhsDBQkDwmcABQsJCAcCBhUICQoLAgQWAgMB\n"
Packit Service 6c01f9
"Ah4BAheAAAoJEGkAfYFvqqHsYR0BAOz8JjYB4VvGkt6noLS3F5TLfsedGwQkBCw5\n"
Packit Service 6c01f9
"znw/vGZsAQD9DSX+ekwdrN56mNO8ISt5uVS7B1ZQtouNBF+nzcwbDbg4BFhvsUoS\n"
Packit Service 6c01f9
"CisGAQQBl1UBBQEBB0BFupW8+Xc1ikab8TJqANjQhvFVh6uLsgcK4g9lZgbGXAMB\n"
Packit Service 6c01f9
"CAeIeAQYFggAIBYhBJ5kRh7EI98w8kgUcmkAfYFvqqHsBQJYb7FKAhsMAAoJEGkA\n"
Packit Service 6c01f9
"fYFvqqHs15ABALdN3uiV/07cJ3RkNb3WPcijGsto+lECDS11dKEwTMFeAQDx+V36\n"
Packit Service 6c01f9
"ocbYC/xEuwi3w45oNqGieazzcD/GBbt8OBk3BA==\n"
Packit Service 6c01f9
"=45IR\n"
Packit Service 672cf4
"-----END PGP PUBLIC KEY BLOCK-----\n";
Packit Service 672cf4
Packit Service 672cf4
static const char conflictMsg1[] = "-----BEGIN PGP MESSAGE-----\n"
Packit Service 672cf4
"\n"
Packit Service 6c01f9
"owGbwMvMwCG2z/HA4aX/5W0YT3MlMUTkb2xPSizi6ihlYRDjYJAVU2Sp4mTZNpV3\n"
Packit Service 6c01f9
"5QwmLqkrMLWsTCCFDFycAjCR1vcMf4U0Qrs6qzqfHJ9puGOFduLN2nVmhsumxjBE\n"
Packit Service 6c01f9
"mdw4lr1ehIWR4QdLuNBpe86PGx1PtNXfVAzm/hu+vfjCp5BVNjPTM9L0eAA=\n"
Packit Service 6c01f9
"=MfBD\n"
Packit Service 672cf4
"-----END PGP MESSAGE-----\n";
Packit Service 672cf4
Packit Service 672cf4
static const char conflictMsg2[] = "-----BEGIN PGP MESSAGE-----\n"
Packit Service 672cf4
"\n"
Packit Service 6c01f9
"owGbwMvMwCGWyVDbmL9q4RvG01xJDBH5GyvS8vO5OkpZGMQ4GGTFFFnmpbjJHVG+\n"
Packit Service 6c01f9
"b/DJQ6QIppaVCaSQgYtTACaySZHhr/SOPrdFJ89KrcwKY5i1XnflXYf2PK76SafK\n"
Packit Service 6c01f9
"tkxXuXzvJAvDX4kCybuqFk3HXCexz2+IrnZ+5X5EqOnuo3ens2cte+uzlhMA\n"
Packit Service 6c01f9
"=BIAi\n"
Packit Service 672cf4
"-----END PGP MESSAGE-----\n";
Packit Service 672cf4
Packit Service 672cf4
class TofuInfoTest: public QGpgMETest
Packit Service 672cf4
{
Packit Service 672cf4
    Q_OBJECT
Packit Service 672cf4
Q_SIGNALS:
Packit Service 672cf4
    void asyncDone();
Packit Service 672cf4
Packit Service 672cf4
private:
Packit Service 672cf4
    bool testSupported()
Packit Service 672cf4
    {
Packit Service 672cf4
        static bool initialized, supported;
Packit Service 672cf4
        if (initialized) {
Packit Service 672cf4
            return supported;
Packit Service 672cf4
        }
Packit Service 672cf4
        initialized = true;
Packit Service 672cf4
        if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.1.16") {
Packit Service 672cf4
            return false;
Packit Service 672cf4
        }
Packit Service 672cf4
        // If the keylist fails here this means that gnupg does not
Packit Service 672cf4
        // support tofu at all. It can be disabled at compile time. So no
Packit Service 672cf4
        // tests.
Packit Service 672cf4
        auto *job = openpgp()->keyListJob(false, false, false);
Packit Service 672cf4
        job->addMode(GpgME::WithTofu);
Packit Service 672cf4
        std::vector<GpgME::Key> keys;
Packit Service 672cf4
        job->exec(QStringList() << QStringLiteral("zulu@example.net"), true, keys);
Packit Service 672cf4
        delete job;
Packit Service 672cf4
        supported = !keys.empty();
Packit Service 672cf4
        return supported;
Packit Service 672cf4
    }
Packit Service 672cf4
Packit Service 672cf4
    void testTofuCopy(TofuInfo other, const TofuInfo &orig)
Packit Service 672cf4
    {
Packit Service 672cf4
        QVERIFY(!orig.isNull());
Packit Service 672cf4
        QVERIFY(!other.isNull());
Packit Service 672cf4
        QVERIFY(orig.signLast() == other.signLast());
Packit Service 672cf4
        QVERIFY(orig.signCount() == other.signCount());
Packit Service 672cf4
        QVERIFY(orig.validity() == other.validity());
Packit Service 672cf4
        QVERIFY(orig.policy() == other.policy());
Packit Service 672cf4
    }
Packit Service 672cf4
Packit Service 672cf4
    void signAndVerify(const QString &what, const GpgME::Key &key, int expected)
Packit Service 672cf4
    {
Packit Service 672cf4
        auto job = openpgp()->signJob();
Packit Service 672cf4
        auto ctx = Job::context(job);
Packit Service 672cf4
        TestPassphraseProvider provider;
Packit Service 672cf4
        ctx->setPassphraseProvider(&provider);
Packit Service 672cf4
        ctx->setPinentryMode(Context::PinentryLoopback);
Packit Service 672cf4
Packit Service 672cf4
        std::vector<Key> keys;
Packit Service 672cf4
        keys.push_back(key);
Packit Service 672cf4
        QByteArray signedData;
Packit Service 672cf4
        auto sigResult = job->exec(keys, what.toUtf8(), NormalSignatureMode, signedData);
Packit Service 672cf4
        delete job;
Packit Service 672cf4
Packit Service 672cf4
        QVERIFY(!sigResult.error());
Packit Service 672cf4
        foreach (const auto uid, keys[0].userIDs()) {
Packit Service 672cf4
            auto info = uid.tofuInfo();
Packit Service 672cf4
            QVERIFY(info.signCount() == expected - 1);
Packit Service 672cf4
        }
Packit Service 672cf4
Packit Service 672cf4
        auto verifyJob = openpgp()->verifyOpaqueJob();
Packit Service 672cf4
        QByteArray verified;
Packit Service 672cf4
Packit Service 672cf4
        auto result = verifyJob->exec(signedData, verified);
Packit Service 672cf4
        delete verifyJob;
Packit Service 672cf4
Packit Service 672cf4
        QVERIFY(!result.error());
Packit Service 672cf4
        QVERIFY(verified == what.toUtf8());
Packit Service 672cf4
Packit Service 672cf4
        QVERIFY(result.numSignatures() == 1);
Packit Service 672cf4
        auto sig = result.signatures()[0];
Packit Service 672cf4
Packit Service 672cf4
        auto key2 = sig.key();
Packit Service 672cf4
        QVERIFY(!key.isNull());
Packit Service 672cf4
        QVERIFY(!strcmp (key2.primaryFingerprint(), key.primaryFingerprint()));
Packit Service 672cf4
        QVERIFY(!strcmp (key.primaryFingerprint(), sig.fingerprint()));
Packit Service 672cf4
        auto stats = key2.userID(0).tofuInfo();
Packit Service 672cf4
        QVERIFY(!stats.isNull());
Packit Service 672cf4
        if (stats.signCount() != expected) {
Packit Service 672cf4
            std::cout << "################ Key before verify: "
Packit Service 672cf4
                      << key
Packit Service 672cf4
                      << "################ Key after verify: "
Packit Service 672cf4
                      << key2;
Packit Service 672cf4
        }
Packit Service 672cf4
        QVERIFY(stats.signCount() == expected);
Packit Service 672cf4
    }
Packit Service 672cf4
Packit Service 672cf4
private Q_SLOTS:
Packit Service 672cf4
    void testTofuNull()
Packit Service 672cf4
    {
Packit Service 672cf4
        if (!testSupported()) {
Packit Service 672cf4
            return;
Packit Service 672cf4
        }
Packit Service 672cf4
        TofuInfo tofu;
Packit Service 672cf4
        QVERIFY(tofu.isNull());
Packit Service 672cf4
        QVERIFY(!tofu.description());
Packit Service 672cf4
        QVERIFY(!tofu.signCount());
Packit Service 672cf4
        QVERIFY(!tofu.signLast());
Packit Service 672cf4
        QVERIFY(!tofu.signFirst());
Packit Service 672cf4
        QVERIFY(tofu.validity() == TofuInfo::ValidityUnknown);
Packit Service 672cf4
        QVERIFY(tofu.policy() == TofuInfo::PolicyUnknown);
Packit Service 672cf4
    }
Packit Service 672cf4
Packit Service 672cf4
    void testTofuInfo()
Packit Service 672cf4
    {
Packit Service 672cf4
        if (!testSupported()) {
Packit Service 672cf4
            return;
Packit Service 672cf4
        }
Packit Service 672cf4
        auto *job = openpgp()->verifyOpaqueJob(true);
Packit Service 672cf4
        const QByteArray data1(testMsg1);
Packit Service 672cf4
        QByteArray plaintext;
Packit Service 672cf4
Packit Service 672cf4
        auto ctx = Job::context(job);
Packit Service 672cf4
        QVERIFY(ctx);
Packit Service 672cf4
        ctx->setSender("alfa@example.net");
Packit Service 672cf4
Packit Service 672cf4
        auto result = job->exec(data1, plaintext);
Packit Service 672cf4
        delete job;
Packit Service 672cf4
Packit Service 672cf4
        QVERIFY(!result.isNull());
Packit Service 672cf4
        QVERIFY(!result.error());
Packit Service 672cf4
        QVERIFY(!strcmp(plaintext.constData(), "Just GNU it!\n"));
Packit Service 672cf4
Packit Service 672cf4
        QVERIFY(result.numSignatures() == 1);
Packit Service 672cf4
        Signature sig = result.signatures()[0];
Packit Service 672cf4
        /* TOFU is always marginal */
Packit Service 672cf4
        QVERIFY(sig.validity() == Signature::Marginal);
Packit Service 672cf4
Packit Service 672cf4
        auto stats = sig.key().userID(0).tofuInfo();
Packit Service 672cf4
        QVERIFY(!stats.isNull());
Packit Service 672cf4
        QVERIFY(sig.key().primaryFingerprint());
Packit Service 672cf4
        QVERIFY(sig.fingerprint());
Packit Service 672cf4
        QVERIFY(!strcmp(sig.key().primaryFingerprint(), sig.fingerprint()));
Packit Service 672cf4
        QVERIFY(stats.signFirst() == stats.signLast());
Packit Service 672cf4
        QVERIFY(stats.signCount() == 1);
Packit Service 672cf4
        QVERIFY(stats.policy() == TofuInfo::PolicyAuto);
Packit Service 672cf4
        QVERIFY(stats.validity() == TofuInfo::LittleHistory);
Packit Service 672cf4
Packit Service 672cf4
        testTofuCopy(stats, stats);
Packit Service 672cf4
Packit Service 672cf4
        /* Another verify */
Packit Service 672cf4
Packit Service 672cf4
        job = openpgp()->verifyOpaqueJob(true);
Packit Service 672cf4
        result = job->exec(data1, plaintext);
Packit Service 672cf4
        delete job;
Packit Service 672cf4
Packit Service 672cf4
        QVERIFY(!result.isNull());
Packit Service 672cf4
        QVERIFY(!result.error());
Packit Service 672cf4
Packit Service 672cf4
        QVERIFY(result.numSignatures() == 1);
Packit Service 672cf4
        sig = result.signatures()[0];
Packit Service 672cf4
        /* TOFU is always marginal */
Packit Service 672cf4
        QVERIFY(sig.validity() == Signature::Marginal);
Packit Service 672cf4
Packit Service 672cf4
        stats = sig.key().userID(0).tofuInfo();
Packit Service 672cf4
        QVERIFY(!stats.isNull());
Packit Service 672cf4
        QVERIFY(!strcmp(sig.key().primaryFingerprint(), sig.fingerprint()));
Packit Service 672cf4
        QVERIFY(stats.signFirst() == stats.signLast());
Packit Service 672cf4
        QVERIFY(stats.signCount() == 1);
Packit Service 672cf4
        QVERIFY(stats.policy() == TofuInfo::PolicyAuto);
Packit Service 672cf4
        QVERIFY(stats.validity() == TofuInfo::LittleHistory);
Packit Service 672cf4
Packit Service 672cf4
        /* Verify that another call yields the same result */
Packit Service 672cf4
        job = openpgp()->verifyOpaqueJob(true);
Packit Service 672cf4
        result = job->exec(data1, plaintext);
Packit Service 672cf4
        delete job;
Packit Service 672cf4
Packit Service 672cf4
        QVERIFY(!result.isNull());
Packit Service 672cf4
        QVERIFY(!result.error());
Packit Service 672cf4
Packit Service 672cf4
        QVERIFY(result.numSignatures() == 1);
Packit Service 672cf4
        sig = result.signatures()[0];
Packit Service 672cf4
        /* TOFU is always marginal */
Packit Service 672cf4
        QVERIFY(sig.validity() == Signature::Marginal);
Packit Service 672cf4
Packit Service 672cf4
        stats = sig.key().userID(0).tofuInfo();
Packit Service 672cf4
        QVERIFY(!stats.isNull());
Packit Service 672cf4
        QVERIFY(!strcmp(sig.key().primaryFingerprint(), sig.fingerprint()));
Packit Service 672cf4
        QVERIFY(stats.signFirst() == stats.signLast());
Packit Service 672cf4
        QVERIFY(stats.signCount() == 1);
Packit Service 672cf4
        QVERIFY(stats.policy() == TofuInfo::PolicyAuto);
Packit Service 672cf4
        QVERIFY(stats.validity() == TofuInfo::LittleHistory);
Packit Service 672cf4
    }
Packit Service 672cf4
Packit Service 672cf4
    void testTofuSignCount()
Packit Service 672cf4
    {
Packit Service 672cf4
        if (!testSupported()) {
Packit Service 672cf4
            return;
Packit Service 672cf4
        }
Packit Service 672cf4
        auto *job = openpgp()->keyListJob(false, false, false);
Packit Service 672cf4
        job->addMode(GpgME::WithTofu);
Packit Service 672cf4
        std::vector<GpgME::Key> keys;
Packit Service 672cf4
        GpgME::KeyListResult result = job->exec(QStringList() << QStringLiteral("zulu@example.net"),
Packit Service 672cf4
                                                true, keys);
Packit Service 672cf4
        delete job;
Packit Service 672cf4
        QVERIFY(!keys.empty());
Packit Service 672cf4
        Key key = keys[0];
Packit Service 672cf4
        QVERIFY(!key.isNull());
Packit Service 672cf4
Packit Service 672cf4
        /* As we sign & verify quickly here we need different
Packit Service 672cf4
         * messages to avoid having them treated as the same
Packit Service 672cf4
         * message if they were created within the same second.
Packit Service 672cf4
         * Alternatively we could use the same message and wait
Packit Service 672cf4
         * a second between each call. But this would slow down
Packit Service 672cf4
         * the testsuite. */
Packit Service 672cf4
        signAndVerify(QStringLiteral("Hello"), key, 1);
Packit Service 672cf4
        key.update();
Packit Service 672cf4
        signAndVerify(QStringLiteral("Hello2"), key, 2);
Packit Service 672cf4
        key.update();
Packit Service 672cf4
        signAndVerify(QStringLiteral("Hello3"), key, 3);
Packit Service 672cf4
        key.update();
Packit Service 672cf4
        signAndVerify(QStringLiteral("Hello4"), key, 4);
Packit Service 672cf4
    }
Packit Service 672cf4
Packit Service 672cf4
    void testTofuKeyList()
Packit Service 672cf4
    {
Packit Service 672cf4
        if (!testSupported()) {
Packit Service 672cf4
            return;
Packit Service 672cf4
        }
Packit Service 672cf4
Packit Service 672cf4
        /* First check that the key has no tofu info. */
Packit Service 672cf4
        auto *job = openpgp()->keyListJob(false, false, false);
Packit Service 672cf4
        std::vector<GpgME::Key> keys;
Packit Service 672cf4
        auto result = job->exec(QStringList() << QStringLiteral("zulu@example.net"),
Packit Service 672cf4
                                                 true, keys);
Packit Service 672cf4
        delete job;
Packit Service 672cf4
        QVERIFY(!keys.empty());
Packit Service 672cf4
        auto key = keys[0];
Packit Service 672cf4
        QVERIFY(!key.isNull());
Packit Service 672cf4
        QVERIFY(key.userID(0).tofuInfo().isNull());
Packit Service 672cf4
        auto keyCopy = key;
Packit Service 672cf4
        keyCopy.update();
Packit Service 672cf4
        auto sigCnt = keyCopy.userID(0).tofuInfo().signCount();
Packit Service 672cf4
        signAndVerify(QStringLiteral("Hello5"), keyCopy,
Packit Service 672cf4
                      sigCnt + 1);
Packit Service 672cf4
        keyCopy.update();
Packit Service 672cf4
        signAndVerify(QStringLiteral("Hello6"), keyCopy,
Packit Service 672cf4
                      sigCnt + 2);
Packit Service 672cf4
Packit Service 672cf4
        /* Now another one but with tofu */
Packit Service 672cf4
        job = openpgp()->keyListJob(false, false, false);
Packit Service 672cf4
        job->addMode(GpgME::WithTofu);
Packit Service 672cf4
        result = job->exec(QStringList() << QStringLiteral("zulu@example.net"),
Packit Service 672cf4
                           true, keys);
Packit Service 672cf4
        delete job;
Packit Service 672cf4
        QVERIFY(!result.error());
Packit Service 672cf4
        QVERIFY(!keys.empty());
Packit Service 672cf4
        auto key2 = keys[0];
Packit Service 672cf4
        QVERIFY(!key2.isNull());
Packit Service 672cf4
        auto info = key2.userID(0).tofuInfo();
Packit Service 672cf4
        QVERIFY(!info.isNull());
Packit Service 672cf4
        QVERIFY(info.signCount());
Packit Service 672cf4
    }
Packit Service 672cf4
Packit Service 672cf4
    void testTofuPolicy()
Packit Service 672cf4
    {
Packit Service 672cf4
        if (!testSupported()) {
Packit Service 672cf4
            return;
Packit Service 672cf4
        }
Packit Service 672cf4
Packit Service 672cf4
        /* First check that the key has no tofu info. */
Packit Service 672cf4
        auto *job = openpgp()->keyListJob(false, false, false);
Packit Service 672cf4
        std::vector<GpgME::Key> keys;
Packit Service 672cf4
        job->addMode(GpgME::WithTofu);
Packit Service 672cf4
        auto result = job->exec(QStringList() << QStringLiteral("bravo@example.net"),
Packit Service 672cf4
                                                 false, keys);
Packit Service 672cf4
Packit Service 672cf4
        if (keys.empty()) {
Packit Service 672cf4
            qDebug() << "bravo@example.net not found";
Packit Service 672cf4
            qDebug() << "Error: " << result.error().asString();
Packit Service 672cf4
            const auto homedir = QString::fromLocal8Bit(qgetenv("GNUPGHOME"));
Packit Service 672cf4
            qDebug() << "Homedir is: " << homedir;
Packit Service 672cf4
            QFileInfo fi(homedir + "/pubring.gpg");
Packit Service 672cf4
            qDebug () << "pubring exists: " << fi.exists() << " readable? "
Packit Service 672cf4
                      << fi.isReadable() << " size: " << fi.size();
Packit Service 672cf4
            QFileInfo fi2(homedir + "/pubring.kbx");
Packit Service 672cf4
            qDebug () << "keybox exists: " << fi2.exists() << " readable? "
Packit Service 672cf4
                      << fi2.isReadable() << " size: " << fi2.size();
Packit Service 672cf4
Packit Service 672cf4
            result = job->exec(QStringList(), false, keys);
Packit Service 672cf4
            foreach (const auto key, keys) {
Packit Service 672cf4
                qDebug() << "Key: " << key.userID(0).name() << " <"
Packit Service 672cf4
                         << key.userID(0).email()
Packit Service 672cf4
                         << ">\n fpr: " << key.primaryFingerprint();
Packit Service 672cf4
            }
Packit Service 672cf4
        }
Packit Service 672cf4
        QVERIFY(!result.error());
Packit Service 672cf4
        QVERIFY(!keys.empty());
Packit Service 672cf4
        auto key = keys[0];
Packit Service 672cf4
        QVERIFY(!key.isNull());
Packit Service 672cf4
        QVERIFY(key.userID(0).tofuInfo().policy() != TofuInfo::PolicyBad);
Packit Service 672cf4
        auto *tofuJob = openpgp()->tofuPolicyJob();
Packit Service 672cf4
        auto err = tofuJob->exec(key, TofuInfo::PolicyBad);
Packit Service 672cf4
        QVERIFY(!err);
Packit Service 672cf4
        result = job->exec(QStringList() << QStringLiteral("bravo@example.net"),
Packit Service 672cf4
                                            false, keys);
Packit Service 672cf4
        QVERIFY(!keys.empty());
Packit Service 672cf4
        key = keys[0];
Packit Service 672cf4
        QVERIFY(key.userID(0).tofuInfo().policy() == TofuInfo::PolicyBad);
Packit Service 672cf4
        err = tofuJob->exec(key, TofuInfo::PolicyGood);
Packit Service 672cf4
Packit Service 672cf4
        result = job->exec(QStringList() << QStringLiteral("bravo@example.net"),
Packit Service 672cf4
                                            false, keys);
Packit Service 672cf4
        key = keys[0];
Packit Service 672cf4
        QVERIFY(key.userID(0).tofuInfo().policy() == TofuInfo::PolicyGood);
Packit Service 672cf4
        delete tofuJob;
Packit Service 672cf4
        delete job;
Packit Service 672cf4
    }
Packit Service 672cf4
Packit Service 672cf4
    void testTofuConflict()
Packit Service 672cf4
    {
Packit Service 672cf4
        if (!testSupported()) {
Packit Service 672cf4
            return;
Packit Service 672cf4
        }
Packit Service 672cf4
Packit Service 672cf4
        if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.1.19") {
Packit Service 672cf4
            return;
Packit Service 672cf4
        }
Packit Service 672cf4
Packit Service 672cf4
        // Import key 1
Packit Service 672cf4
        auto importjob = openpgp()->importJob();
Packit Service 672cf4
        connect(importjob, &ImportJob::result, this,
Packit Service 672cf4
                [this](ImportResult result, QString, Error)
Packit Service 672cf4
        {
Packit Service 672cf4
            QVERIFY(!result.error());
Packit Service 672cf4
            QVERIFY(!result.imports().empty());
Packit Service 672cf4
            QVERIFY(result.numImported());
Packit Service 672cf4
            Q_EMIT asyncDone();
Packit Service 672cf4
        });
Packit Service 672cf4
        importjob->start(QByteArray(conflictKey1));
Packit Service 672cf4
        QSignalSpy spy (this, SIGNAL(asyncDone()));
Packit Service 672cf4
        QVERIFY(spy.wait());
Packit Service 672cf4
Packit Service 672cf4
        // Verify Message 1
Packit Service 672cf4
        const QByteArray signedData(conflictMsg1);
Packit Service 672cf4
        auto verifyJob = openpgp()->verifyOpaqueJob(true);
Packit Service 672cf4
        QByteArray verified;
Packit Service 672cf4
        auto result = verifyJob->exec(signedData, verified);
Packit Service 672cf4
        delete verifyJob;
Packit Service 672cf4
Packit Service 672cf4
        QVERIFY(!result.isNull());
Packit Service 672cf4
        QVERIFY(!result.error());
Packit Service 672cf4
Packit Service 672cf4
        QVERIFY(result.numSignatures() == 1);
Packit Service 672cf4
        auto sig = result.signatures()[0];
Packit Service 672cf4
        QVERIFY(sig.validity() == Signature::Marginal);
Packit Service 672cf4
Packit Service 672cf4
        auto stats = sig.key().userID(0).tofuInfo();
Packit Service 672cf4
        QVERIFY(!stats.isNull());
Packit Service 672cf4
        QVERIFY(!strcmp(sig.key().primaryFingerprint(), sig.fingerprint()));
Packit Service 672cf4
        QVERIFY(stats.signFirst() == stats.signLast());
Packit Service 672cf4
        QVERIFY(stats.signCount() == 1);
Packit Service 672cf4
        QVERIFY(stats.policy() == TofuInfo::PolicyAuto);
Packit Service 672cf4
        QVERIFY(stats.validity() == TofuInfo::LittleHistory);
Packit Service 672cf4
Packit Service 672cf4
        // Import key 2
Packit Service 672cf4
        importjob = openpgp()->importJob();
Packit Service 672cf4
        connect(importjob, &ImportJob::result, this,
Packit Service 672cf4
                [this](ImportResult result, QString, Error)
Packit Service 672cf4
        {
Packit Service 672cf4
            QVERIFY(!result.error());
Packit Service 672cf4
            QVERIFY(!result.imports().empty());
Packit Service 672cf4
            QVERIFY(result.numImported());
Packit Service 672cf4
            Q_EMIT asyncDone();
Packit Service 672cf4
        });
Packit Service 672cf4
        importjob->start(QByteArray(conflictKey2));
Packit Service 672cf4
        QSignalSpy spy2 (this, SIGNAL(asyncDone()));
Packit Service 672cf4
        QVERIFY(spy2.wait());
Packit Service 672cf4
Packit Service 672cf4
        // Verify Message 2
Packit Service 672cf4
        const QByteArray signedData2(conflictMsg2);
Packit Service 672cf4
        QByteArray verified2;
Packit Service 672cf4
        verifyJob = openpgp()->verifyOpaqueJob(true);
Packit Service 672cf4
        result = verifyJob->exec(signedData2, verified2);
Packit Service 672cf4
        delete verifyJob;
Packit Service 672cf4
Packit Service 672cf4
        QVERIFY(!result.isNull());
Packit Service 672cf4
        QVERIFY(!result.error());
Packit Service 672cf4
Packit Service 672cf4
        QVERIFY(result.numSignatures() == 1);
Packit Service 672cf4
        sig = result.signatures()[0];
Packit Service 672cf4
        QVERIFY(sig.validity() == Signature::Unknown);
Packit Service 672cf4
        // TODO activate when implemented
Packit Service 672cf4
        // QVERIFY(sig.summary() == Signature::TofuConflict);
Packit Service 672cf4
Packit Service 672cf4
        stats = sig.key().userID(0).tofuInfo();
Packit Service 672cf4
        QVERIFY(!stats.isNull());
Packit Service 672cf4
        QVERIFY(!strcmp(sig.key().primaryFingerprint(), sig.fingerprint()));
Packit Service 672cf4
        QVERIFY(stats.signFirst() == stats.signLast());
Packit Service 672cf4
        QVERIFY(stats.signCount() == 1);
Packit Service 672cf4
        QVERIFY(stats.policy() == TofuInfo::PolicyAsk);
Packit Service 672cf4
        QVERIFY(stats.validity() == TofuInfo::Conflict);
Packit Service 672cf4
    }
Packit Service 672cf4
Packit Service 672cf4
Packit Service 672cf4
    void initTestCase()
Packit Service 672cf4
    {
Packit Service 672cf4
        QGpgMETest::initTestCase();
Packit Service 672cf4
        const QString gpgHome = qgetenv("GNUPGHOME");
Packit Service 672cf4
        qputenv("GNUPGHOME", mDir.path().toUtf8());
Packit Service 672cf4
        QVERIFY(mDir.isValid());
Packit Service 672cf4
        QFile conf(mDir.path() + QStringLiteral("/gpg.conf"));
Packit Service 672cf4
        QVERIFY(conf.open(QIODevice::WriteOnly));
Packit Service 672cf4
        conf.write("trust-model tofu+pgp");
Packit Service 672cf4
        conf.close();
Packit Service 672cf4
        QFile agentConf(mDir.path() + QStringLiteral("/gpg-agent.conf"));
Packit Service 672cf4
        QVERIFY(agentConf.open(QIODevice::WriteOnly));
Packit Service 672cf4
        agentConf.write("allow-loopback-pinentry");
Packit Service 672cf4
        agentConf.close();
Packit Service 672cf4
        QVERIFY(copyKeyrings(gpgHome, mDir.path()));
Packit Service 672cf4
    }
Packit Service 672cf4
private:
Packit Service 672cf4
    QTemporaryDir mDir;
Packit Service 672cf4
Packit Service 672cf4
};
Packit Service 672cf4
Packit Service 672cf4
QTEST_MAIN(TofuInfoTest)
Packit Service 672cf4
Packit Service 672cf4
#include "t-tofuinfo.moc"