Qt: Add encryption test and refactor testsuite
[gpgme.git] / lang / qt / tests / t-tofuinfo.cpp
1 /* t-tofuinfo.cpp
2
3     This file is part of qgpgme, the Qt API binding for gpgme
4     Copyright (c) 2016 Intevation GmbH
5
6     QGpgME is free software; you can redistribute it and/or
7     modify it under the terms of the GNU General Public License as
8     published by the Free Software Foundation; either version 2 of the
9     License, or (at your option) any later version.
10
11     QGpgME is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14     General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19
20     In addition, as a special exception, the copyright holders give
21     permission to link the code of this program with any edition of
22     the Qt library by Trolltech AS, Norway (or with modified versions
23     of Qt that use the same license as Qt), and distribute linked
24     combinations including the two.  You must obey the GNU General
25     Public License in all respects for all of the code used other than
26     Qt.  If you modify this file, you may extend this exception to
27     your version of the file, but you are not obligated to do so.  If
28     you do not wish to do so, delete this exception statement from
29     your version.
30 */
31 #include <QDebug>
32 #include <QTest>
33 #include <QTemporaryDir>
34 #include "protocol.h"
35 #include "tofuinfo.h"
36 #include "verifyopaquejob.h"
37 #include "verificationresult.h"
38 #include "signingresult.h"
39 #include "keylistjob.h"
40 #include "keylistresult.h"
41 #include "qgpgmesignjob.h"
42 #include "key.h"
43 #include "t-support.h"
44 #include <iostream>
45
46 using namespace QGpgME;
47 using namespace GpgME;
48
49 static const char testMsg1[] =
50 "-----BEGIN PGP MESSAGE-----\n"
51 "\n"
52 "owGbwMvMwCSoW1RzPCOz3IRxjXQSR0lqcYleSUWJTZOvjVdpcYmCu1+oQmaJIleH\n"
53 "GwuDIBMDGysTSIqBi1MApi+nlGGuwDeHao53HBr+FoVGP3xX+kvuu9fCMJvl6IOf\n"
54 "y1kvP4y+8D5a11ang0udywsA\n"
55 "=Crq6\n"
56 "-----END PGP MESSAGE-----\n";
57
58 class TofuInfoTest: public QGpgMETest
59 {
60     Q_OBJECT
61
62     void testTofuCopy(TofuInfo other, const TofuInfo &orig)
63     {
64         Q_ASSERT(!orig.isNull());
65         Q_ASSERT(!other.isNull());
66         Q_ASSERT(!strcmp(orig.fingerprint(), other.fingerprint()));
67         Q_ASSERT(orig.lastSeen() == other.lastSeen());
68         Q_ASSERT(orig.signCount() == other.signCount());
69         Q_ASSERT(orig.validity() == other.validity());
70         Q_ASSERT(orig.policy() == other.policy());
71     }
72
73     void signAndVerify(const QString &what, const GpgME::Key &key, int expected)
74     {
75         Context *ctx = Context::createForProtocol(OpenPGP);
76         ctx->setPassphraseProvider(new TestPassphraseProvider);
77         ctx->setPinentryMode(Context::PinentryLoopback);
78         auto *job = new QGpgMESignJob(ctx);
79
80         std::vector<Key> keys;
81         keys.push_back(key);
82         QByteArray signedData;
83         auto sigResult = job->exec(keys, what.toUtf8(), NormalSignatureMode, signedData);
84
85         Q_ASSERT(!sigResult.error());
86
87         auto verifyJob = openpgp()->verifyOpaqueJob();
88         QByteArray verified;
89
90         auto result = verifyJob->exec(signedData, verified);
91
92         Q_ASSERT(!result.error());
93         Q_ASSERT(verified == what.toUtf8());
94
95         Q_ASSERT(result.numSignatures() == 1);
96         auto sig = result.signatures()[0];
97
98         Q_FOREACH(const TofuInfo stats, sig.tofuInfo()) {
99             Q_ASSERT(!stats.isNull());
100             Q_ASSERT(!strcmp(stats.fingerprint(), sig.fingerprint()));
101             Q_ASSERT(stats.signCount() == expected);
102         }
103     }
104
105 private:
106     QTemporaryDir mDir;
107
108 private /* FIXME Disabled until GnuPG-Bug-Id 2405 is fixed Q_SLOTS */:
109     void testTofuNull()
110     {
111         TofuInfo tofu;
112         Q_ASSERT(tofu.isNull());
113         Q_ASSERT(!tofu.fingerprint());
114         Q_ASSERT(!tofu.address());
115         Q_ASSERT(!tofu.description());
116         Q_ASSERT(!tofu.signCount());
117         Q_ASSERT(!tofu.lastSeen());
118         Q_ASSERT(!tofu.firstSeen());
119         Q_ASSERT(tofu.validity() == TofuInfo::ValidityUnknown);
120         Q_ASSERT(tofu.policy() == TofuInfo::PolicyUnknown);
121     }
122
123     void testTofuInfo()
124     {
125         auto *job = openpgp()->verifyOpaqueJob(true);
126         const QByteArray data1(testMsg1);
127         QByteArray plaintext;
128
129         auto result = job->exec(data1, plaintext);
130
131         Q_ASSERT(!result.isNull());
132         Q_ASSERT(!result.error());
133         Q_ASSERT(!strcmp(plaintext.constData(), "Just GNU it!\n"));
134
135         Q_ASSERT(result.numSignatures() == 1);
136         Signature sig = result.signatures()[0];
137         /* TOFU is always marginal */
138         Q_ASSERT(sig.validity() == Signature::Marginal);
139
140         Q_ASSERT(!sig.tofuInfo().empty());
141         Q_FOREACH(const TofuInfo stats, sig.tofuInfo()) {
142             Q_ASSERT(!stats.isNull());
143             Q_ASSERT(!strcmp(stats.fingerprint(), sig.fingerprint()));
144             Q_ASSERT(stats.firstSeen() == stats.lastSeen());
145             Q_ASSERT(!stats.signCount());
146             Q_ASSERT(stats.address());
147           /* See issue2405 Comment back in when resolved
148             Q_ASSERT(stats.policy() == TofuInfo::PolicyAuto); */
149             Q_ASSERT(stats.validity() == TofuInfo::NoHistory);
150         }
151
152         const TofuInfo first = sig.tofuInfo()[0];
153         testTofuCopy(first, first);
154
155         /* Another verify */
156
157         job = openpgp()->verifyOpaqueJob(true);
158         result = job->exec(data1, plaintext);
159
160         Q_ASSERT(!result.isNull());
161         Q_ASSERT(!result.error());
162
163         Q_ASSERT(result.numSignatures() == 1);
164         sig = result.signatures()[0];
165         /* TOFU is always marginal */
166         Q_ASSERT(sig.validity() == Signature::Marginal);
167
168         Q_ASSERT(!sig.tofuInfo().empty());
169         Q_FOREACH(const TofuInfo stats, sig.tofuInfo()) {
170             Q_ASSERT(!stats.isNull());
171             Q_ASSERT(!strcmp(stats.fingerprint(), sig.fingerprint()));
172             Q_ASSERT(stats.signCount() == 1);
173             Q_ASSERT(stats.address());
174             Q_ASSERT(stats.policy() == TofuInfo::PolicyAuto);
175             Q_ASSERT(stats.validity() == TofuInfo::LittleHistory);
176         }
177
178         /* Verify that another call yields the same result */
179         job = openpgp()->verifyOpaqueJob(true);
180         result = job->exec(data1, plaintext);
181
182         Q_ASSERT(!result.isNull());
183         Q_ASSERT(!result.error());
184
185         Q_ASSERT(result.numSignatures() == 1);
186         sig = result.signatures()[0];
187         /* TOFU is always marginal */
188         Q_ASSERT(sig.validity() == Signature::Marginal);
189
190         Q_ASSERT(!sig.tofuInfo().empty());
191         Q_FOREACH(const TofuInfo stats, sig.tofuInfo()) {
192             Q_ASSERT(!stats.isNull());
193             Q_ASSERT(!strcmp(stats.fingerprint(), sig.fingerprint()));
194             Q_ASSERT(stats.signCount() == 1);
195             Q_ASSERT(stats.address());
196             Q_ASSERT(stats.policy() == TofuInfo::PolicyAuto);
197             Q_ASSERT(stats.validity() == TofuInfo::LittleHistory);
198         }
199     }
200
201     void testTofuSignCount()
202     {
203         auto *job = openpgp()->keyListJob(false, false, false);
204         std::vector<GpgME::Key> keys;
205         GpgME::KeyListResult result = job->exec(QStringList() << QStringLiteral("zulu@example.net"),
206                                                 true, keys);
207         Q_ASSERT(!keys.empty());
208         Key key = keys[0];
209         Q_ASSERT(!key.isNull());
210
211         signAndVerify(QStringLiteral("Hello"), key, 0);
212         signAndVerify(QStringLiteral("Hello2"), key, 1);
213         signAndVerify(QStringLiteral("Hello3"), key, 2);
214         signAndVerify(QStringLiteral("Hello4"), key, 3);
215     }
216
217     void initTestCase()
218     {
219         QGpgMETest::initTestCase();
220         const QString gpgHome = qgetenv("GNUPGHOME");
221         qputenv("GNUPGHOME", mDir.path().toUtf8());
222         Q_ASSERT(mDir.isValid());
223         QFile conf(mDir.path() + QStringLiteral("/gpg.conf"));
224         Q_ASSERT(conf.open(QIODevice::WriteOnly));
225         conf.write("trust-model tofu+pgp");
226         conf.close();
227         QFile agentConf(mDir.path() + QStringLiteral("/gpg-agent.conf"));
228         Q_ASSERT(agentConf.open(QIODevice::WriteOnly));
229         agentConf.write("allow-loopback-pinentry");
230         agentConf.close();
231         Q_ASSERT(QFile::copy(gpgHome + QStringLiteral("/pubring.gpg"),
232                  mDir.path() + QStringLiteral("/pubring.gpg")));
233         Q_ASSERT(QFile::copy(gpgHome + QStringLiteral("/secring.gpg"),
234                  mDir.path() + QStringLiteral("/secring.gpg")));
235
236     }
237 };
238
239 QTEST_MAIN(TofuInfoTest)
240
241 #include "t-tofuinfo.moc"