aboutsummaryrefslogtreecommitdiffstats
path: root/lang
diff options
context:
space:
mode:
authorIngo Klöcker <[email protected]>2024-01-05 11:10:22 +0000
committerIngo Klöcker <[email protected]>2024-01-05 11:10:22 +0000
commitc631622484dc9c00a05e3c25c53ef263db83b381 (patch)
tree84d9986d50ea50d3ff66d175ea36da47e21761b0 /lang
parentcore: Tell gpg that we want to verify signed data (diff)
downloadgpgme-c631622484dc9c00a05e3c25c53ef263db83b381.tar.gz
gpgme-c631622484dc9c00a05e3c25c53ef263db83b381.zip
qt: Support verification of detached signatures directly from files
* lang/qt/src/Makefile.am: Add new files. * lang/qt/src/job.cpp (VerifyDetachedJob): Move definition of constructor and destructor and inclusion of the moc file to the corresponding .cpp file. * lang/qt/src/verifydetachedjob.cpp: New. * lang/qt/src/verifydetachedjob.h (VerifyDetachedJob): Add member functions setSignatureFile, signatureFile, setSignedFile, signedFile. * lang/qt/src/verifydetachedjob_p.h: New. * lang/qt/src/qgpgmeverifydetachedjob.cpp (class QGpgMEVerifyDetachedJobPrivate): New. (QGpgMEVerifyDetachedJob::QGpgMEVerifyDetachedJob): Instantiate private job class. (verify_from_filename): New. * lang/qt/tests/Makefile.am: Add new test program. * lang/qt/tests/run-verifydetachedjob.cpp: New. -- This makes it possible to tell gpg to read the input directly from the specified files bypassing GpgME's Data IO when verifying a detached signature. GnuPG-bug-id: 6550
Diffstat (limited to 'lang')
-rw-r--r--lang/qt/src/Makefile.am2
-rw-r--r--lang/qt/src/job.cpp3
-rw-r--r--lang/qt/src/qgpgmeverifydetachedjob.cpp78
-rw-r--r--lang/qt/src/verifydetachedjob.cpp74
-rw-r--r--lang/qt/src/verifydetachedjob.h25
-rw-r--r--lang/qt/src/verifydetachedjob_p.h50
-rw-r--r--lang/qt/tests/Makefile.am2
-rw-r--r--lang/qt/tests/run-verifydetachedjob.cpp121
8 files changed, 345 insertions, 10 deletions
diff --git a/lang/qt/src/Makefile.am b/lang/qt/src/Makefile.am
index 81e07ce6..b696dc66 100644
--- a/lang/qt/src/Makefile.am
+++ b/lang/qt/src/Makefile.am
@@ -69,6 +69,7 @@ qgpgme_sources = \
signjob.cpp \
dn.cpp cryptoconfig.cpp wkdlookupresult.cpp \
util.cpp \
+ verifydetachedjob.cpp \
verifyopaquejob.cpp \
wkdrefreshjob.cpp
@@ -233,6 +234,7 @@ private_qgpgme_headers = \
signjob_p.h \
threadedjobmixin.h \
util.h \
+ verifydetachedjob_p.h \
verifyopaquejob_p.h \
wkdrefreshjob_p.h
diff --git a/lang/qt/src/job.cpp b/lang/qt/src/job.cpp
index dbaba195..8150d9a3 100644
--- a/lang/qt/src/job.cpp
+++ b/lang/qt/src/job.cpp
@@ -45,7 +45,6 @@
#include "listallkeysjob.h"
#include "decryptjob.h"
#include "signkeyjob.h"
-#include "verifydetachedjob.h"
#include "keygenerationjob.h"
#include "importjob.h"
#include "importfromkeyserverjob.h"
@@ -161,7 +160,6 @@ make_job_subclass(KeyListJob)
make_job_subclass(ListAllKeysJob)
make_job_subclass(DecryptJob)
make_job_subclass(SignKeyJob)
-make_job_subclass(VerifyDetachedJob)
make_job_subclass(KeyGenerationJob)
make_job_subclass(AbstractImportJob)
make_job_subclass_ext(ImportJob, AbstractImportJob)
@@ -194,7 +192,6 @@ make_job_subclass(SetPrimaryUserIDJob)
#include "listallkeysjob.moc"
#include "decryptjob.moc"
#include "signkeyjob.moc"
-#include "verifydetachedjob.moc"
#include "keygenerationjob.moc"
#include "abstractimportjob.moc"
#include "importjob.moc"
diff --git a/lang/qt/src/qgpgmeverifydetachedjob.cpp b/lang/qt/src/qgpgmeverifydetachedjob.cpp
index 52d4329b..57b3c368 100644
--- a/lang/qt/src/qgpgmeverifydetachedjob.cpp
+++ b/lang/qt/src/qgpgmeverifydetachedjob.cpp
@@ -39,10 +39,14 @@
#include "qgpgmeverifydetachedjob.h"
#include "dataprovider.h"
+#include "util.h"
+#include "verifydetachedjob_p.h"
-#include "context.h"
-#include "verificationresult.h"
-#include "data.h"
+#include <QFile>
+
+#include <context.h>
+#include <data.h>
+#include <verificationresult.h>
#include <cassert>
@@ -50,9 +54,36 @@
using namespace QGpgME;
using namespace GpgME;
+namespace
+{
+
+class QGpgMEVerifyDetachedJobPrivate : public VerifyDetachedJobPrivate
+{
+ QGpgMEVerifyDetachedJob *q = nullptr;
+
+public:
+ QGpgMEVerifyDetachedJobPrivate(QGpgMEVerifyDetachedJob *qq)
+ : q{qq}
+ {
+ }
+
+ ~QGpgMEVerifyDetachedJobPrivate() override = default;
+
+private:
+ GpgME::Error startIt() override;
+
+ void startNow() override
+ {
+ q->run();
+ }
+};
+
+}
+
QGpgMEVerifyDetachedJob::QGpgMEVerifyDetachedJob(Context *context)
: mixin_type(context)
{
+ setJobPrivate(this, std::unique_ptr<QGpgMEVerifyDetachedJobPrivate>{new QGpgMEVerifyDetachedJobPrivate{this}});
lateInitialization();
}
@@ -98,6 +129,31 @@ static QGpgMEVerifyDetachedJob::result_type verify_detached_qba(Context *ctx, co
}
+static QGpgMEVerifyDetachedJob::result_type verify_from_filename(Context *ctx,
+ const QString &signatureFilePath,
+ const QString &signedFilePath)
+{
+ Data signatureData;
+#ifdef Q_OS_WIN
+ signatureData.setFileName(signatureFilePath().toUtf8().constData());
+#else
+ signatureData.setFileName(QFile::encodeName(signatureFilePath).constData());
+#endif
+
+ Data signedData;
+#ifdef Q_OS_WIN
+ signedData.setFileName(signedFilePath().toUtf8().constData());
+#else
+ signedData.setFileName(QFile::encodeName(signedFilePath).constData());
+#endif
+
+ const auto verificationResult = ctx->verifyDetachedSignature(signatureData, signedData);
+
+ Error ae;
+ const QString log = _detail::audit_log_as_html(ctx, ae);
+ return std::make_tuple(verificationResult, log, ae);
+}
+
Error QGpgMEVerifyDetachedJob::start(const QByteArray &signature, const QByteArray &signedData)
{
run(std::bind(&verify_detached_qba, std::placeholders::_1, signature, signedData));
@@ -117,10 +173,22 @@ GpgME::VerificationResult QGpgME::QGpgMEVerifyDetachedJob::exec(const QByteArray
return mResult;
}
-//PENDING(marc) implement showErrorDialog()
-
void QGpgME::QGpgMEVerifyDetachedJob::resultHook(const result_type &tuple)
{
mResult = std::get<0>(tuple);
}
+
+GpgME::Error QGpgMEVerifyDetachedJobPrivate::startIt()
+{
+ if (m_signatureFilePath.isEmpty() || m_signedFilePath.isEmpty()) {
+ return Error::fromCode(GPG_ERR_INV_VALUE);
+ }
+
+ q->run([=](Context *ctx) {
+ return verify_from_filename(ctx, m_signatureFilePath, m_signedFilePath);
+ });
+
+ return {};
+}
+
#include "qgpgmeverifydetachedjob.moc"
diff --git a/lang/qt/src/verifydetachedjob.cpp b/lang/qt/src/verifydetachedjob.cpp
new file mode 100644
index 00000000..11e630c1
--- /dev/null
+++ b/lang/qt/src/verifydetachedjob.cpp
@@ -0,0 +1,74 @@
+/*
+ verifydetachedjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2024 g10 Code GmbH
+ Software engineering by Ingo Klöcker <[email protected]>
+
+ 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 "verifydetachedjob.h"
+#include "verifydetachedjob_p.h"
+
+using namespace QGpgME;
+
+VerifyDetachedJob::VerifyDetachedJob(QObject *parent)
+ : Job{parent}
+{
+}
+
+VerifyDetachedJob::~VerifyDetachedJob() = default;
+
+void VerifyDetachedJob::setSignatureFile(const QString &path)
+{
+ auto d = jobPrivate<VerifyDetachedJobPrivate>(this);
+ d->m_signatureFilePath = path;
+}
+
+QString VerifyDetachedJob::signatureFile() const
+{
+ auto d = jobPrivate<VerifyDetachedJobPrivate>(this);
+ return d->m_signatureFilePath;
+}
+
+void VerifyDetachedJob::setSignedFile(const QString &path)
+{
+ auto d = jobPrivate<VerifyDetachedJobPrivate>(this);
+ d->m_signedFilePath = path;
+}
+
+QString VerifyDetachedJob::signedFile() const
+{
+ auto d = jobPrivate<VerifyDetachedJobPrivate>(this);
+ return d->m_signedFilePath;
+}
+
+#include "verifydetachedjob.moc"
diff --git a/lang/qt/src/verifydetachedjob.h b/lang/qt/src/verifydetachedjob.h
index 12fdfbb0..c8c516bf 100644
--- a/lang/qt/src/verifydetachedjob.h
+++ b/lang/qt/src/verifydetachedjob.h
@@ -36,7 +36,6 @@
#define __KLEO_VERIFYDETACHEDJOB_H__
#include "job.h"
-#include "qgpgme_export.h"
#include <memory>
@@ -62,6 +61,12 @@ namespace QGpgME
VerifyDetachedJob instance will have scheduled it's own
destruction with a call to QObject::deleteLater().
+ Alternatively, the job can be started with startIt() after setting
+ the input files. If the job is started this way then the backend reads the
+ input directly from the specified input files. This direct IO mode is
+ currently only supported for OpenPGP. Note that startIt() does not schedule
+ the job's destruction if starting the job failed.
+
After result() is emitted, the VerifyDetachedJob will schedule
it's own destruction by calling QObject::deleteLater().
*/
@@ -71,7 +76,23 @@ class QGPGME_EXPORT VerifyDetachedJob : public Job
protected:
explicit VerifyDetachedJob(QObject *parent);
public:
- ~VerifyDetachedJob();
+ ~VerifyDetachedJob() override;
+
+ /**
+ * Sets the path of the file containing the signature to verify.
+ *
+ * Used if the job is started with startIt().
+ */
+ void setSignatureFile(const QString &path);
+ QString signatureFile() const;
+
+ /**
+ * Sets the path of the file containing the signed data to verify.
+ *
+ * Used if the job is started with startIt().
+ */
+ void setSignedFile(const QString &path);
+ QString signedFile() const;
/**
Starts the verification operation. \a signature contains the
diff --git a/lang/qt/src/verifydetachedjob_p.h b/lang/qt/src/verifydetachedjob_p.h
new file mode 100644
index 00000000..1fedc8fb
--- /dev/null
+++ b/lang/qt/src/verifydetachedjob_p.h
@@ -0,0 +1,50 @@
+/*
+ verifydetachedjob_p.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2024 g10 Code GmbH
+ Software engineering by Ingo Klöcker <[email protected]>
+
+ 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_VERIFYDETACHEDJOB_P_H__
+#define __QGPGME_VERIFYDETACHEDJOB_P_H__
+
+#include "job_p.h"
+
+namespace QGpgME
+{
+
+struct VerifyDetachedJobPrivate : public JobPrivate
+{
+ QString m_signatureFilePath;
+ QString m_signedFilePath;
+};
+
+}
+
+#endif // __QGPGME_VERIFYDETACHEDJOB_P_H__
diff --git a/lang/qt/tests/Makefile.am b/lang/qt/tests/Makefile.am
index e3dec517..3e579303 100644
--- a/lang/qt/tests/Makefile.am
+++ b/lang/qt/tests/Makefile.am
@@ -100,6 +100,7 @@ run_receivekeysjob_SOURCES = run-receivekeysjob.cpp
run_refreshkeysjob_SOURCES = run-refreshkeysjob.cpp
run_signarchivejob_SOURCES = run-signarchivejob.cpp
run_signjob_SOURCES = run-signjob.cpp
+run_verifydetachedjob_SOURCES = run-verifydetachedjob.cpp
run_verifyopaquejob_SOURCES = run-verifyopaquejob.cpp
run_wkdrefreshjob_SOURCES = run-wkdrefreshjob.cpp
@@ -121,6 +122,7 @@ noinst_PROGRAMS = \
run-importjob run-exportjob run-receivekeysjob run-refreshkeysjob \
run-signarchivejob \
run-signjob \
+ run-verifydetachedjob \
run-verifyopaquejob \
run-wkdrefreshjob
diff --git a/lang/qt/tests/run-verifydetachedjob.cpp b/lang/qt/tests/run-verifydetachedjob.cpp
new file mode 100644
index 00000000..6ee21109
--- /dev/null
+++ b/lang/qt/tests/run-verifydetachedjob.cpp
@@ -0,0 +1,121 @@
+/*
+ run-verifydetachedjob.cpp
+
+ This file is part of QGpgME's test suite.
+ Copyright (c) 2024 by g10 Code GmbH
+ Software engineering by Ingo Klöcker <[email protected]>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ 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 <protocol.h>
+#include <verifydetachedjob.h>
+
+#include <QCommandLineParser>
+#include <QCoreApplication>
+#include <QDebug>
+#include <QFile>
+
+#include <context.h>
+#include <verificationresult.h>
+
+#include <iostream>
+
+using namespace GpgME;
+
+std::ostream &operator<<(std::ostream &os, const QString &s)
+{
+ return os << s.toLocal8Bit().constData();
+}
+
+struct CommandLineOptions {
+ QString signatureFile;
+ QString signedFile;
+};
+
+CommandLineOptions parseCommandLine(const QStringList &arguments)
+{
+ CommandLineOptions options;
+
+ QCommandLineParser parser;
+ parser.setApplicationDescription("Test program for VerifyDetachedJob");
+ parser.addHelpOption();
+ parser.addPositionalArgument("signature", "Detached SIGNATURE to verify", "SIGNATURE");
+ parser.addPositionalArgument("signed file", "FILE containing the signed data", "FILE");
+
+ parser.process(arguments);
+
+ const auto args = parser.positionalArguments();
+ if (args.size() != 2) {
+ parser.showHelp(1);
+ }
+
+ options.signatureFile = args[0];
+ options.signedFile = args[1];
+
+ return options;
+}
+
+int main(int argc, char **argv)
+{
+ GpgME::initializeLibrary();
+
+ QCoreApplication app{argc, argv};
+ app.setApplicationName("run-verifydetachedjob");
+
+ const auto options = parseCommandLine(app.arguments());
+
+ auto job = QGpgME::openpgp()->verifyDetachedJob();
+ if (!job) {
+ std::cerr << "Error: Could not create job" << std::endl;
+ return 1;
+ }
+ QObject::connect(job,
+ &QGpgME::VerifyDetachedJob::result,
+ &app,
+ [](const GpgME::VerificationResult &verificationResult,
+ const QString &auditLog,
+ const GpgME::Error &) {
+ std::cerr << "Diagnostics: " << auditLog << std::endl;
+ std::cerr << "Verification Result: " << verificationResult << std::endl;
+ qApp->quit();
+ });
+
+ std::shared_ptr<QFile> input;
+ GpgME::Error err;
+ job->setSignatureFile(options.signatureFile);
+ job->setSignedFile(options.signedFile);
+ err = job->startIt();
+ if (err) {
+ std::cerr << "Error: Starting the job failed: " << err.asString() << std::endl;
+ return 1;
+ }
+
+ return app.exec();
+}