Line data Source code
1 : /* t-wkspublish.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 <QSignalSpy>
39 : #include <QTemporaryDir>
40 : #include "wkspublishjob.h"
41 : #include "keygenerationjob.h"
42 : #include "keygenerationresult.h"
43 : #include "importjob.h"
44 : #include "importresult.h"
45 : #include "protocol.h"
46 : #include "engineinfo.h"
47 :
48 : #include "t-support.h"
49 :
50 : using namespace QGpgME;
51 : using namespace GpgME;
52 :
53 : //#define DO_ONLINE_TESTS
54 :
55 : #define TEST_ADDRESS "testuser2@test.gnupg.org"
56 :
57 : static const char *testSecKey =
58 : "-----BEGIN PGP PRIVATE KEY BLOCK-----\n"
59 : "\n"
60 : "lHgEV77hVhMJKyQDAwIIAQEHAgMEN3qKqBr9EecnfUnpw8RS8DHAjJqhwm2HAoEE\n"
61 : "3yfQQ9w8uB/bKm5dqW4HML3JWRH8YoJaKSVrJY2D1FZUY+vHlgABAKDwEAB0HND8\n"
62 : "5kbxiJmqKIuuNqCJ2jHgs9G0xk4GdKvZEdq0JlRlc3QgVXNlciAyIDx0ZXN0dXNl\n"
63 : "cjJAdGVzdC5nbnVwZy5vcmc+iHkEExMIACEFAle+4VYCGwMFCwkIBwIGFQgJCgsC\n"
64 : "BBYCAwECHgECF4AACgkQRVRoUEJO+6zgFQD7BF3pnS3w3A7J9y+Y3kyGfmscXFWJ\n"
65 : "Kme1PAsAlVSm1y4A+weReMvWFYHJH257v94yhStmV8egGoybsNDttNAW53cbnHwE\n"
66 : "V77hVhIJKyQDAwIIAQEHAgMEX+6cF0HEn4g3ztFvwHyr7uwXMVYUGL3lE3mjhnV3\n"
67 : "SbY6Dmy3OeFVnEVkawHqSv+HobpQTeEqNoQHAoIiXFCRlgMBCAcAAP9FykiyDspm\n"
68 : "T33XWRPD+LAOmaIU7CIhfv9+lVkeExlU1w+qiGEEGBMIAAkFAle+4VYCGwwACgkQ\n"
69 : "RVRoUEJO+6xjhgD/ZJ/MwYZJPk/xPYhTP8+wF+tErVNA8w3pP9D69dgUPdcA/izZ\n"
70 : "Pji6YetVhgsyaHc4PrKynsk5G6nM3KkAOehUQsX8\n"
71 : "=S/Wa\n"
72 : "-----END PGP PRIVATE KEY BLOCK-----\n";
73 :
74 : static const char *testResponse =
75 : "From key-submission@test.gnupg.org Thu Aug 25 12:15:54 2016\n"
76 : "Return-Path: <webkey@g10code.com>\n"
77 : "From: key-submission@test.gnupg.org\n"
78 : "To: testuser2@test.gnupg.org\n"
79 : "Subject: Confirm your key publication\n"
80 : "X-Wks-Loop: webkey.g10code.com\n"
81 : "MIME-Version: 1.0\n"
82 : "Content-Type: multipart/encrypted; protocol=\"application/pgp-encrypted\";\n"
83 : " boundary=\"=-=01-wbu5fr9nu6fix5tcojjo=-=\"\n"
84 : "Date: Thu, 25 Aug 2016 12:15:54 +0000\n"
85 : "Message-Id: <E1bctZa-0004LE-Fr@kerckhoffs.g10code.com>\n"
86 : "Sender: <webkey@g10code.com>\n"
87 : "X-Kolab-Scheduling-Message: FALSE\n"
88 : "\n"
89 : " \n"
90 : "\n"
91 : "--=-=01-wbu5fr9nu6fix5tcojjo=-=\n"
92 : "Content-Type: application/pgp-encrypted\n"
93 : "\n"
94 : "Version: 1\n"
95 : "\n"
96 : "--=-=01-wbu5fr9nu6fix5tcojjo=-=\n"
97 : "Content-Type: application/octet-stream\n"
98 : "\n"
99 : "-----BEGIN PGP MESSAGE-----\n"
100 : "Version: GnuPG v2\n"
101 : "\n"
102 : "hH4D8pSp7hUsFUASAgMEg0w39E6d0TkFYxLbT6n3YcoKTT+Ur/c7Sn1ECyL7Rnuk\n"
103 : "cmPO0adt3JxueK7Oz5COlk32SECFODdF3cQuDhkGxzC6Sfc4SfisdILmNhaT/MeW\n"
104 : "8a+yE4skSK70absif4kw5XkvxXNxHeIHfAteP50jPJLSwEsBTEceb9cRMoP7s8w0\n"
105 : "lYyi+RWQ7UKlKKywtcRCL4ow2H7spjx+a+3FzNOAoy7K0/thhLVRk8z+iuPi0/4n\n"
106 : "Z2Ql60USLLUlfV2ZIpXdCd+5GjTJsnGhDos1pas5TZcOOAxO12Cg5TcqHISOaqa8\n"
107 : "6BqxcKCU3NypIynOKHj375KArSs0WsEH8HWHyBBHB+NYtNpnTAuHNKxM+JtNxf+U\n"
108 : "NfD2zptS6kyiHLw+4zjL5pEV7RHS2PBwWBDS6vhnyybNwckleya96U04iYiGRYGE\n"
109 : "lUUR6Fl8H6x04dItFH1/jJA6Ppcu4FoYou04HADWCqJXPTgztjiW1/9QoCeXl5lm\n"
110 : "CcOCcuw7lXp+qTejuns=\n"
111 : "=SsWX\n"
112 : "-----END PGP MESSAGE-----\n"
113 : "\n"
114 : "--=-=01-wbu5fr9nu6fix5tcojjo=-=--\n";
115 :
116 :
117 0 : class WKSPublishTest : public QGpgMETest
118 : {
119 : Q_OBJECT
120 :
121 : Q_SIGNALS:
122 : void asyncDone();
123 :
124 : private Q_SLOTS:
125 0 : void testUnsupported()
126 : {
127 : // First check if it is supported
128 0 : auto job = openpgp()->wksPublishJob();
129 : connect(job, &WKSPublishJob::result, this,
130 0 : [this] (Error err, QByteArray, QByteArray, QString, Error) {
131 0 : QVERIFY(err);
132 0 : Q_EMIT asyncDone();
133 0 : });
134 0 : job->startCheck ("testuser1@localhost");
135 0 : QSignalSpy spy (this, SIGNAL(asyncDone()));
136 0 : QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
137 : }
138 : #ifdef DO_ONLINE_TESTS
139 : private Q_SLOTS:
140 : #else
141 : private:
142 : #endif
143 : void testWSKPublishSupport()
144 : {
145 : // First check if it is supported
146 : auto job = openpgp()->wksPublishJob();
147 : connect(job, &WKSPublishJob::result, this,
148 : [this] (Error err, QByteArray, QByteArray, QString, Error) {
149 : if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.0.16") {
150 : std::cout << err;
151 : QVERIFY(err);
152 : } else {
153 : QVERIFY(!err);
154 : }
155 : Q_EMIT asyncDone();
156 : });
157 : job->startCheck ("testuser1@test.gnupg.org");
158 : QSignalSpy spy (this, SIGNAL(asyncDone()));
159 : QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
160 : }
161 :
162 : void testWKSPublishErrors() {
163 : if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.0.16") {
164 : /* Not supported */
165 : return;
166 : }
167 : auto job = openpgp()->wksPublishJob();
168 : connect(job, &WKSPublishJob::result, this,
169 : [this] (Error err, QByteArray, QByteArray, QString, Error) {
170 : QVERIFY(err);
171 : Q_EMIT asyncDone();
172 : });
173 : job->startCreate("AB874F24E98EBB8487EE7B170F8E3D97FE7011B7",
174 : QStringLiteral("Foo@bar.baz"));
175 : QSignalSpy spy (this, SIGNAL(asyncDone()));
176 : QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
177 : }
178 :
179 : void testWKSPublishCreate() {
180 : if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.0.16") {
181 : /* Not supported */
182 : return;
183 : }
184 : /* First generate a test key */
185 : const QString args = QStringLiteral("<GnupgKeyParms format=\"internal\">\n"
186 : "%no-protection\n"
187 : "%transient-key\n"
188 : "key-type: ECDSA\n"
189 : "key-curve: brainpoolP256r1\n"
190 : "key-usage: sign\n"
191 : "subkey-type: ECDH\n"
192 : "subkey-curve: brainpoolP256r1\n"
193 : "subkey-usage: encrypt\n"
194 : "name-email: %1\n"
195 : "name-real: Test User\n"
196 : "</GnupgKeyParms>").arg(TEST_ADDRESS);
197 :
198 : auto keygenjob = openpgp()->keyGenerationJob();
199 : QByteArray fpr;
200 : connect(keygenjob, &KeyGenerationJob::result, this,
201 : [this, &fpr](KeyGenerationResult result, QByteArray, QString, Error)
202 : {
203 : QVERIFY(!result.error());
204 : fpr = QByteArray(result.fingerprint());
205 : QVERIFY(!fpr.isEmpty());
206 : Q_EMIT asyncDone();
207 : });
208 : keygenjob->start(args);
209 : QSignalSpy spy (this, SIGNAL(asyncDone()));
210 : QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
211 :
212 : /* Then try to create a request. */
213 : auto job = openpgp()->wksPublishJob();
214 : connect(job, &WKSPublishJob::result, this,
215 : [this] (Error err, QByteArray out, QByteArray, QString, Error) {
216 : QVERIFY(!err);
217 : Q_EMIT asyncDone();
218 : const QString outstr = QString(out);
219 : QVERIFY(outstr.contains(
220 : QStringLiteral("-----BEGIN PGP PUBLIC KEY BLOCK-----")));
221 : QVERIFY(outstr.contains(
222 : QStringLiteral("Content-Type: application/pgp-keys")));
223 : QVERIFY(outstr.contains(
224 : QStringLiteral("From: " TEST_ADDRESS)));
225 : });
226 : job->startCreate(fpr.constData(), QLatin1String(TEST_ADDRESS));
227 : QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
228 : }
229 :
230 : void testWKSPublishReceive() {
231 : if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.0.16") {
232 : /* Not supported */
233 : return;
234 : }
235 : auto importjob = openpgp()->importJob();
236 : connect(importjob, &ImportJob::result, this,
237 : [this](ImportResult result, QString, Error)
238 : {
239 : QVERIFY(!result.error());
240 : QVERIFY(!result.imports().empty());
241 : QVERIFY(result.numSecretKeysImported());
242 : Q_EMIT asyncDone();
243 : });
244 : importjob->start(QByteArray(testSecKey));
245 : QSignalSpy spy (this, SIGNAL(asyncDone()));
246 : QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
247 :
248 : /* Get a response. */
249 : auto job = openpgp()->wksPublishJob();
250 : connect(job, &WKSPublishJob::result, this,
251 : [this] (Error err, QByteArray out, QByteArray, QString, Error) {
252 : QVERIFY(!err);
253 : Q_EMIT asyncDone();
254 : const QString outstr = QString(out);
255 : QVERIFY(outstr.contains(
256 : QStringLiteral("-----BEGIN PGP MESSAGE-----")));
257 : QVERIFY(outstr.contains(
258 : QStringLiteral("Content-Type: multipart/encrypted;")));
259 : QVERIFY(outstr.contains(
260 : QStringLiteral("From: " TEST_ADDRESS)));
261 : });
262 : job->startReceive(QByteArray(testResponse));
263 : QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
264 : }
265 :
266 : void initTestCase()
267 : {
268 : QGpgMETest::initTestCase();
269 : const QString gpgHome = qgetenv("GNUPGHOME");
270 : qputenv("GNUPGHOME", mDir.path().toUtf8());
271 : QVERIFY(mDir.isValid());
272 : QFile agentConf(mDir.path() + QStringLiteral("/gpg-agent.conf"));
273 : QVERIFY(agentConf.open(QIODevice::WriteOnly));
274 : agentConf.write("allow-loopback-pinentry");
275 : agentConf.close();
276 : }
277 : private:
278 : QTemporaryDir mDir;
279 : };
280 :
281 0 : QTEST_MAIN(WKSPublishTest)
282 :
283 : #include "t-wkspublish.moc"
|