Page MenuHome GnuPG

No OneTemporary

diff --git a/src/commands/newopenpgpcertificatecommand.cpp b/src/commands/newopenpgpcertificatecommand.cpp
index 208068923..517c88bdf 100644
--- a/src/commands/newopenpgpcertificatecommand.cpp
+++ b/src/commands/newopenpgpcertificatecommand.cpp
@@ -1,325 +1,327 @@
/*
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB
SPDX-FileCopyrightText: 2022 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <config-kleopatra.h>
#include "newopenpgpcertificatecommand.h"
#include "command_p.h"
#include "kleopatraapplication.h"
#include "utils/emptypassphraseprovider.h"
#include "utils/userinfo.h"
#include <qgpgme/quickjob.h>
#include <settings.h>
#include <Libkleo/Formatting>
#include <Libkleo/KeyCache>
#include <Libkleo/KeyParameters>
#include <Libkleo/OpenPGPCertificateCreationDialog>
#include <KConfigGroup>
#include <KLocalizedString>
#include <KMessageBox>
#include <KSharedConfig>
#include <QGpgME/KeyGenerationJob>
#include <QGpgME/Protocol>
#include <QGpgME/QuickJob>
#include <QProgressDialog>
#include <QSettings>
#include <gpgme++/context.h>
#include <gpgme++/keygenerationresult.h>
#include <kleopatra_debug.h>
using namespace Kleo;
using namespace GpgME;
class NewOpenPGPCertificateCommand::Private : public Command::Private
{
friend class ::Kleo::NewOpenPGPCertificateCommand;
NewOpenPGPCertificateCommand *q_func() const
{
return static_cast<NewOpenPGPCertificateCommand *>(q);
}
public:
explicit Private(NewOpenPGPCertificateCommand *qq, KeyListController *c)
: Command::Private{qq, c}
{
}
void getCertificateDetails();
void createCertificate();
void showResult(const KeyGenerationResult &result);
void showErrorDialog(const KeyGenerationResult &result);
private:
KeyParameters keyParameters;
bool protectKeyWithPassword = false;
bool isTeamKey = false;
EmptyPassphraseProvider emptyPassphraseProvider;
QPointer<OpenPGPCertificateCreationDialog> detailsDialog;
QPointer<QGpgME::Job> job;
QPointer<QProgressDialog> progressDialog;
std::shared_ptr<KeyCacheAutoRefreshSuspension> keyCacheAutoRefreshSuspension;
};
NewOpenPGPCertificateCommand::Private *NewOpenPGPCertificateCommand::d_func()
{
return static_cast<Private *>(d.get());
}
const NewOpenPGPCertificateCommand::Private *NewOpenPGPCertificateCommand::d_func() const
{
return static_cast<const Private *>(d.get());
}
#define d d_func()
#define q q_func()
void NewOpenPGPCertificateCommand::Private::getCertificateDetails()
{
detailsDialog = new OpenPGPCertificateCreationDialog;
detailsDialog->setAttribute(Qt::WA_DeleteOnClose);
applyWindowID(detailsDialog);
if (isTeamKey) {
detailsDialog->setWindowTitle(i18nc("title:window", "Create OpenPGP Team Certificate"));
detailsDialog->setInfoText(
i18nc("@info", "Enter a name and/or an email address to use for the certificate. The certificate will be set up for shared usage in a team."));
+ detailsDialog->setEmailLabel(i18nc("@label", "Team email address"));
+ detailsDialog->setNameLabel(i18nc("@label", "Team name"));
}
if (keyParameters.protocol() == KeyParameters::NoProtocol) {
const auto settings = Kleo::Settings{};
const KConfigGroup config{KSharedConfig::openConfig(), QLatin1StringView("CertificateCreationWizard")};
if (!isTeamKey) {
// prefer the last used name and email address over the values retrieved from the system
detailsDialog->setName(config.readEntry("NAME", QString{}));
if (detailsDialog->name().isEmpty() && settings.prefillName()) {
detailsDialog->setName(userFullName());
}
detailsDialog->setEmail(config.readEntry("EMAIL", QString{}));
if (detailsDialog->email().isEmpty() && settings.prefillEmail()) {
detailsDialog->setEmail(userEmailAddress());
}
}
} else {
detailsDialog->setKeyParameters(keyParameters);
detailsDialog->setProtectKeyWithPassword(protectKeyWithPassword);
}
connect(detailsDialog, &QDialog::accepted, q, [this]() {
keyParameters = detailsDialog->keyParameters();
protectKeyWithPassword = detailsDialog->protectKeyWithPassword();
QMetaObject::invokeMethod(
q,
[this] {
createCertificate();
},
Qt::QueuedConnection);
});
connect(detailsDialog, &QDialog::rejected, q, [this]() {
canceled();
});
detailsDialog->show();
}
void NewOpenPGPCertificateCommand::Private::createCertificate()
{
Q_ASSERT(keyParameters.protocol() == KeyParameters::OpenPGP);
auto keyGenJob = QGpgME::openpgp()->keyGenerationJob();
if (!keyGenJob) {
finished();
return;
}
if (!protectKeyWithPassword) {
auto ctx = QGpgME::Job::context(keyGenJob);
ctx->setPassphraseProvider(&emptyPassphraseProvider);
ctx->setPinentryMode(Context::PinentryLoopback);
}
auto settings = KleopatraApplication::instance()->distributionSettings();
if (settings) {
keyParameters.setComment(settings->value(QStringLiteral("uidcomment"), {}).toString());
}
keyCacheAutoRefreshSuspension = KeyCache::mutableInstance()->suspendAutoRefresh();
auto usage = keyParameters.keyUsage();
usage.setIsGroupKey(isTeamKey);
usage.setCanSign(!isTeamKey);
keyParameters.setKeyUsage(usage);
connect(keyGenJob, &QGpgME::KeyGenerationJob::result, q, [this](const KeyGenerationResult &result) {
QMetaObject::invokeMethod(
q,
[this, result] {
if (isTeamKey) {
connect(KeyCache::instance().get(), &KeyCache::keysMayHaveChanged, q, [result, this]() {
auto key = KeyCache::instance()->findByFingerprint(result.fingerprint());
if (key.isNull()) {
return;
}
auto quickJob = QGpgME::openpgp()->quickJob();
auto err = quickJob->startAddSubkey(key, QByteArrayLiteral("rsa3072") /*TODO*/, {}, Context::CreationFlags::CreateSign);
disconnect(KeyCache::instance().get(), nullptr, q, nullptr);
if (err) {
error(i18nc("@info", "Failed to create encryption subkey: %1", Formatting::errorAsString(err)));
return;
}
connect(quickJob, &QGpgME::QuickJob::result, q, [this, result](const auto &err) {
if (err) {
error(i18nc("@info", "Failed to create encryption subkey: %1", Formatting::errorAsString(err)));
return;
}
if (err.isCanceled()) {
return;
}
showResult(result);
});
});
} else {
showResult(result);
}
},
Qt::QueuedConnection);
});
if (const Error err = keyGenJob->start(keyParameters.toString())) {
error(i18n("Could not start key pair creation: %1", Formatting::errorAsString(err)));
finished();
return;
} else {
job = keyGenJob;
}
progressDialog = new QProgressDialog;
progressDialog->setAttribute(Qt::WA_DeleteOnClose);
applyWindowID(progressDialog);
progressDialog->setModal(true);
progressDialog->setWindowTitle(i18nc("@title", "Creating Key Pair..."));
progressDialog->setLabelText(i18n("The process of creating a key requires large amounts of random numbers. This may require several minutes..."));
progressDialog->setRange(0, 0);
connect(progressDialog, &QProgressDialog::canceled, job, &QGpgME::Job::slotCancel);
connect(job, &QGpgME::Job::done, q, [this]() {
if (progressDialog) {
progressDialog->accept();
}
});
progressDialog->show();
}
void NewOpenPGPCertificateCommand::Private::showResult(const KeyGenerationResult &result)
{
if (result.error().isCanceled()) {
finished();
return;
}
// Ensure that we have the key in the cache
Key key;
if (!result.error().code() && result.fingerprint()) {
std::unique_ptr<Context> ctx{Context::createForProtocol(OpenPGP)};
if (ctx) {
Error err;
ctx->addKeyListMode(GpgME::Validate);
key = ctx->key(result.fingerprint(), err, /*secret=*/true);
if (!key.isNull()) {
KeyCache::mutableInstance()->insert(key);
}
}
}
keyCacheAutoRefreshSuspension.reset();
if (!key.isNull()) {
success(xi18nc("@info",
"<para>A new OpenPGP certificate was created successfully.</para>"
"<para>Fingerprint of the new certificate: %1</para>",
Formatting::prettyID(key.primaryFingerprint())));
finished();
} else {
showErrorDialog(result);
}
}
void NewOpenPGPCertificateCommand::Private::showErrorDialog(const KeyGenerationResult &result)
{
QString text;
if (result.error() || !result.fingerprint()) {
text = xi18nc("@info",
"<para>The creation of a new OpenPGP certificate failed.</para>"
"<para>Error: <message>%1</message></para>",
Formatting::errorAsString(result.error()));
} else {
// no error and we have a fingerprint, but there was no corresponding key in the key ring
text = xi18nc("@info",
"<para>A new OpenPGP certificate was created successfully, but it has not been found in the key ring.</para>"
"<para>Fingerprint of the new certificate:<nl/>%1</para>",
Formatting::prettyID(result.fingerprint()));
}
auto dialog = new QDialog;
applyWindowID(dialog);
dialog->setWindowTitle(i18nc("@title:window", "Error"));
auto buttonBox = new QDialogButtonBox{QDialogButtonBox::Retry | QDialogButtonBox::Ok, dialog};
const auto buttonCode = KMessageBox::createKMessageBox(dialog, buttonBox, QMessageBox::Critical, text, {}, {}, nullptr, {});
if (buttonCode == QDialogButtonBox::Retry) {
QMetaObject::invokeMethod(
q,
[this]() {
getCertificateDetails();
},
Qt::QueuedConnection);
} else {
finished();
}
}
NewOpenPGPCertificateCommand::NewOpenPGPCertificateCommand()
: NewOpenPGPCertificateCommand(nullptr, nullptr)
{
}
NewOpenPGPCertificateCommand::NewOpenPGPCertificateCommand(QAbstractItemView *v, KeyListController *c)
: Command(v, new Private(this, c))
{
}
NewOpenPGPCertificateCommand::~NewOpenPGPCertificateCommand() = default;
void NewOpenPGPCertificateCommand::doStart()
{
d->getCertificateDetails();
}
void NewOpenPGPCertificateCommand::doCancel()
{
if (d->detailsDialog) {
d->detailsDialog->close();
}
if (d->job) {
d->job->slotCancel();
}
}
void NewOpenPGPCertificateCommand::setIsTeamKey(bool isTeamKey)
{
d->isTeamKey = isTeamKey;
}
#undef d
#undef q
#include "moc_newopenpgpcertificatecommand.cpp"

File Metadata

Mime Type
text/x-diff
Expires
Thu, Oct 16, 4:50 AM (1 d, 19 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
93/b1/eb2bc6c977b3bcee3180f879c748

Event Timeline