Page MenuHome GnuPG

No OneTemporary

diff --git a/src/commands/keytocardcommand.cpp b/src/commands/keytocardcommand.cpp
index 864ac9d14..4718108f9 100644
--- a/src/commands/keytocardcommand.cpp
+++ b/src/commands/keytocardcommand.cpp
@@ -1,248 +1,235 @@
/* commands/setinitialpincommand.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2017 Bundesamt für Sicherheit in der Informationstechnik
SPDX-FileContributor: Intevation GmbH
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <config-kleopatra.h>
#include "keytocardcommand.h"
#include "kleopatra_debug.h"
#include "command_p.h"
#include "smartcard/readerstatus.h"
#include "smartcard/openpgpcard.h"
#include <QInputDialog>
#include <QDateTime>
#include <QStringList>
#include <KLocalizedString>
#include <gpgme++/gpgmepp_version.h>
#if GPGMEPP_VERSION > 0x10801
# define GPGME_SUBKEY_HAS_KEYGRIP
#endif
#include "kleopatra_debug.h"
using namespace Kleo;
using namespace Kleo::Commands;
using namespace Kleo::SmartCard;
using namespace GpgME;
bool KeyToCardCommand::supported()
{
#ifdef GPGME_SUBKEY_HAS_KEYGRIP
return true;
#else
return false;
#endif
}
class KeyToCardCommand::Private : public Command::Private
{
friend class ::Kleo::Commands::KeyToCardCommand;
KeyToCardCommand *q_func() const
{
return static_cast<KeyToCardCommand *>(q);
}
public:
explicit Private(KeyToCardCommand *qq, const GpgME::Subkey &key, const std::string &serialno);
~Private();
private:
void start()
{
qCDebug(KLEOPATRA_LOG) << "KeyToCardCommand::Private::start()";
// Check if we need to ask the user for the slot
if ((mKey.canSign() || mKey.canCertify()) && !mKey.canEncrypt() && !mKey.canAuthenticate()) {
// Signing only
slotDetermined(1);
return;
}
if (mKey.canEncrypt() && !(mKey.canSign() || mKey.canCertify()) && !mKey.canAuthenticate()) {
// Encrypt only
slotDetermined(2);
return;
}
if (mKey.canAuthenticate() && !(mKey.canSign() || mKey.canCertify()) && !mKey.canEncrypt()) {
// Auth only
slotDetermined(3);
return;
}
// Multiple uses, ask user.
QStringList options;
if (mKey.canSign() || mKey.canCertify()) {
options << i18nc("Placeholder is the number of a slot on a smart card", "Signature (%1)", 1);
}
if (mKey.canEncrypt()) {
options << i18nc("Placeholder is the number of a slot on a smart card", "Encryption (%1)", 2);
}
if (mKey.canAuthenticate()) {
options << i18nc("Placeholder is the number of a slot on a smart card", "Authentication (%1)", 3);
}
bool ok;
const QString choice = QInputDialog::getItem(parentWidgetOrView(), i18n("Select Slot"),
i18n("Please select the slot the key should be written to:"), options, /* current= */ 0, /* editable= */ false, &ok);
const int slot = options.indexOf(choice) + 1;
if (!ok || slot == 0) {
finished();
} else {
slotDetermined(slot);
}
}
void slotDetermined(int slot)
{
- // Check if we need to do the overwrite warning.
- const auto cards = ReaderStatus::instance()->getCards();
+ qCDebug(KLEOPATRA_LOG) << "KeyToCardCommand::Private::slotDetermined():" << slot;
- qDebug() << "slot determined" << slot;
- bool cardFound = false;
- std::string existingKey;
- QString encKeyWarning;
- for (const auto &card: cards) {
- if (card->serialNumber() == mSerial) {
- const auto pgpCard = dynamic_cast<SmartCard::OpenPGPCard*>(card.get());
- Q_ASSERT(pgpCard);
- cardFound = true;
- if (slot == 1) {
- existingKey = pgpCard->sigFpr();
- break;
- }
- if (slot == 2) {
- existingKey = pgpCard->encFpr();
- encKeyWarning = i18n("It will no longer be possible to decrypt past communication "
- "encrypted for the existing key.");
- break;
- }
- if (slot == 3) {
- existingKey = pgpCard->authFpr();
- break;
- }
- break;
- }
- }
- if (!cardFound) {
+ // Check if we need to do the overwrite warning.
+ const auto pgpCard = ReaderStatus::instance()->getCard<OpenPGPCard>(mSerial);
+ if (!pgpCard) {
error(i18n("Failed to find the card with the serial number: %1", QString::fromStdString(mSerial)));
finished();
return;
}
+
+ std::string existingKey;
+ QString encKeyWarning;
+ if (slot == 1) {
+ existingKey = pgpCard->sigFpr();
+ } else if (slot == 2) {
+ existingKey = pgpCard->encFpr();
+ encKeyWarning = i18n("It will no longer be possible to decrypt past communication "
+ "encrypted for the existing key.");
+ } else if (slot == 3) {
+ existingKey = pgpCard->authFpr();
+ }
if (!existingKey.empty()) {
if (KMessageBox::warningContinueCancel(parentWidgetOrView(), i18nc("@info",
"<p>This card already contains a key in this slot. Continuing will <b>overwrite</b> that key.</p>"
"<p>If there is no backup the existing key will be irrecoverably lost.</p>") +
i18n("The existing key has the fingerprint:") + QStringLiteral("<pre>%1</pre>").arg(QString::fromStdString(existingKey)) +
encKeyWarning,
i18nc("@title:window", "Overwrite existing key"),
KStandardGuiItem::cont(), KStandardGuiItem::cancel(), QString(), KMessageBox::Notify | KMessageBox::Dangerous)
!= KMessageBox::Continue) {
finished();
return;
}
}
// Now do the deed
const auto time = QDateTime::fromSecsSinceEpoch(mKey.creationTime());
const auto timestamp = time.toString(QStringLiteral("yyyyMMdd'T'HHmmss"));
#ifdef GPGME_SUBKEY_HAS_KEYGRIP
const QString cmd = QStringLiteral("KEYTOCARD --force %1 %2 OPENPGP.%3 %4").arg(QString::fromLatin1(mKey.keyGrip()), QString::fromStdString(mSerial))
.arg(slot)
.arg(timestamp);
ReaderStatus::mutableInstance()->startSimpleTransaction(cmd.toUtf8(), q_func(), "keyToCardDone");
#else
finished();
#endif
}
private:
std::string mSerial;
GpgME::Subkey mKey;
};
KeyToCardCommand::Private *KeyToCardCommand::d_func()
{
return static_cast<Private *>(d.get());
}
const KeyToCardCommand::Private *KeyToCardCommand::d_func() const
{
return static_cast<const Private *>(d.get());
}
#define q q_func()
#define d d_func()
void KeyToCardCommand::keyToCardDone(const GpgME::Error &err)
{
if (err) {
d->error(i18nc("@info",
"Moving the key to the card failed: %1", QString::fromUtf8(err.asString())),
i18nc("@title", "Error"));
} else if (!err.isCanceled()) {
/* TODO DELETE_KEY is too strong, because it also deletes the stub
* of the secret key. I could not find out how GnuPG does this. Question
* to GnuPG Developers is pending an answer
if (KMessageBox::questionYesNo(d->parentWidgetOrView(),
i18n("Do you want to delete the key on this computer?"),
i18nc("@title:window",
"Key transferred to card")) == KMessageBox::Yes) {
const QString cmd = QStringLiteral("DELETE_KEY --force %1").arg(d->mKey.keyGrip());
// Using readerstatus is a bit overkill but it's an easy way to talk to the agent.
ReaderStatus::mutableInstance()->startSimpleTransaction(cmd.toUtf8(), this, "deleteDone");
}
*/
KMessageBox::information(d->parentWidgetOrView(),
i18n("Successfully copied the key to the card."),
i18nc("@title", "Success"));
}
d->finished();
}
void KeyToCardCommand::deleteDone(const GpgME::Error &err)
{
if (err) {
d->error(i18nc("@info", "Failed to delete the key: %1", QString::fromUtf8(err.asString())),
i18nc("@title", "Error"));
}
d->finished();
}
KeyToCardCommand::Private::Private(KeyToCardCommand *qq,
const GpgME::Subkey &key,
const std::string &serialno)
: Command::Private(qq, nullptr),
mSerial(serialno),
mKey(key)
{
}
KeyToCardCommand::Private::~Private() {}
KeyToCardCommand::KeyToCardCommand(const GpgME::Subkey &key, const std::string &serialno)
: Command(new Private(this, key, serialno))
{
}
KeyToCardCommand::~KeyToCardCommand() {}
void KeyToCardCommand::doStart()
{
qCDebug(KLEOPATRA_LOG) << "KeyToCardCommand::doStart()";
d->start();
}
void KeyToCardCommand::doCancel()
{
}
#undef q_func
#undef d_func

File Metadata

Mime Type
text/x-diff
Expires
Tue, Feb 10, 7:47 PM (1 d, 12 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
b7/0b/be0d41f7d2cebfe86246076cf019

Event Timeline