qt: Support WKD lookup without implicit import
* lang/qt/src/Makefile.am (qgpgme_sources): Add qgpgmewkdlookupjob.cpp, wkdlookupresult.cpp. (qgpgme_headers): Add wkdlookupjob.h, wkdlookupresult.h. (camelcase_headers): Add WKDLookupJob, WKDLookupResult. (private_qgpgme_headers): Add qgpgmewkdlookupjob.h. (qgpgme_moc_sources): Add qgpgmewkdlookupjob.moc, wkdlookupjob.moc. * lang/qt/src/job.cpp: Define c'tor and d'tor of WKDLookupJob. * lang/qt/src/protocol.h (Protocol::wkdLookupJob): New. * lang/qt/src/protocol_p.h (Protocol::wkdLookupJob): New. * lang/qt/src/qgpgmewkdlookupjob.cpp, lang/qt/src/qgpgmewkdlookupjob.h, lang/qt/src/wkdlookupjob.h, lang/qt/src/wkdlookupresult.cpp, lang/qt/src/wkdlookupresult.h: New. * lang/qt/tests/Makefile.am (EXTRA_DIST): Add final.test. (the_tests): New. (TESTS): Remove all t-*. Add $(the_tests) and final.test. (moc_files): Add t-wkdlookup.moc. (t_wkdlookup_SOURCES): New. (noinst_PROGRAMS): Add t-wkdlookup. * lang/qt/tests/final.test: New. * lang/qt/tests/t-support.h (QTest::toString): New template specialization for std::string. * lang/qt/tests/t-wkdlookup.cpp: New. -- The new WKDLookupJob allows running a WKD lookup without implicit import of the retrieved key. This makes it possible to do WKD lookups similar to keyserver lookups (aka external keylistings). The new final.test pseudo test stops a dirmngr that may have been started by the tests. The toString() template specialization enables printing of the actual and expected values in case of failed QCOMPARE. GnuPG-bug-id: 5728
This commit is contained in:
parent
0e70a2313a
commit
ed7e7df2e1
@ -36,12 +36,12 @@ qgpgme_sources = \
|
||||
qgpgmerefreshkeysjob.cpp \
|
||||
qgpgmesecretkeyexportjob.cpp qgpgmesignencryptjob.cpp \
|
||||
qgpgmesignjob.cpp qgpgmesignkeyjob.cpp qgpgmeverifydetachedjob.cpp \
|
||||
qgpgmeverifyopaquejob.cpp threadedjobmixin.cpp \
|
||||
qgpgmeverifyopaquejob.cpp qgpgmewkdlookupjob.cpp threadedjobmixin.cpp \
|
||||
qgpgmekeyformailboxjob.cpp qgpgme_debug.cpp \
|
||||
qgpgmetofupolicyjob.cpp qgpgmequickjob.cpp \
|
||||
defaultkeygenerationjob.cpp qgpgmewkspublishjob.cpp \
|
||||
qgpgmegpgcardjob.cpp changeexpiryjob.cpp \
|
||||
dn.cpp cryptoconfig.cpp
|
||||
dn.cpp cryptoconfig.cpp wkdlookupresult.cpp
|
||||
|
||||
# If you add one here make sure that you also add one in camelcase
|
||||
qgpgme_headers= \
|
||||
@ -81,6 +81,8 @@ qgpgme_headers= \
|
||||
verifydetachedjob.h \
|
||||
defaultkeygenerationjob.h \
|
||||
tofupolicyjob.h \
|
||||
wkdlookupjob.h \
|
||||
wkdlookupresult.h \
|
||||
wkspublishjob.h \
|
||||
gpgcardjob.h \
|
||||
dn.h
|
||||
@ -121,6 +123,8 @@ camelcase_headers= \
|
||||
VerifyDetachedJob \
|
||||
KeyForMailboxJob \
|
||||
DefaultKeyGenerationJob \
|
||||
WKDLookupJob \
|
||||
WKDLookupResult \
|
||||
WKSPublishJob \
|
||||
TofuPolicyJob \
|
||||
GpgCardJob
|
||||
@ -152,6 +156,7 @@ private_qgpgme_headers = \
|
||||
qgpgmesignkeyjob.h \
|
||||
qgpgmeverifydetachedjob.h \
|
||||
qgpgmeverifyopaquejob.h \
|
||||
qgpgmewkdlookupjob.h \
|
||||
qgpgmekeyformailboxjob.h \
|
||||
qgpgmewkspublishjob.h \
|
||||
qgpgmetofupolicyjob.h \
|
||||
@ -201,6 +206,7 @@ qgpgme_moc_sources = \
|
||||
qgpgmesignkeyjob.moc \
|
||||
qgpgmeverifydetachedjob.moc \
|
||||
qgpgmeverifyopaquejob.moc \
|
||||
qgpgmewkdlookupjob.moc \
|
||||
qgpgmewkspublishjob.moc \
|
||||
tofupolicyjob.moc \
|
||||
qgpgmetofupolicyjob.moc \
|
||||
@ -211,6 +217,7 @@ qgpgme_moc_sources = \
|
||||
specialjob.moc \
|
||||
verifydetachedjob.moc \
|
||||
verifyopaquejob.moc \
|
||||
wkdlookupjob.moc \
|
||||
keyformailboxjob.moc \
|
||||
wkspublishjob.moc \
|
||||
qgpgmekeyformailboxjob.moc \
|
||||
|
@ -64,6 +64,7 @@
|
||||
#include "adduseridjob.h"
|
||||
#include "specialjob.h"
|
||||
#include "keyformailboxjob.h"
|
||||
#include "wkdlookupjob.h"
|
||||
#include "wkspublishjob.h"
|
||||
#include "tofupolicyjob.h"
|
||||
#include "threadedjobmixin.h"
|
||||
@ -161,6 +162,7 @@ make_job_subclass(RefreshKeysJob)
|
||||
make_job_subclass(AddUserIDJob)
|
||||
make_job_subclass(SpecialJob)
|
||||
make_job_subclass(KeyForMailboxJob)
|
||||
make_job_subclass(WKDLookupJob)
|
||||
make_job_subclass(WKSPublishJob)
|
||||
make_job_subclass(TofuPolicyJob)
|
||||
make_job_subclass(QuickJob)
|
||||
@ -194,6 +196,7 @@ make_job_subclass(GpgCardJob)
|
||||
#include "adduseridjob.moc"
|
||||
#include "specialjob.moc"
|
||||
#include "keyformailboxjob.moc"
|
||||
#include "wkdlookupjob.moc"
|
||||
#include "wkspublishjob.moc"
|
||||
#include "tofupolicyjob.moc"
|
||||
#include "quickjob.moc"
|
||||
|
@ -64,6 +64,7 @@ class ChangePasswdJob;
|
||||
class AddUserIDJob;
|
||||
class SpecialJob;
|
||||
class KeyForMailboxJob;
|
||||
class WKDLookupJob;
|
||||
class WKSPublishJob;
|
||||
class TofuPolicyJob;
|
||||
class QuickJob;
|
||||
@ -155,6 +156,9 @@ public:
|
||||
/** Find the best key to use for a mailbox. */
|
||||
virtual KeyForMailboxJob *keyForMailboxJob() const = 0;
|
||||
|
||||
/** This job looks up a key via WKD without importing it. */
|
||||
virtual WKDLookupJob *wkdLookupJob() const = 0;
|
||||
|
||||
/** A Job for interacting with gnupg's wks tools. */
|
||||
virtual WKSPublishJob *wksPublishJob() const = 0;
|
||||
|
||||
|
@ -58,6 +58,7 @@
|
||||
#include "qgpgmechangepasswdjob.h"
|
||||
#include "qgpgmeadduseridjob.h"
|
||||
#include "qgpgmekeyformailboxjob.h"
|
||||
#include "qgpgmewkdlookupjob.h"
|
||||
#include "qgpgmewkspublishjob.h"
|
||||
#include "qgpgmetofupolicyjob.h"
|
||||
#include "qgpgmequickjob.h"
|
||||
@ -392,6 +393,18 @@ public:
|
||||
return new QGpgME::QGpgMEKeyForMailboxJob(context);
|
||||
}
|
||||
|
||||
QGpgME::WKDLookupJob *wkdLookupJob() const Q_DECL_OVERRIDE
|
||||
{
|
||||
if (mProtocol != GpgME::OpenPGP) {
|
||||
return nullptr;
|
||||
}
|
||||
auto context = GpgME::Context::createForEngine(GpgME::AssuanEngine);
|
||||
if (!context) {
|
||||
return nullptr;
|
||||
}
|
||||
return new QGpgME::QGpgMEWKDLookupJob(context.release());
|
||||
}
|
||||
|
||||
QGpgME::WKSPublishJob *wksPublishJob() const Q_DECL_OVERRIDE
|
||||
{
|
||||
if (mProtocol != GpgME::OpenPGP) {
|
||||
|
182
lang/qt/src/qgpgmewkdlookupjob.cpp
Normal file
182
lang/qt/src/qgpgmewkdlookupjob.cpp
Normal file
@ -0,0 +1,182 @@
|
||||
/*
|
||||
qgpgmewkdlookupjob.cpp
|
||||
|
||||
This file is part of qgpgme, the Qt API binding for gpgme
|
||||
Copyright (c) 2021 g10 Code GmbH
|
||||
Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
|
||||
|
||||
QGpgME is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
QGpgME is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
In addition, as a special exception, the copyright holders give
|
||||
permission to link the code of this program with any edition of
|
||||
the Qt library by Trolltech AS, Norway (or with modified versions
|
||||
of Qt that use the same license as Qt), and distribute linked
|
||||
combinations including the two. You must obey the GNU General
|
||||
Public License in all respects for all of the code used other than
|
||||
Qt. If you modify this file, you may extend this exception to
|
||||
your version of the file, but you are not obligated to do so. If
|
||||
you do not wish to do so, delete this exception statement from
|
||||
your version.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "qgpgmewkdlookupjob.h"
|
||||
|
||||
#include "qgpgme_debug.h"
|
||||
|
||||
#include <gpgme++/context.h>
|
||||
#include <gpgme++/data.h>
|
||||
#include <gpgme++/defaultassuantransaction.h>
|
||||
|
||||
#include <gpg-error.h>
|
||||
|
||||
using namespace QGpgME;
|
||||
using namespace GpgME;
|
||||
|
||||
QGpgMEWKDLookupJob::QGpgMEWKDLookupJob(Context *context)
|
||||
: mixin_type{context}
|
||||
{
|
||||
lateInitialization();
|
||||
}
|
||||
|
||||
QGpgMEWKDLookupJob::~QGpgMEWKDLookupJob() = default;
|
||||
|
||||
static GpgME::Error startDirmngr(Context *assuanCtx)
|
||||
{
|
||||
Error err;
|
||||
|
||||
auto spawnCtx = std::unique_ptr<Context>{Context::createForEngine(SpawnEngine, &err)};
|
||||
if (err) {
|
||||
qCDebug(QGPGME_LOG) << "Error: Failed to get context for spawn engine (" << err.asString() << ")";
|
||||
}
|
||||
|
||||
const auto dirmngrProgram = GpgME::dirInfo("dirmngr-name");
|
||||
const auto homedir = GpgME::dirInfo("homedir");
|
||||
const char *argv[] = {
|
||||
dirmngrProgram,
|
||||
"--homedir",
|
||||
homedir,
|
||||
"--daemon",
|
||||
NULL
|
||||
};
|
||||
auto ignoreIO = Data{Data::null};
|
||||
if (!err) {
|
||||
qCDebug(QGPGME_LOG) << "Starting dirmngr ...";
|
||||
err = spawnCtx->spawnAsync(dirmngrProgram, argv,
|
||||
ignoreIO, ignoreIO, ignoreIO,
|
||||
Context::SpawnDetached);
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
// wait for socket to become available
|
||||
int cnt = 0;
|
||||
do {
|
||||
++cnt;
|
||||
qCDebug(QGPGME_LOG) << "Waiting for dirmngr to start ...";
|
||||
QThread::msleep(250 * cnt);
|
||||
err = assuanCtx->assuanTransact("GETINFO version");
|
||||
} while (err.code() == GPG_ERR_ASS_CONNECT_FAILED && cnt < 5);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static GpgME::Error setUpDirmngrAssuanConnection(Context *ctx)
|
||||
{
|
||||
Error err;
|
||||
|
||||
const std::string dirmngrSocket = GpgME::dirInfo("dirmngr-socket");
|
||||
err = ctx->setEngineFileName(dirmngrSocket.c_str());
|
||||
|
||||
if (!err) {
|
||||
err = ctx->setEngineHomeDirectory("");
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
// try do connect to dirmngr
|
||||
err = ctx->assuanTransact("GETINFO version");
|
||||
if (err.code() == GPG_ERR_ASS_CONNECT_FAILED) {
|
||||
err = startDirmngr(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static GpgME::Error run_wkd_get(Context *ctx, const QString &email)
|
||||
{
|
||||
Error err;
|
||||
|
||||
const auto cmd = std::string{"WKD_GET "} + email.toUtf8().toStdString();
|
||||
err = ctx->assuanTransact(cmd.c_str());
|
||||
if (err.code() == GPG_ERR_NO_NAME || err.code() == GPG_ERR_NO_DATA) {
|
||||
// ignore those benign errors; GPG_ERR_NO_NAME indicates that the domain
|
||||
// doesn't exist (on first request); GPG_ERR_NO_DATA indicates that
|
||||
// no key for email is available via WKD or that the domain doesn't
|
||||
// support WKD or that the domain doesn't exist (on subsequent requests
|
||||
// using dirmngr's internal cache)
|
||||
qCDebug(QGPGME_LOG) << "WKD_GET returned" << err.asString() << "; ignoring...";
|
||||
err = {};
|
||||
}
|
||||
if (err) {
|
||||
qCDebug(QGPGME_LOG) << "WKD_GET failed with" << err.asString();
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static QGpgMEWKDLookupJob::result_type lookup_keys(Context *ctx, const QString &email)
|
||||
{
|
||||
WKDLookupResult result;
|
||||
|
||||
Error err = setUpDirmngrAssuanConnection(ctx);
|
||||
|
||||
if (!err) {
|
||||
err = run_wkd_get(ctx, email);
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
const auto transaction = std::unique_ptr<DefaultAssuanTransaction>(dynamic_cast<DefaultAssuanTransaction*>(ctx->takeLastAssuanTransaction().release()));
|
||||
const auto source = transaction->firstStatusLine("SOURCE");
|
||||
const auto rawData = transaction->data();
|
||||
if (rawData.size() == 0) {
|
||||
qCDebug(QGPGME_LOG) << "No key found for" << email;
|
||||
result = WKDLookupResult{GpgME::Data::null, {}, {}};
|
||||
} else {
|
||||
qCDebug(QGPGME_LOG) << "Found key for" << email << "at" << source.c_str();
|
||||
result = WKDLookupResult{GpgME::Data{rawData.c_str(), rawData.size()}, source, {}};
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_tuple(err ? WKDLookupResult{err} : result, QString{}, Error{});
|
||||
}
|
||||
|
||||
Error QGpgMEWKDLookupJob::start(const QString &email)
|
||||
{
|
||||
run(std::bind(&lookup_keys, std::placeholders::_1, email));
|
||||
return Error();
|
||||
}
|
||||
|
||||
WKDLookupResult QGpgMEWKDLookupJob::exec(const QString &email)
|
||||
{
|
||||
const result_type r = lookup_keys(context(), email);
|
||||
resultHook(r);
|
||||
return std::get<0>(r);
|
||||
}
|
||||
|
||||
#include "qgpgmewkdlookupjob.moc"
|
70
lang/qt/src/qgpgmewkdlookupjob.h
Normal file
70
lang/qt/src/qgpgmewkdlookupjob.h
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
qgpgmewkdlookupjob.h
|
||||
|
||||
This file is part of qgpgme, the Qt API binding for gpgme
|
||||
Copyright (c) 2021 g10 Code GmbH
|
||||
Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
|
||||
|
||||
QGpgME is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
QGpgME is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
In addition, as a special exception, the copyright holders give
|
||||
permission to link the code of this program with any edition of
|
||||
the Qt library by Trolltech AS, Norway (or with modified versions
|
||||
of Qt that use the same license as Qt), and distribute linked
|
||||
combinations including the two. You must obey the GNU General
|
||||
Public License in all respects for all of the code used other than
|
||||
Qt. If you modify this file, you may extend this exception to
|
||||
your version of the file, but you are not obligated to do so. If
|
||||
you do not wish to do so, delete this exception statement from
|
||||
your version.
|
||||
*/
|
||||
|
||||
#ifndef __QGPGME_QGPGMEWKDLOOKUPJOB_H__
|
||||
#define __QGPGME_QGPGMEWKDLOOKUPJOB_H__
|
||||
|
||||
#include "threadedjobmixin.h"
|
||||
#include "wkdlookupjob.h"
|
||||
#include "wkdlookupresult.h"
|
||||
|
||||
namespace QGpgME
|
||||
{
|
||||
class WKDLookupResult;
|
||||
|
||||
class QGpgMEWKDLookupJob
|
||||
#ifdef Q_MOC_RUN
|
||||
: public WKDLookupJob
|
||||
#else
|
||||
: public _detail::ThreadedJobMixin<WKDLookupJob, std::tuple<WKDLookupResult, QString, GpgME::Error> >
|
||||
#endif
|
||||
{
|
||||
Q_OBJECT
|
||||
#ifdef Q_MOC_RUN
|
||||
public Q_SLOTS:
|
||||
void slotFinished();
|
||||
#endif
|
||||
public:
|
||||
explicit QGpgMEWKDLookupJob(GpgME::Context *context);
|
||||
~QGpgMEWKDLookupJob();
|
||||
|
||||
/* from WKDLookupJob */
|
||||
GpgME::Error start(const QString &email) Q_DECL_OVERRIDE;
|
||||
|
||||
/* from WKDLookupJob */
|
||||
WKDLookupResult exec(const QString &email) Q_DECL_OVERRIDE;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // __QGPGME_QGPGMEWKDLOOKUPJOB_H__
|
78
lang/qt/src/wkdlookupjob.h
Normal file
78
lang/qt/src/wkdlookupjob.h
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
wkdlookupjob.h
|
||||
|
||||
This file is part of qgpgme, the Qt API binding for gpgme
|
||||
Copyright (c) 2021 g10 Code GmbH
|
||||
Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
|
||||
|
||||
QGpgME is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
QGpgME is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
In addition, as a special exception, the copyright holders give
|
||||
permission to link the code of this program with any edition of
|
||||
the Qt library by Trolltech AS, Norway (or with modified versions
|
||||
of Qt that use the same license as Qt), and distribute linked
|
||||
combinations including the two. You must obey the GNU General
|
||||
Public License in all respects for all of the code used other than
|
||||
Qt. If you modify this file, you may extend this exception to
|
||||
your version of the file, but you are not obligated to do so. If
|
||||
you do not wish to do so, delete this exception statement from
|
||||
your version.
|
||||
*/
|
||||
|
||||
#ifndef __QGPGME_WKDLOOKUPJOB_H__
|
||||
#define __QGPGME_WKDLOOKUPJOB_H__
|
||||
|
||||
#include "job.h"
|
||||
#include "qgpgme_export.h"
|
||||
|
||||
class QString;
|
||||
|
||||
namespace GpgME
|
||||
{
|
||||
class Data;
|
||||
class Error;
|
||||
}
|
||||
|
||||
namespace QGpgME
|
||||
{
|
||||
|
||||
class WKDLookupResult;
|
||||
|
||||
class QGPGME_EXPORT WKDLookupJob : public Job
|
||||
{
|
||||
Q_OBJECT
|
||||
protected:
|
||||
explicit WKDLookupJob(QObject *parent);
|
||||
|
||||
public:
|
||||
~WKDLookupJob();
|
||||
|
||||
/**
|
||||
Starts a key lookup operation for the email address \a email via WKD.
|
||||
*/
|
||||
virtual GpgME::Error start(const QString &email) = 0;
|
||||
|
||||
/**
|
||||
Runs a key lookup operation for the email address \a email via WKD.
|
||||
*/
|
||||
virtual WKDLookupResult exec(const QString &email) = 0;
|
||||
|
||||
Q_SIGNALS:
|
||||
void result(const WKDLookupResult &result, const QString &auditLogAsHtml = {}, const GpgME::Error &auditLogError = {});
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // __QGPGME_WKDLOOKUPJOB_H__
|
111
lang/qt/src/wkdlookupresult.cpp
Normal file
111
lang/qt/src/wkdlookupresult.cpp
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
wkdlookupresult.cpp - wraps the result of a WKDLookupJob
|
||||
|
||||
This file is part of qgpgme, the Qt API binding for gpgme
|
||||
Copyright (c) 2021 g10 Code GmbH
|
||||
Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
|
||||
|
||||
QGpgME is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
QGpgME is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
In addition, as a special exception, the copyright holders give
|
||||
permission to link the code of this program with any edition of
|
||||
the Qt library by Trolltech AS, Norway (or with modified versions
|
||||
of Qt that use the same license as Qt), and distribute linked
|
||||
combinations including the two. You must obey the GNU General
|
||||
Public License in all respects for all of the code used other than
|
||||
Qt. If you modify this file, you may extend this exception to
|
||||
your version of the file, but you are not obligated to do so. If
|
||||
you do not wish to do so, delete this exception statement from
|
||||
your version.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "wkdlookupresult.h"
|
||||
|
||||
#include <gpgme++/data.h>
|
||||
|
||||
using namespace QGpgME;
|
||||
using namespace GpgME;
|
||||
|
||||
class WKDLookupResult::Private
|
||||
{
|
||||
public:
|
||||
GpgME::Data keyData;
|
||||
std::string source;
|
||||
};
|
||||
|
||||
WKDLookupResult::WKDLookupResult() = default;
|
||||
|
||||
WKDLookupResult::~WKDLookupResult() = default;
|
||||
|
||||
WKDLookupResult::WKDLookupResult(const Error &error)
|
||||
: Result{error}
|
||||
, d{}
|
||||
{
|
||||
}
|
||||
|
||||
WKDLookupResult::WKDLookupResult(const Data &keyData, const std::string &source, const Error &error)
|
||||
: Result{error}
|
||||
, d{new Private{keyData, source}}
|
||||
{
|
||||
}
|
||||
|
||||
WKDLookupResult::WKDLookupResult(const WKDLookupResult &other)
|
||||
: Result{other}
|
||||
{
|
||||
if (other.d) {
|
||||
d.reset(new Private{*other.d});
|
||||
}
|
||||
}
|
||||
|
||||
WKDLookupResult &WKDLookupResult::operator=(const WKDLookupResult &other)
|
||||
{
|
||||
auto tmp = other;
|
||||
swap(tmp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
WKDLookupResult::WKDLookupResult(WKDLookupResult &&other) = default;
|
||||
|
||||
WKDLookupResult &WKDLookupResult::operator=(WKDLookupResult &&other) = default;
|
||||
|
||||
void WKDLookupResult::swap(WKDLookupResult &other) noexcept
|
||||
{
|
||||
Result::swap(other);
|
||||
std::swap(this->d, other.d);
|
||||
}
|
||||
|
||||
bool WKDLookupResult::isNull() const
|
||||
{
|
||||
return !d && !bool(error());
|
||||
}
|
||||
|
||||
Data WKDLookupResult::keyData() const
|
||||
{
|
||||
return d ? d->keyData : Data{};
|
||||
}
|
||||
|
||||
std::string WKDLookupResult::source() const
|
||||
{
|
||||
return d ? d->source : std::string{};
|
||||
}
|
||||
|
||||
void QGpgME::swap(WKDLookupResult &a, WKDLookupResult &b)
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
83
lang/qt/src/wkdlookupresult.h
Normal file
83
lang/qt/src/wkdlookupresult.h
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
wkdlookupresult.h - wraps the result of a WKDLookupJob
|
||||
|
||||
This file is part of qgpgme, the Qt API binding for gpgme
|
||||
Copyright (c) 2021 g10 Code GmbH
|
||||
Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
|
||||
|
||||
QGpgME is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
QGpgME is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
In addition, as a special exception, the copyright holders give
|
||||
permission to link the code of this program with any edition of
|
||||
the Qt library by Trolltech AS, Norway (or with modified versions
|
||||
of Qt that use the same license as Qt), and distribute linked
|
||||
combinations including the two. You must obey the GNU General
|
||||
Public License in all respects for all of the code used other than
|
||||
Qt. If you modify this file, you may extend this exception to
|
||||
your version of the file, but you are not obligated to do so. If
|
||||
you do not wish to do so, delete this exception statement from
|
||||
your version.
|
||||
*/
|
||||
|
||||
#ifndef __QGPGME_WKDLOOKUPRESULT_H__
|
||||
#define __QGPGME_WKDLOOKUPRESULT_H__
|
||||
|
||||
#include "qgpgme_export.h"
|
||||
|
||||
#include <gpgme++/result.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace GpgME
|
||||
{
|
||||
class Data;
|
||||
class Error;
|
||||
}
|
||||
|
||||
namespace QGpgME
|
||||
{
|
||||
|
||||
class QGPGME_EXPORT WKDLookupResult : public GpgME::Result
|
||||
{
|
||||
public:
|
||||
WKDLookupResult();
|
||||
~WKDLookupResult();
|
||||
|
||||
explicit WKDLookupResult(const GpgME::Error &err);
|
||||
explicit WKDLookupResult(const GpgME::Data &keyData, const std::string &source, const GpgME::Error &err);
|
||||
|
||||
WKDLookupResult(const WKDLookupResult &other);
|
||||
WKDLookupResult &operator=(const WKDLookupResult &other);
|
||||
|
||||
WKDLookupResult(WKDLookupResult &&other);
|
||||
WKDLookupResult &operator=(WKDLookupResult &&other);
|
||||
|
||||
void swap(WKDLookupResult &other) noexcept;
|
||||
|
||||
bool isNull() const;
|
||||
|
||||
GpgME::Data keyData() const;
|
||||
std::string source() const;
|
||||
|
||||
private:
|
||||
class Private;
|
||||
std::unique_ptr<Private> d;
|
||||
};
|
||||
|
||||
QGPGME_EXPORT void swap(WKDLookupResult &a, WKDLookupResult &b);
|
||||
|
||||
}
|
||||
|
||||
#endif // __QGPGME_WKDLOOKUPRESULT_H__
|
@ -24,16 +24,19 @@ GPG = gpg
|
||||
GNUPGHOME=$(abs_builddir)
|
||||
TESTS_ENVIRONMENT = GNUPGHOME=$(GNUPGHOME)
|
||||
|
||||
EXTRA_DIST = initial.test
|
||||
EXTRA_DIST = initial.test final.test
|
||||
|
||||
TESTS = initial.test t-keylist t-keylocate t-ownertrust t-tofuinfo \
|
||||
t-encrypt t-verify t-various t-config t-remarks t-trustsignatures \
|
||||
t-changeexpiryjob
|
||||
the_tests = \
|
||||
t-keylist t-keylocate t-ownertrust t-tofuinfo \
|
||||
t-encrypt t-verify t-various t-config t-remarks t-trustsignatures \
|
||||
t-changeexpiryjob t-wkdlookup
|
||||
|
||||
TESTS = initial.test $(the_tests) final.test
|
||||
|
||||
moc_files = t-keylist.moc t-keylocate.moc t-ownertrust.moc t-tofuinfo.moc \
|
||||
t-encrypt.moc t-support.hmoc t-wkspublish.moc t-verify.moc \
|
||||
t-various.moc t-config.moc t-remarks.moc t-trustsignatures.moc \
|
||||
t-changeexpiryjob.moc
|
||||
t-changeexpiryjob.moc t-wkdlookup.moc
|
||||
|
||||
AM_LDFLAGS = -no-install
|
||||
|
||||
@ -61,6 +64,7 @@ t_config_SOURCES = t-config.cpp $(support_src)
|
||||
t_remarks_SOURCES = t-remarks.cpp $(support_src)
|
||||
t_trustsignatures_SOURCES = t-trustsignatures.cpp $(support_src)
|
||||
t_changeexpiryjob_SOURCES = t-changeexpiryjob.cpp $(support_src)
|
||||
t_wkdlookup_SOURCES = t-wkdlookup.cpp $(support_src)
|
||||
run_keyformailboxjob_SOURCES = run-keyformailboxjob.cpp
|
||||
|
||||
nodist_t_keylist_SOURCES = $(moc_files)
|
||||
@ -69,7 +73,7 @@ BUILT_SOURCES = $(moc_files) pubring-stamp
|
||||
|
||||
noinst_PROGRAMS = t-keylist t-keylocate t-ownertrust t-tofuinfo t-encrypt \
|
||||
run-keyformailboxjob t-wkspublish t-verify t-various t-config t-remarks \
|
||||
t-trustsignatures t-changeexpiryjob
|
||||
t-trustsignatures t-changeexpiryjob t-wkdlookup
|
||||
|
||||
CLEANFILES = secring.gpg pubring.gpg pubring.kbx trustdb.gpg dirmngr.conf \
|
||||
gpg-agent.conf pubring.kbx~ S.gpg-agent gpg.conf pubring.gpg~ \
|
||||
|
6
lang/qt/tests/final.test
Executable file
6
lang/qt/tests/final.test
Executable file
@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
# stop the dirmngr that may have been started
|
||||
gpgconf --kill dirmngr
|
||||
|
||||
exit 0
|
@ -34,9 +34,19 @@
|
||||
|
||||
#include "interfaces/passphraseprovider.h"
|
||||
#include <QObject>
|
||||
#include <QTest>
|
||||
|
||||
#include <gpg-error.h>
|
||||
|
||||
namespace QTest
|
||||
{
|
||||
template <>
|
||||
inline char *toString(const std::string &s)
|
||||
{
|
||||
return QTest::toString(s.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
namespace GpgME
|
||||
{
|
||||
class TestPassphraseProvider : public PassphraseProvider
|
||||
|
148
lang/qt/tests/t-wkdlookup.cpp
Normal file
148
lang/qt/tests/t-wkdlookup.cpp
Normal file
@ -0,0 +1,148 @@
|
||||
/* t-wkdlookup.cpp
|
||||
|
||||
This file is part of qgpgme, the Qt API binding for gpgme
|
||||
Copyright (c) 2021 g10 Code GmbH
|
||||
Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
|
||||
|
||||
QGpgME is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
QGpgME is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
In addition, as a special exception, the copyright holders give
|
||||
permission to link the code of this program with any edition of
|
||||
the Qt library by Trolltech AS, Norway (or with modified versions
|
||||
of Qt that use the same license as Qt), and distribute linked
|
||||
combinations including the two. You must obey the GNU General
|
||||
Public License in all respects for all of the code used other than
|
||||
Qt. If you modify this file, you may extend this exception to
|
||||
your version of the file, but you are not obligated to do so. If
|
||||
you do not wish to do so, delete this exception statement from
|
||||
your version.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "t-support.h"
|
||||
|
||||
#include "data.h"
|
||||
#include "engineinfo.h"
|
||||
#include "protocol.h"
|
||||
#include "wkdlookupjob.h"
|
||||
#include "wkdlookupresult.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QSignalSpy>
|
||||
#include <QTest>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace QGpgME;
|
||||
using namespace GpgME;
|
||||
|
||||
static const char *requiredVersion = "2.1.12";
|
||||
|
||||
namespace
|
||||
{
|
||||
bool keyHasUserIDWithMatchingEmailAddress(const Key &key, const QString &expectedEmailAddress)
|
||||
{
|
||||
const auto email = expectedEmailAddress.toLower();
|
||||
const auto userIds = key.userIDs();
|
||||
return std::any_of(
|
||||
std::begin(userIds), std::end(userIds),
|
||||
[email](const UserID &uid) {
|
||||
return email == QString::fromUtf8(uid.email()).toLower();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class WKDLookupTest : public QGpgMETest
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_SIGNALS:
|
||||
void asyncDone();
|
||||
|
||||
private Q_SLOTS:
|
||||
|
||||
#ifndef DO_ONLINE_TESTS
|
||||
void testWKDLookupAsync()
|
||||
{
|
||||
if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < requiredVersion) {
|
||||
QSKIP("dirmngr does not yet support WKD lookup");
|
||||
}
|
||||
const QString email = QLatin1String{"wk@gnupg.org"};
|
||||
|
||||
WKDLookupResult result;
|
||||
auto *job = openpgp()->wkdLookupJob();
|
||||
connect(job, &WKDLookupJob::result, job, [this, &result](const WKDLookupResult &result_, const QString &, const Error &)
|
||||
{
|
||||
result = result_;
|
||||
Q_EMIT asyncDone();
|
||||
});
|
||||
job->start(email);
|
||||
QSignalSpy spy (this, SIGNAL(asyncDone()));
|
||||
QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
|
||||
|
||||
QVERIFY(result.error().code() == GPG_ERR_NO_ERROR);
|
||||
QCOMPARE(result.source(), "https://openpgpkey.gnupg.org");
|
||||
const auto keys = result.keyData().toKeys(GpgME::OpenPGP);
|
||||
QVERIFY(keys.size() == 1);
|
||||
QVERIFY(keyHasUserIDWithMatchingEmailAddress(keys.front(), email));
|
||||
}
|
||||
|
||||
void testWKDLookupSync()
|
||||
{
|
||||
if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < requiredVersion) {
|
||||
QSKIP("dirmngr does not yet support WKD lookup");
|
||||
}
|
||||
const QString email = QLatin1String{"wk@gnupg.org"};
|
||||
|
||||
auto *job = openpgp()->wkdLookupJob();
|
||||
const auto result = job->exec(email);
|
||||
|
||||
QVERIFY(result.error().code() == GPG_ERR_NO_ERROR);
|
||||
QCOMPARE(result.source(), "https://openpgpkey.gnupg.org");
|
||||
const auto keys = result.keyData().toKeys(GpgME::OpenPGP);
|
||||
QVERIFY(keys.size() == 1);
|
||||
QVERIFY(keyHasUserIDWithMatchingEmailAddress(keys.front(), email));
|
||||
}
|
||||
|
||||
void testLookupWithNoResultAsync()
|
||||
{
|
||||
if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < requiredVersion) {
|
||||
QSKIP("dirmngr does not yet support WKD lookup");
|
||||
}
|
||||
const QString email = QLatin1String{"alfa@example.net"};
|
||||
|
||||
WKDLookupResult result;
|
||||
auto *job = openpgp()->wkdLookupJob();
|
||||
connect(job, &WKDLookupJob::result, job, [this, &result](const WKDLookupResult &result_, const QString &, const Error &)
|
||||
{
|
||||
result = result_;
|
||||
Q_EMIT asyncDone();
|
||||
});
|
||||
job->start(email);
|
||||
QSignalSpy spy (this, SIGNAL(asyncDone()));
|
||||
QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
|
||||
|
||||
QVERIFY(result.error().code() == GPG_ERR_NO_ERROR);
|
||||
QCOMPARE(result.source(), "");
|
||||
QVERIFY(result.keyData().isNull());
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
QTEST_MAIN(WKDLookupTest)
|
||||
|
||||
#include "t-wkdlookup.moc"
|
Loading…
Reference in New Issue
Block a user