Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F34183635
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
13 KB
Subscribers
None
View Options
diff --git a/src/commands/newopenpgpcertificatecommand.cpp b/src/commands/newopenpgpcertificatecommand.cpp
index 517c88bdf..7bd5a164a 100644
--- a/src/commands/newopenpgpcertificatecommand.cpp
+++ b/src/commands/newopenpgpcertificatecommand.cpp
@@ -1,327 +1,313 @@
/*
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;
+ bool teamKey = 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);
+ detailsDialog->showTeamKeyOption(true);
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());
- }
+ // 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();
+ teamKey = detailsDialog->isTeamKey();
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) {
+ if (teamKey) {
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);
+ auto flags = Context::CreationFlags::CreateSign;
+ if (!protectKeyWithPassword) {
+ flags |= GpgME::Context::CreationFlags::CreateNoPassword;
+ }
+ auto err = quickJob->startAddSubkey(key, QByteArrayLiteral("rsa3072") /*TODO*/, {}, flags);
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"
diff --git a/src/commands/newopenpgpcertificatecommand.h b/src/commands/newopenpgpcertificatecommand.h
index d1f96b603..e37f11e91 100644
--- a/src/commands/newopenpgpcertificatecommand.h
+++ b/src/commands/newopenpgpcertificatecommand.h
@@ -1,38 +1,35 @@
/*
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
*/
#pragma once
#include "command.h"
namespace Kleo
{
class NewOpenPGPCertificateCommand : public Command
{
Q_OBJECT
public:
NewOpenPGPCertificateCommand();
NewOpenPGPCertificateCommand(QAbstractItemView *view, KeyListController *parent);
~NewOpenPGPCertificateCommand() override;
-protected:
- void setIsTeamKey(bool isTeamKey);
-
private:
void doStart() override;
void doCancel() override;
private:
class Private;
inline Private *d_func();
inline const Private *d_func() const;
};
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Dec 14, 10:21 AM (23 h, 52 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
2c/e4/db48dfd20a7a62dff1a008e7f7f7
Attached To
rKLEOPATRA Kleopatra
Event Timeline
Log In to Comment