Line data Source code
1 : /* t-tofuinfo.cpp
2 :
3 : This file is part of qgpgme, the Qt API binding for gpgme
4 : Copyright (c) 2016 by Bundesamt für Sicherheit in der Informationstechnik
5 : Software engineering by Intevation GmbH
6 :
7 : QGpgME is free software; you can redistribute it and/or
8 : modify it under the terms of the GNU General Public License as
9 : published by the Free Software Foundation; either version 2 of the
10 : License, or (at your option) any later version.
11 :
12 : QGpgME is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with this program; if not, write to the Free Software
19 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 :
21 : In addition, as a special exception, the copyright holders give
22 : permission to link the code of this program with any edition of
23 : the Qt library by Trolltech AS, Norway (or with modified versions
24 : of Qt that use the same license as Qt), and distribute linked
25 : combinations including the two. You must obey the GNU General
26 : Public License in all respects for all of the code used other than
27 : Qt. If you modify this file, you may extend this exception to
28 : your version of the file, but you are not obligated to do so. If
29 : you do not wish to do so, delete this exception statement from
30 : your version.
31 : */
32 : #ifdef HAVE_CONFIG_H
33 : #include "config.h"
34 : #endif
35 :
36 : #include <QDebug>
37 : #include <QTest>
38 : #include <QTemporaryDir>
39 : #include <QSignalSpy>
40 :
41 : #include "protocol.h"
42 : #include "tofuinfo.h"
43 : #include "tofupolicyjob.h"
44 : #include "verifyopaquejob.h"
45 : #include "verificationresult.h"
46 : #include "signingresult.h"
47 : #include "importjob.h"
48 : #include "importresult.h"
49 : #include "keylistjob.h"
50 : #include "keylistresult.h"
51 : #include "signjob.h"
52 : #include "key.h"
53 : #include "t-support.h"
54 : #include "engineinfo.h"
55 : #include "context.h"
56 : #include <iostream>
57 :
58 : using namespace QGpgME;
59 : using namespace GpgME;
60 :
61 : static const char testMsg1[] =
62 : "-----BEGIN PGP MESSAGE-----\n"
63 : "\n"
64 : "owGbwMvMwCSoW1RzPCOz3IRxjXQSR0lqcYleSUWJTZOvjVdpcYmCu1+oQmaJIleH\n"
65 : "GwuDIBMDGysTSIqBi1MApi+nlGGuwDeHao53HBr+FoVGP3xX+kvuu9fCMJvl6IOf\n"
66 : "y1kvP4y+8D5a11ang0udywsA\n"
67 : "=Crq6\n"
68 : "-----END PGP MESSAGE-----\n";
69 :
70 : static const char conflictKey1[] = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n"
71 : "\n"
72 : "mDMEWG+w/hYJKwYBBAHaRw8BAQdAiq1oStvDYg8ZfFs5DgisYJo8dJxD+C/AA21O\n"
73 : "K/aif0O0GXRvZnVfY29uZmxpY3RAZXhhbXBsZS5jb22IlgQTFggAPhYhBHoJBLaV\n"
74 : "DamYAgoa1L5BwMOl/x88BQJYb7D+AhsDBQkDwmcABQsJCAcCBhUICQoLAgQWAgMB\n"
75 : "Ah4BAheAAAoJEL5BwMOl/x88GvwA/0SxkbLyAcshGm2PRrPsFQsSVAfwaSYFVmS2\n"
76 : "cMVIw1PfAQDclRH1Z4MpufK07ju4qI33o4s0UFpVRBuSxt7A4P2ZD7g4BFhvsP4S\n"
77 : "CisGAQQBl1UBBQEBB0AmVrgaDNJ7K2BSalsRo2EkRJjHGqnp5bBB0tapnF81CQMB\n"
78 : "CAeIeAQYFggAIBYhBHoJBLaVDamYAgoa1L5BwMOl/x88BQJYb7D+AhsMAAoJEL5B\n"
79 : "wMOl/x88OR0BAMq4/vmJUORRTmzjHcv/DDrQB030DSq666rlckGIKTShAPoDXM9N\n"
80 : "0gZK+YzvrinSKZXHmn0aSwmC1/hyPybJPEljBw==\n"
81 : "=p2Oj\n"
82 : "-----END PGP PUBLIC KEY BLOCK-----\n";
83 :
84 : static const char conflictKey2[] = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n"
85 : "\n"
86 : "mDMEWG+xShYJKwYBBAHaRw8BAQdA567gPEPJRpqKnZjlFJMRNUqruRviYMyygfF6\n"
87 : "6Ok+ygu0GXRvZnVfY29uZmxpY3RAZXhhbXBsZS5jb22IlgQTFggAPhYhBJ5kRh7E\n"
88 : "I98w8kgUcmkAfYFvqqHsBQJYb7FKAhsDBQkDwmcABQsJCAcCBhUICQoLAgQWAgMB\n"
89 : "Ah4BAheAAAoJEGkAfYFvqqHsYR0BAOz8JjYB4VvGkt6noLS3F5TLfsedGwQkBCw5\n"
90 : "znw/vGZsAQD9DSX+ekwdrN56mNO8ISt5uVS7B1ZQtouNBF+nzcwbDbg4BFhvsUoS\n"
91 : "CisGAQQBl1UBBQEBB0BFupW8+Xc1ikab8TJqANjQhvFVh6uLsgcK4g9lZgbGXAMB\n"
92 : "CAeIeAQYFggAIBYhBJ5kRh7EI98w8kgUcmkAfYFvqqHsBQJYb7FKAhsMAAoJEGkA\n"
93 : "fYFvqqHs15ABALdN3uiV/07cJ3RkNb3WPcijGsto+lECDS11dKEwTMFeAQDx+V36\n"
94 : "ocbYC/xEuwi3w45oNqGieazzcD/GBbt8OBk3BA==\n"
95 : "=45IR\n"
96 : "-----END PGP PUBLIC KEY BLOCK-----\n";
97 :
98 : static const char conflictMsg1[] = "-----BEGIN PGP MESSAGE-----\n"
99 : "\n"
100 : "owGbwMvMwCG2z/HA4aX/5W0YT3MlMUTkb2xPSizi6ihlYRDjYJAVU2Sp4mTZNpV3\n"
101 : "5QwmLqkrMLWsTCCFDFycAjCR1vcMf4U0Qrs6qzqfHJ9puGOFduLN2nVmhsumxjBE\n"
102 : "mdw4lr1ehIWR4QdLuNBpe86PGx1PtNXfVAzm/hu+vfjCp5BVNjPTM9L0eAA=\n"
103 : "=MfBD\n"
104 : "-----END PGP MESSAGE-----\n";
105 :
106 : static const char conflictMsg2[] = "-----BEGIN PGP MESSAGE-----\n"
107 : "\n"
108 : "owGbwMvMwCGWyVDbmL9q4RvG01xJDBH5GyvS8vO5OkpZGMQ4GGTFFFnmpbjJHVG+\n"
109 : "b/DJQ6QIppaVCaSQgYtTACaySZHhr/SOPrdFJ89KrcwKY5i1XnflXYf2PK76SafK\n"
110 : "tkxXuXzvJAvDX4kCybuqFk3HXCexz2+IrnZ+5X5EqOnuo3ens2cte+uzlhMA\n"
111 : "=BIAi\n"
112 : "-----END PGP MESSAGE-----\n";
113 :
114 2 : class TofuInfoTest: public QGpgMETest
115 : {
116 : Q_OBJECT
117 : Q_SIGNALS:
118 : void asyncDone();
119 :
120 : private:
121 6 : bool testSupported()
122 : {
123 : static bool initialized, supported;
124 6 : if (initialized) {
125 5 : return supported;
126 : }
127 1 : initialized = true;
128 1 : if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.1.16") {
129 0 : return false;
130 : }
131 : // If the keylist fails here this means that gnupg does not
132 : // support tofu at all. It can be disabled at compile time. So no
133 : // tests.
134 1 : auto *job = openpgp()->keyListJob(false, false, false);
135 1 : job->addMode(GpgME::WithTofu);
136 2 : std::vector<GpgME::Key> keys;
137 2 : job->exec(QStringList() << QStringLiteral("zulu@example.net"), true, keys);
138 1 : delete job;
139 1 : supported = !keys.empty();
140 1 : return supported;
141 : }
142 :
143 1 : void testTofuCopy(TofuInfo other, const TofuInfo &orig)
144 : {
145 1 : QVERIFY(!orig.isNull());
146 1 : QVERIFY(!other.isNull());
147 1 : QVERIFY(orig.signLast() == other.signLast());
148 1 : QVERIFY(orig.signCount() == other.signCount());
149 1 : QVERIFY(orig.validity() == other.validity());
150 1 : QVERIFY(orig.policy() == other.policy());
151 : }
152 :
153 6 : void signAndVerify(const QString &what, const GpgME::Key &key, int expected)
154 : {
155 6 : auto job = openpgp()->signJob();
156 6 : auto ctx = Job::context(job);
157 12 : TestPassphraseProvider provider;
158 6 : ctx->setPassphraseProvider(&provider);
159 6 : ctx->setPinentryMode(Context::PinentryLoopback);
160 :
161 12 : std::vector<Key> keys;
162 6 : keys.push_back(key);
163 12 : QByteArray signedData;
164 12 : auto sigResult = job->exec(keys, what.toUtf8(), NormalSignatureMode, signedData);
165 6 : delete job;
166 :
167 6 : QVERIFY(!sigResult.error());
168 12 : foreach (const auto uid, keys[0].userIDs()) {
169 12 : auto info = uid.tofuInfo();
170 6 : QVERIFY(info.signCount() == expected - 1);
171 : }
172 :
173 6 : auto verifyJob = openpgp()->verifyOpaqueJob();
174 12 : QByteArray verified;
175 :
176 12 : auto result = verifyJob->exec(signedData, verified);
177 6 : delete verifyJob;
178 :
179 6 : QVERIFY(!result.error());
180 6 : QVERIFY(verified == what.toUtf8());
181 :
182 6 : QVERIFY(result.numSignatures() == 1);
183 12 : auto sig = result.signatures()[0];
184 :
185 12 : auto key2 = sig.key();
186 6 : QVERIFY(!key.isNull());
187 6 : QVERIFY(!strcmp (key2.primaryFingerprint(), key.primaryFingerprint()));
188 6 : QVERIFY(!strcmp (key.primaryFingerprint(), sig.fingerprint()));
189 12 : auto stats = key2.userID(0).tofuInfo();
190 6 : QVERIFY(!stats.isNull());
191 6 : if (stats.signCount() != expected) {
192 0 : std::cout << "################ Key before verify: "
193 0 : << key
194 0 : << "################ Key after verify: "
195 0 : << key2;
196 : }
197 6 : QVERIFY(stats.signCount() == expected);
198 : }
199 :
200 : private Q_SLOTS:
201 1 : void testTofuNull()
202 : {
203 1 : if (!testSupported()) {
204 0 : return;
205 : }
206 2 : TofuInfo tofu;
207 1 : QVERIFY(tofu.isNull());
208 1 : QVERIFY(!tofu.description());
209 1 : QVERIFY(!tofu.signCount());
210 1 : QVERIFY(!tofu.signLast());
211 1 : QVERIFY(!tofu.signFirst());
212 1 : QVERIFY(tofu.validity() == TofuInfo::ValidityUnknown);
213 1 : QVERIFY(tofu.policy() == TofuInfo::PolicyUnknown);
214 : }
215 :
216 1 : void testTofuInfo()
217 : {
218 1 : if (!testSupported()) {
219 0 : return;
220 : }
221 1 : auto *job = openpgp()->verifyOpaqueJob(true);
222 2 : const QByteArray data1(testMsg1);
223 2 : QByteArray plaintext;
224 :
225 1 : auto ctx = Job::context(job);
226 1 : QVERIFY(ctx);
227 1 : ctx->setSender("alfa@example.net");
228 :
229 2 : auto result = job->exec(data1, plaintext);
230 1 : delete job;
231 :
232 1 : QVERIFY(!result.isNull());
233 1 : QVERIFY(!result.error());
234 1 : QVERIFY(!strcmp(plaintext.constData(), "Just GNU it!\n"));
235 :
236 1 : QVERIFY(result.numSignatures() == 1);
237 2 : Signature sig = result.signatures()[0];
238 : /* TOFU is always marginal */
239 1 : QVERIFY(sig.validity() == Signature::Marginal);
240 :
241 2 : auto stats = sig.key().userID(0).tofuInfo();
242 1 : QVERIFY(!stats.isNull());
243 1 : QVERIFY(sig.key().primaryFingerprint());
244 1 : QVERIFY(sig.fingerprint());
245 1 : QVERIFY(!strcmp(sig.key().primaryFingerprint(), sig.fingerprint()));
246 1 : QVERIFY(stats.signFirst() == stats.signLast());
247 1 : QVERIFY(stats.signCount() == 1);
248 1 : QVERIFY(stats.policy() == TofuInfo::PolicyAuto);
249 1 : QVERIFY(stats.validity() == TofuInfo::LittleHistory);
250 :
251 1 : testTofuCopy(stats, stats);
252 :
253 : /* Another verify */
254 :
255 1 : job = openpgp()->verifyOpaqueJob(true);
256 1 : result = job->exec(data1, plaintext);
257 1 : delete job;
258 :
259 1 : QVERIFY(!result.isNull());
260 1 : QVERIFY(!result.error());
261 :
262 1 : QVERIFY(result.numSignatures() == 1);
263 1 : sig = result.signatures()[0];
264 : /* TOFU is always marginal */
265 1 : QVERIFY(sig.validity() == Signature::Marginal);
266 :
267 1 : stats = sig.key().userID(0).tofuInfo();
268 1 : QVERIFY(!stats.isNull());
269 1 : QVERIFY(!strcmp(sig.key().primaryFingerprint(), sig.fingerprint()));
270 1 : QVERIFY(stats.signFirst() == stats.signLast());
271 1 : QVERIFY(stats.signCount() == 1);
272 1 : QVERIFY(stats.policy() == TofuInfo::PolicyAuto);
273 1 : QVERIFY(stats.validity() == TofuInfo::LittleHistory);
274 :
275 : /* Verify that another call yields the same result */
276 1 : job = openpgp()->verifyOpaqueJob(true);
277 1 : result = job->exec(data1, plaintext);
278 1 : delete job;
279 :
280 1 : QVERIFY(!result.isNull());
281 1 : QVERIFY(!result.error());
282 :
283 1 : QVERIFY(result.numSignatures() == 1);
284 1 : sig = result.signatures()[0];
285 : /* TOFU is always marginal */
286 1 : QVERIFY(sig.validity() == Signature::Marginal);
287 :
288 1 : stats = sig.key().userID(0).tofuInfo();
289 1 : QVERIFY(!stats.isNull());
290 1 : QVERIFY(!strcmp(sig.key().primaryFingerprint(), sig.fingerprint()));
291 1 : QVERIFY(stats.signFirst() == stats.signLast());
292 1 : QVERIFY(stats.signCount() == 1);
293 1 : QVERIFY(stats.policy() == TofuInfo::PolicyAuto);
294 1 : QVERIFY(stats.validity() == TofuInfo::LittleHistory);
295 : }
296 :
297 1 : void testTofuSignCount()
298 : {
299 1 : if (!testSupported()) {
300 0 : return;
301 : }
302 1 : auto *job = openpgp()->keyListJob(false, false, false);
303 1 : job->addMode(GpgME::WithTofu);
304 2 : std::vector<GpgME::Key> keys;
305 3 : GpgME::KeyListResult result = job->exec(QStringList() << QStringLiteral("zulu@example.net"),
306 3 : true, keys);
307 1 : delete job;
308 1 : QVERIFY(!keys.empty());
309 2 : Key key = keys[0];
310 1 : QVERIFY(!key.isNull());
311 :
312 : /* As we sign & verify quickly here we need different
313 : * messages to avoid having them treated as the same
314 : * message if they were created within the same second.
315 : * Alternatively we could use the same message and wait
316 : * a second between each call. But this would slow down
317 : * the testsuite. */
318 2 : signAndVerify(QStringLiteral("Hello"), key, 1);
319 1 : key.update();
320 2 : signAndVerify(QStringLiteral("Hello2"), key, 2);
321 1 : key.update();
322 2 : signAndVerify(QStringLiteral("Hello3"), key, 3);
323 1 : key.update();
324 2 : signAndVerify(QStringLiteral("Hello4"), key, 4);
325 : }
326 :
327 1 : void testTofuKeyList()
328 : {
329 1 : if (!testSupported()) {
330 0 : return;
331 : }
332 :
333 : /* First check that the key has no tofu info. */
334 1 : auto *job = openpgp()->keyListJob(false, false, false);
335 2 : std::vector<GpgME::Key> keys;
336 3 : auto result = job->exec(QStringList() << QStringLiteral("zulu@example.net"),
337 3 : true, keys);
338 1 : delete job;
339 1 : QVERIFY(!keys.empty());
340 2 : auto key = keys[0];
341 1 : QVERIFY(!key.isNull());
342 1 : QVERIFY(key.userID(0).tofuInfo().isNull());
343 2 : auto keyCopy = key;
344 1 : keyCopy.update();
345 1 : auto sigCnt = keyCopy.userID(0).tofuInfo().signCount();
346 3 : signAndVerify(QStringLiteral("Hello5"), keyCopy,
347 1 : sigCnt + 1);
348 1 : keyCopy.update();
349 3 : signAndVerify(QStringLiteral("Hello6"), keyCopy,
350 1 : sigCnt + 2);
351 :
352 : /* Now another one but with tofu */
353 1 : job = openpgp()->keyListJob(false, false, false);
354 1 : job->addMode(GpgME::WithTofu);
355 3 : result = job->exec(QStringList() << QStringLiteral("zulu@example.net"),
356 2 : true, keys);
357 1 : delete job;
358 1 : QVERIFY(!result.error());
359 1 : QVERIFY(!keys.empty());
360 2 : auto key2 = keys[0];
361 1 : QVERIFY(!key2.isNull());
362 2 : auto info = key2.userID(0).tofuInfo();
363 1 : QVERIFY(!info.isNull());
364 1 : QVERIFY(info.signCount());
365 : }
366 :
367 1 : void testTofuPolicy()
368 : {
369 1 : if (!testSupported()) {
370 0 : return;
371 : }
372 :
373 : /* First check that the key has no tofu info. */
374 1 : auto *job = openpgp()->keyListJob(false, false, false);
375 2 : std::vector<GpgME::Key> keys;
376 1 : job->addMode(GpgME::WithTofu);
377 3 : auto result = job->exec(QStringList() << QStringLiteral("bravo@example.net"),
378 3 : false, keys);
379 :
380 1 : if (keys.empty()) {
381 0 : qDebug() << "bravo@example.net not found";
382 0 : qDebug() << "Error: " << result.error().asString();
383 0 : const auto homedir = QString::fromLocal8Bit(qgetenv("GNUPGHOME"));
384 0 : qDebug() << "Homedir is: " << homedir;
385 0 : QFileInfo fi(homedir + "/pubring.gpg");
386 0 : qDebug () << "pubring exists: " << fi.exists() << " readable? "
387 0 : << fi.isReadable() << " size: " << fi.size();
388 0 : QFileInfo fi2(homedir + "/pubring.kbx");
389 0 : qDebug () << "keybox exists: " << fi2.exists() << " readable? "
390 0 : << fi2.isReadable() << " size: " << fi2.size();
391 :
392 0 : result = job->exec(QStringList(), false, keys);
393 0 : foreach (const auto key, keys) {
394 0 : qDebug() << "Key: " << key.userID(0).name() << " <"
395 0 : << key.userID(0).email()
396 0 : << ">\n fpr: " << key.primaryFingerprint();
397 : }
398 : }
399 1 : QVERIFY(!result.error());
400 1 : QVERIFY(!keys.empty());
401 2 : auto key = keys[0];
402 1 : QVERIFY(!key.isNull());
403 1 : QVERIFY(key.userID(0).tofuInfo().policy() != TofuInfo::PolicyBad);
404 1 : auto *tofuJob = openpgp()->tofuPolicyJob();
405 2 : auto err = tofuJob->exec(key, TofuInfo::PolicyBad);
406 1 : QVERIFY(!err);
407 3 : result = job->exec(QStringList() << QStringLiteral("bravo@example.net"),
408 2 : false, keys);
409 1 : QVERIFY(!keys.empty());
410 1 : key = keys[0];
411 1 : QVERIFY(key.userID(0).tofuInfo().policy() == TofuInfo::PolicyBad);
412 1 : err = tofuJob->exec(key, TofuInfo::PolicyGood);
413 :
414 3 : result = job->exec(QStringList() << QStringLiteral("bravo@example.net"),
415 2 : false, keys);
416 1 : key = keys[0];
417 1 : QVERIFY(key.userID(0).tofuInfo().policy() == TofuInfo::PolicyGood);
418 1 : delete tofuJob;
419 1 : delete job;
420 : }
421 :
422 1 : void testTofuConflict()
423 : {
424 1 : if (!testSupported()) {
425 0 : return;
426 : }
427 :
428 1 : if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.1.19") {
429 0 : return;
430 : }
431 :
432 : // Import key 1
433 1 : auto importjob = openpgp()->importJob();
434 : connect(importjob, &ImportJob::result, this,
435 1 : [this](ImportResult result, QString, Error)
436 1 : {
437 1 : QVERIFY(!result.error());
438 1 : QVERIFY(!result.imports().empty());
439 1 : QVERIFY(result.numImported());
440 1 : Q_EMIT asyncDone();
441 1 : });
442 1 : importjob->start(QByteArray(conflictKey1));
443 2 : QSignalSpy spy (this, SIGNAL(asyncDone()));
444 1 : QVERIFY(spy.wait());
445 :
446 : // Verify Message 1
447 2 : const QByteArray signedData(conflictMsg1);
448 1 : auto verifyJob = openpgp()->verifyOpaqueJob(true);
449 2 : QByteArray verified;
450 2 : auto result = verifyJob->exec(signedData, verified);
451 1 : delete verifyJob;
452 :
453 1 : QVERIFY(!result.isNull());
454 1 : QVERIFY(!result.error());
455 :
456 1 : QVERIFY(result.numSignatures() == 1);
457 2 : auto sig = result.signatures()[0];
458 1 : QVERIFY(sig.validity() == Signature::Marginal);
459 :
460 2 : auto stats = sig.key().userID(0).tofuInfo();
461 1 : QVERIFY(!stats.isNull());
462 1 : QVERIFY(!strcmp(sig.key().primaryFingerprint(), sig.fingerprint()));
463 1 : QVERIFY(stats.signFirst() == stats.signLast());
464 1 : QVERIFY(stats.signCount() == 1);
465 1 : QVERIFY(stats.policy() == TofuInfo::PolicyAuto);
466 1 : QVERIFY(stats.validity() == TofuInfo::LittleHistory);
467 :
468 : // Import key 2
469 1 : importjob = openpgp()->importJob();
470 : connect(importjob, &ImportJob::result, this,
471 1 : [this](ImportResult result, QString, Error)
472 1 : {
473 1 : QVERIFY(!result.error());
474 1 : QVERIFY(!result.imports().empty());
475 1 : QVERIFY(result.numImported());
476 1 : Q_EMIT asyncDone();
477 1 : });
478 1 : importjob->start(QByteArray(conflictKey2));
479 2 : QSignalSpy spy2 (this, SIGNAL(asyncDone()));
480 1 : QVERIFY(spy2.wait());
481 :
482 : // Verify Message 2
483 2 : const QByteArray signedData2(conflictMsg2);
484 2 : QByteArray verified2;
485 1 : verifyJob = openpgp()->verifyOpaqueJob(true);
486 1 : result = verifyJob->exec(signedData2, verified2);
487 1 : delete verifyJob;
488 :
489 1 : QVERIFY(!result.isNull());
490 1 : QVERIFY(!result.error());
491 :
492 1 : QVERIFY(result.numSignatures() == 1);
493 1 : sig = result.signatures()[0];
494 1 : QVERIFY(sig.validity() == Signature::Unknown);
495 : // TODO activate when implemented
496 : // QVERIFY(sig.summary() == Signature::TofuConflict);
497 :
498 1 : stats = sig.key().userID(0).tofuInfo();
499 1 : QVERIFY(!stats.isNull());
500 1 : QVERIFY(!strcmp(sig.key().primaryFingerprint(), sig.fingerprint()));
501 1 : QVERIFY(stats.signFirst() == stats.signLast());
502 1 : QVERIFY(stats.signCount() == 1);
503 1 : QVERIFY(stats.policy() == TofuInfo::PolicyAsk);
504 1 : QVERIFY(stats.validity() == TofuInfo::Conflict);
505 : }
506 :
507 :
508 1 : void initTestCase()
509 : {
510 1 : QGpgMETest::initTestCase();
511 2 : const QString gpgHome = qgetenv("GNUPGHOME");
512 1 : qputenv("GNUPGHOME", mDir.path().toUtf8());
513 1 : QVERIFY(mDir.isValid());
514 3 : QFile conf(mDir.path() + QStringLiteral("/gpg.conf"));
515 1 : QVERIFY(conf.open(QIODevice::WriteOnly));
516 1 : conf.write("trust-model tofu+pgp");
517 1 : conf.close();
518 3 : QFile agentConf(mDir.path() + QStringLiteral("/gpg-agent.conf"));
519 1 : QVERIFY(agentConf.open(QIODevice::WriteOnly));
520 1 : agentConf.write("allow-loopback-pinentry");
521 1 : agentConf.close();
522 1 : QVERIFY(copyKeyrings(gpgHome, mDir.path()));
523 : }
524 : private:
525 : QTemporaryDir mDir;
526 :
527 : };
528 :
529 1 : QTEST_MAIN(TofuInfoTest)
530 :
531 : #include "t-tofuinfo.moc"
|