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