Page MenuHome GnuPG

No OneTemporary

diff --git a/src/commands/changeroottrustcommand.cpp b/src/commands/changeroottrustcommand.cpp
index b57c21310..fa4fffd0f 100644
--- a/src/commands/changeroottrustcommand.cpp
+++ b/src/commands/changeroottrustcommand.cpp
@@ -1,390 +1,340 @@
/* -*- mode: c++; c-basic-offset:4 -*-
commands/changeroottrustcommand.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <config-kleopatra.h>
#include "changeroottrustcommand.h"
#include "command_p.h"
#include <Libkleo/CryptoConfig>
#include <Libkleo/Dn>
#include <Libkleo/GnuPG>
#include <Libkleo/KeyCache>
#include "kleopatra_debug.h"
#include <KLocalizedString>
#include <QSaveFile>
#include <QByteArray>
#include <QDir>
#include <QFile>
#include <QMutex>
#include <QMutexLocker>
#include <QProcess>
#include <QString>
#include <QStringList>
#include <QThread>
#include <gpgme++/key.h>
using namespace Kleo;
using namespace Kleo::Commands;
using namespace GpgME;
class ChangeRootTrustCommand::Private : public QThread, public Command::Private
{
Q_OBJECT
private:
friend class ::Kleo::Commands::ChangeRootTrustCommand;
ChangeRootTrustCommand *q_func() const
{
return static_cast<ChangeRootTrustCommand *>(q);
}
public:
- explicit Private(ChangeRootTrustCommand *qq, KeyListController *c)
+ explicit Private(ChangeRootTrustCommand *qq, GpgME::Key::OwnerTrust trust_, KeyListController *c)
: QThread()
, Command::Private(qq, c)
, mutex()
- , trust(Key::Ultimate)
+ , trust(trust_)
, trustListFile(QDir(gnupgHomeDirectory()).absoluteFilePath(QStringLiteral("trustlist.txt")))
, canceled(false)
{
}
private:
void init()
{
q->setWarnWhenRunningAtShutdown(false);
connect(this, &QThread::finished, this, &ChangeRootTrustCommand::Private::slotOperationFinished);
}
void run() override;
private:
void slotOperationFinished()
{
KeyCache::mutableInstance()->enableFileSystemWatcher(true);
if (errorText.isEmpty()) {
KeyCache::mutableInstance()->reload(GpgME::CMS);
} else
error(i18n("Failed to update the trust database:\n"
"%1",
errorText),
i18n("Root Trust Update Failed"));
Command::Private::finished();
}
private:
mutable QMutex mutex;
Key::OwnerTrust trust;
QString trustListFile;
QString gpgConfPath;
QString errorText;
volatile bool canceled;
};
ChangeRootTrustCommand::Private *ChangeRootTrustCommand::d_func()
{
return static_cast<Private *>(d.get());
}
const ChangeRootTrustCommand::Private *ChangeRootTrustCommand::d_func() const
{
return static_cast<const Private *>(d.get());
}
#define q q_func()
#define d d_func()
-ChangeRootTrustCommand::ChangeRootTrustCommand(KeyListController *p)
- : Command(new Private(this, p))
+ChangeRootTrustCommand::ChangeRootTrustCommand(GpgME::Key::OwnerTrust trust, QAbstractItemView *v, KeyListController *p)
+ : Command(v, new Private(this, trust, p))
{
d->init();
}
-ChangeRootTrustCommand::ChangeRootTrustCommand(QAbstractItemView *v, KeyListController *p)
- : Command(v, new Private(this, p))
-{
- d->init();
-}
-
-ChangeRootTrustCommand::ChangeRootTrustCommand(const GpgME::Key &key, KeyListController *p)
- : Command(new Private(this, p))
-{
- Q_ASSERT(!key.isNull());
- d->init();
- setKey(key);
-}
-
-ChangeRootTrustCommand::ChangeRootTrustCommand(const GpgME::Key &key, QAbstractItemView *v, KeyListController *p)
- : Command(v, new Private(this, p))
-{
- Q_ASSERT(!key.isNull());
- d->init();
- setKey(key);
-}
-
-ChangeRootTrustCommand::~ChangeRootTrustCommand()
-{
-}
-
-void ChangeRootTrustCommand::setTrust(Key::OwnerTrust trust)
-{
- Q_ASSERT(!d->isRunning());
- const QMutexLocker locker(&d->mutex);
- d->trust = trust;
-}
-
-Key::OwnerTrust ChangeRootTrustCommand::trust() const
-{
- const QMutexLocker locker(&d->mutex);
- return d->trust;
-}
-
-void ChangeRootTrustCommand::setTrustListFile(const QString &trustListFile)
-{
- Q_ASSERT(!d->isRunning());
- const QMutexLocker locker(&d->mutex);
- d->trustListFile = trustListFile;
-}
-
-QString ChangeRootTrustCommand::trustListFile() const
-{
- const QMutexLocker locker(&d->mutex);
- return d->trustListFile;
-}
+ChangeRootTrustCommand::~ChangeRootTrustCommand() = default;
void ChangeRootTrustCommand::doStart()
{
if (getCryptoConfigBoolValue("gpg-agent", "no-allow-mark-trusted")) {
d->error(i18nc("@info", "You are not allowed to mark certificates as trusted or not trusted."));
d->Command::Private::finished();
return;
}
const std::vector<Key> keys = d->keys();
Key key;
if (keys.size() == 1) {
key = keys.front();
} else {
qCWarning(KLEOPATRA_LOG) << "can only work with one certificate at a time";
}
if (key.isNull()) {
d->Command::Private::finished();
return;
}
d->gpgConfPath = gpgConfPath();
KeyCache::mutableInstance()->enableFileSystemWatcher(false);
d->start();
}
void ChangeRootTrustCommand::doCancel()
{
const QMutexLocker locker(&d->mutex);
d->canceled = true;
}
static QString change_trust_file(const QString &trustListFile, const QString &fingerprint, const DN &dn, Key::OwnerTrust trust);
static QString run_gpgconf_reload_gpg_agent(const QString &gpgConfPath);
void ChangeRootTrustCommand::Private::run()
{
QMutexLocker locker(&mutex);
const auto key = keys().front();
const QString fpr = QString::fromLatin1(key.primaryFingerprint());
const auto dn = DN(key.userID(0).id());
const Key::OwnerTrust trust = this->trust;
const QString trustListFile = this->trustListFile;
const QString gpgConfPath = this->gpgConfPath;
locker.unlock();
QString err = change_trust_file(trustListFile, fpr, dn, trust);
if (err.isEmpty()) {
err = run_gpgconf_reload_gpg_agent(gpgConfPath);
}
locker.relock();
errorText = err;
}
static QString add_colons(const QString &fpr)
{
QString result;
result.reserve(fpr.size() / 2 * 3 + 1);
bool needColon = false;
for (QChar ch : fpr) {
result += ch;
if (needColon) {
result += QLatin1Char(':');
}
needColon = !needColon;
}
if (result.endsWith(QLatin1Char(':'))) {
result.chop(1);
}
return result;
}
namespace
{
// fix stupid default-finalize behaviour...
class KFixedSaveFile : public QSaveFile
{
public:
explicit KFixedSaveFile(const QString &fileName)
: QSaveFile(fileName)
{
}
~KFixedSaveFile() override
{
cancelWriting();
}
};
}
// static
QString change_trust_file(const QString &trustListFile, const QString &key, const DN &dn, Key::OwnerTrust trust)
{
QList<QByteArray> trustListFileContents;
if (QFile::exists(trustListFile)) { // non-existence is not fatal...
if (QFile in(trustListFile); in.open(QIODevice::ReadOnly)) {
trustListFileContents = in.readAll().split('\n');
// remove last empty line to avoid adding more empty lines when we write the lines
if (!trustListFileContents.empty() && trustListFileContents.back().isEmpty()) {
trustListFileContents.pop_back();
}
} else { // ...but failure to open an existing file _is_
return i18n("Cannot open existing file \"%1\" for reading: %2", trustListFile, in.errorString());
}
// the file is now closed, so KSaveFile doesn't clobber the original
} else {
// the default contents of the trustlist.txt file (see the headerblurb variable in trustlist.c of gnupg);
// we add an additional comment about the "include-default" statement
trustListFileContents = {
"# This is the list of trusted keys. Comment lines, like this one, as",
"# well as empty lines are ignored. Lines have a length limit but this",
"# is not a serious limitation as the format of the entries is fixed and",
"# checked by gpg-agent. A non-comment line starts with optional white",
"# space, followed by the SHA-1 fingerpint in hex, followed by a flag",
"# which may be one of 'P', 'S' or '*' and optionally followed by a list of",
"# other flags. The fingerprint may be prefixed with a '!' to mark the",
"# key as not trusted. You should give the gpg-agent a HUP or run the",
"# command \"gpgconf --reload gpg-agent\" after changing this file.",
"# Additionally to this file, gpg-agent will read the default trust list file",
"# if the statement \"include-default\" is used below.",
"",
"",
"# Include the default trust list",
"include-default",
"",
};
}
KFixedSaveFile out(trustListFile);
if (!out.open(QIODevice::WriteOnly))
return i18n("Cannot open file \"%1\" for reading and writing: %2", out.fileName() /*sic!*/, out.errorString());
if (!out.setPermissions(QFile::ReadOwner | QFile::WriteOwner))
return i18n("Cannot set restrictive permissions on file %1: %2", out.fileName() /*sic!*/, out.errorString());
const QString keyColon = add_colons(key);
qCDebug(KLEOPATRA_LOG) << qPrintable(key) << " -> " << qPrintable(keyColon);
// ( 1) ( 2 ) ( 3 )( 4)
static const char16_t pattern[] = uR"(\s*(!?)\s*([a-fA-F0-9]{40}|(?:[a-fA-F0-9]{2}:){19}[a-fA-F0-9]{2})\s*([SsPp*])(.*))";
static const QRegularExpression rx(QRegularExpression::anchoredPattern(pattern));
bool found = false;
for (const QByteArray &rawLine : std::as_const(trustListFileContents)) {
const QString line = QString::fromLatin1(rawLine.data(), rawLine.size());
const QRegularExpressionMatch match = rx.match(line);
if (!match.hasMatch()) {
qCDebug(KLEOPATRA_LOG) << "line \"" << rawLine.data() << "\" does not match";
out.write(rawLine + '\n');
continue;
}
const QString cap2 = match.captured(2);
if (cap2 != key && cap2 != keyColon) {
qCDebug(KLEOPATRA_LOG) << qPrintable(key) << " != " << qPrintable(cap2) << " != " << qPrintable(keyColon);
out.write(rawLine + '\n');
continue;
}
found = true;
const bool disabled = match.capturedView(1) == QLatin1Char('!');
const QByteArray flags = match.captured(3).toLatin1();
const QByteArray rests = match.captured(4).toLatin1();
if (trust == Key::Ultimate)
if (!disabled) { // unchanged
out.write(rawLine + '\n');
} else {
out.write(keyColon.toLatin1() + ' ' + flags + rests + '\n');
}
else if (trust == Key::Never) {
if (disabled) { // unchanged
out.write(rawLine + '\n');
} else {
out.write('!' + keyColon.toLatin1() + ' ' + flags + rests + '\n');
}
}
// else: trust == Key::Unknown
// -> don't write - ie.erase
}
if (!found) { // add
out.write("\n");
// write comment lines with DN attributes
std::for_each(dn.begin(), dn.end(), [&out](const auto &attr) {
out.write("# " + attr.name().toUtf8() + "=" + attr.value().toUtf8() + '\n');
});
if (trust == Key::Ultimate) {
out.write(keyColon.toLatin1() + " S relax\n");
} else if (trust == Key::Never) {
out.write('!' + keyColon.toLatin1() + " S relax\n");
}
}
if (!out.commit())
return i18n("Failed to move file %1 to its final destination, %2: %3", out.fileName(), trustListFile, out.errorString());
return QString();
}
// static
QString run_gpgconf_reload_gpg_agent(const QString &gpgConfPath)
{
if (gpgConfPath.isEmpty()) {
return i18n("Could not find gpgconf executable");
}
QProcess p;
p.start(gpgConfPath, QStringList() << QStringLiteral("--reload") << QStringLiteral("gpg-agent"));
qCDebug(KLEOPATRA_LOG) << "starting " << qPrintable(gpgConfPath) << " --reload gpg-agent";
p.waitForFinished(-1);
qCDebug(KLEOPATRA_LOG) << "done";
if (p.error() == QProcess::UnknownError) {
return QString();
} else {
return i18n("\"gpgconf --reload gpg-agent\" failed: %1", p.errorString());
}
}
#undef q_func
#undef d_func
#include "changeroottrustcommand.moc"
#include "moc_changeroottrustcommand.cpp"
diff --git a/src/commands/changeroottrustcommand.h b/src/commands/changeroottrustcommand.h
index 37e9080b5..69eac5c04 100644
--- a/src/commands/changeroottrustcommand.h
+++ b/src/commands/changeroottrustcommand.h
@@ -1,113 +1,74 @@
/* -*- mode: c++; c-basic-offset:4 -*-
commands/changeroottrustcommand.h
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include <commands/command.h>
#include <gpgme++/key.h>
namespace Kleo
{
namespace Commands
{
class ChangeRootTrustCommand : public Command
{
Q_OBJECT
+protected:
+ ChangeRootTrustCommand(GpgME::Key::OwnerTrust trust, QAbstractItemView *view, KeyListController *parent);
+
public:
- explicit ChangeRootTrustCommand(KeyListController *parent);
- explicit ChangeRootTrustCommand(QAbstractItemView *view, KeyListController *parent);
- explicit ChangeRootTrustCommand(const GpgME::Key &key, KeyListController *parent);
- explicit ChangeRootTrustCommand(const GpgME::Key &key, QAbstractItemView *view, KeyListController *parent);
~ChangeRootTrustCommand() override;
- void setTrust(GpgME::Key::OwnerTrust trust);
- GpgME::Key::OwnerTrust trust() const;
-
- void setTrustListFile(const QString &file);
- QString trustListFile() const;
-
/* reimp */ static Restrictions restrictions()
{
return OnlyOneKey | MustBeCMS | MustBeRoot;
}
private:
void doStart() override;
void doCancel() override;
private:
class Private;
inline Private *d_func();
inline const Private *d_func() const;
};
class TrustRootCommand : public ChangeRootTrustCommand
{
public:
- explicit TrustRootCommand(KeyListController *parent)
- : ChangeRootTrustCommand(parent)
- {
- setTrust(GpgME::Key::Ultimate);
- }
- explicit TrustRootCommand(QAbstractItemView *view, KeyListController *parent)
- : ChangeRootTrustCommand(view, parent)
- {
- setTrust(GpgME::Key::Ultimate);
- }
- explicit TrustRootCommand(const GpgME::Key &key, KeyListController *parent)
- : ChangeRootTrustCommand(key, parent)
+ TrustRootCommand(QAbstractItemView *view, KeyListController *parent)
+ : ChangeRootTrustCommand(GpgME::Key::Ultimate, view, parent)
{
- setTrust(GpgME::Key::Ultimate);
- }
- explicit TrustRootCommand(const GpgME::Key &key, QAbstractItemView *view, KeyListController *parent)
- : ChangeRootTrustCommand(key, view, parent)
- {
- setTrust(GpgME::Key::Ultimate);
}
/* reimp */ static Restrictions restrictions()
{
return ChangeRootTrustCommand::restrictions() | MustBeUntrustedRoot;
}
};
class DistrustRootCommand : public ChangeRootTrustCommand
{
public:
- explicit DistrustRootCommand(KeyListController *parent)
- : ChangeRootTrustCommand(parent)
- {
- setTrust(GpgME::Key::Never);
- }
- explicit DistrustRootCommand(QAbstractItemView *view, KeyListController *parent)
- : ChangeRootTrustCommand(view, parent)
- {
- setTrust(GpgME::Key::Never);
- }
- explicit DistrustRootCommand(const GpgME::Key &key, KeyListController *parent)
- : ChangeRootTrustCommand(key, parent)
- {
- setTrust(GpgME::Key::Never);
- }
- explicit DistrustRootCommand(const GpgME::Key &key, QAbstractItemView *view, KeyListController *parent)
- : ChangeRootTrustCommand(key, view, parent)
+ DistrustRootCommand(QAbstractItemView *view, KeyListController *parent)
+ : ChangeRootTrustCommand(GpgME::Key::Never, view, parent)
{
- setTrust(GpgME::Key::Never);
}
/* reimp */ static Restrictions restrictions()
{
return ChangeRootTrustCommand::restrictions() | MustBeTrustedRoot;
}
};
}
}

File Metadata

Mime Type
text/x-diff
Expires
Sat, Jan 24, 11:29 PM (10 h, 22 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
30/77/23ace0e1e7a865634eef1d397d06

Event Timeline