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