Commit 7435acce authored by Ingo Klöcker's avatar Ingo Klöcker

Pass the card/app to work on to the functions triggering a card command

This is done in preparation of support for multiple cards/apps.

GnuPG-bug-id: 5066
parent 52c3759c
......@@ -11,6 +11,7 @@
#include "cardcommand_p.h"
#include "smartcard/pivcard.h"
#include "smartcard/readerstatus.h"
#include "dialogs/pivcardapplicationadministrationkeyinputdialog.h"
......@@ -114,9 +115,16 @@ void AuthenticatePIVCardApplicationCommand::Private::authenticate(const QByteArr
{
qCDebug(KLEOPATRA_LOG) << "AuthenticatePIVCardApplicationCommand::authenticate()";
const auto pivCard = SmartCard::ReaderStatus::instance()->getCard<PIVCard>(serialNumber());
if (!pivCard) {
error(i18n("Failed to find the PIV card with the serial number: %1", QString::fromStdString(serialNumber())));
finished();
return;
}
const QByteArray plusPercentEncodedAdminKey = adminKey.toPercentEncoding().replace(' ', '+');
const QByteArray command = QByteArray("SCD SETATTR AUTH-ADM-KEY ") + plusPercentEncodedAdminKey;
ReaderStatus::mutableInstance()->startSimpleTransaction(command, q, "slotResult");
ReaderStatus::mutableInstance()->startSimpleTransaction(pivCard, command, q, "slotResult");
}
void AuthenticatePIVCardApplicationCommand::Private::slotResult(const Error &err)
......
......@@ -163,10 +163,16 @@ void CertificateToPIVCardCommand::Private::startCertificateToPIVCard()
}
const QByteArray certificateData = dp.data();
const QString cmd = QStringLiteral("SCD WRITECERT %1")
.arg(QString::fromStdString(cardSlot));
const auto pivCard = SmartCard::ReaderStatus::instance()->getCard<PIVCard>(serialNumber());
if (!pivCard) {
error(i18n("Failed to find the PIV card with the serial number: %1", QString::fromStdString(serialNumber())));
finished();
return;
}
const QByteArray command = QByteArrayLiteral("SCD WRITECERT ") + QByteArray::fromStdString(cardSlot);
auto transaction = std::unique_ptr<AssuanTransaction>(new WriteCertAssuanTransaction(certificateData));
ReaderStatus::mutableInstance()->startTransaction(cmd.toUtf8(), q_func(), "certificateToPIVCardDone", std::move(transaction));
ReaderStatus::mutableInstance()->startTransaction(pivCard, command, q_func(), "certificateToPIVCardDone", std::move(transaction));
}
void CertificateToPIVCardCommand::Private::authenticate()
......
......@@ -105,19 +105,32 @@ void ChangePinCommand::doCancel()
void ChangePinCommand::Private::changePin()
{
qCDebug(KLEOPATRA_LOG) << "ChangePinCommand::changePin()";
const auto card = SmartCard::ReaderStatus::instance()->getCard<Card>(serialNumber());
if (!card) {
error(i18n("Failed to find the smartcard with the serial number: %1", QString::fromStdString(serialNumber())));
finished();
return;
}
QByteArrayList command;
command << "SCD PASSWD";
if (keyRef == OpenPGPCard::resetCodeKeyRef()) {
if (card->appName() == OpenPGPCard::AppName && keyRef == OpenPGPCard::resetCodeKeyRef()) {
// special handling for setting/changing the Reset Code of OpenPGP v2 cards
const auto card = ReaderStatus::instance()->getCard<OpenPGPCard>(serialNumber());
const std::string firstTwoVersionChars = card->cardVersion().substr(0, 2);
const auto pgpCard = std::dynamic_pointer_cast<OpenPGPCard>(card);
if (!pgpCard) {
error(i18n("Failed to find the OpenPGP card with the serial number: %1", QString::fromStdString(serialNumber())));
finished();
return;
}
const std::string firstTwoVersionChars = pgpCard->cardVersion().substr(0, 2);
const bool isVersion2 = !(firstTwoVersionChars == "1." || firstTwoVersionChars == "0.");
if (isVersion2) {
command << "--reset";
}
}
command << QByteArray::fromStdString(keyRef);
ReaderStatus::mutableInstance()->startSimpleTransaction(command.join(' '), q, "slotResult");
ReaderStatus::mutableInstance()->startSimpleTransaction(card, command.join(' '), q, "slotResult");
}
namespace {
......
......@@ -224,7 +224,7 @@ void KeyToCardCommand::Private::startKeyToOpenPGPCard() {
.arg(QString::fromLatin1(subkey.keyGrip()), QString::fromStdString(serialNumber()))
.arg(slot)
.arg(timestamp);
ReaderStatus::mutableInstance()->startSimpleTransaction(cmd.toUtf8(), q_func(), "keyToOpenPGPCardDone");
ReaderStatus::mutableInstance()->startSimpleTransaction(pgpCard, cmd.toUtf8(), q_func(), "keyToOpenPGPCardDone");
}
namespace {
......@@ -329,7 +329,7 @@ void KeyToCardCommand::Private::startKeyToPIVCard()
const QString cmd = QStringLiteral("KEYTOCARD --force %1 %2 %3")
.arg(QString::fromLatin1(subkey.keyGrip()), QString::fromStdString(serialNumber()))
.arg(QString::fromStdString(cardSlot));
ReaderStatus::mutableInstance()->startSimpleTransaction(cmd.toUtf8(), q_func(), "keyToPIVCardDone");
ReaderStatus::mutableInstance()->startSimpleTransaction(pivCard, cmd.toUtf8(), q_func(), "keyToPIVCardDone");
}
void KeyToCardCommand::Private::authenticate()
......@@ -395,7 +395,7 @@ void KeyToCardCommand::keyToOpenPGPCardDone(const GpgME::Error &err)
"Key transferred to card")) == KMessageBox::Yes) {
const QString cmd = QStringLiteral("DELETE_KEY --force %1").arg(d->subkey.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");
ReaderStatus::mutableInstance()->startSimpleTransaction(card, cmd.toUtf8(), this, "deleteDone");
}
*/
d->information(i18nc("@info", "Successfully copied the key to the card."),
......
......@@ -112,7 +112,7 @@ void PIVGenerateCardKeyCommand::doStart()
// check if key exists
auto pivCard = ReaderStatus::instance()->getCard<PIVCard>(d->serialNumber());
if (!pivCard) {
d->error(i18n("Failed to find the card with the serial number: %1", QString::fromStdString(d->serialNumber())));
d->error(i18n("Failed to find the PIV card with the serial number: %1", QString::fromStdString(d->serialNumber())));
d->finished();
return;
}
......@@ -176,6 +176,13 @@ void PIVGenerateCardKeyCommand::Private::generateKey()
{
qCDebug(KLEOPATRA_LOG) << "PIVGenerateCardKeyCommand::generateKey()";
auto pivCard = ReaderStatus::instance()->getCard<PIVCard>(serialNumber());
if (!pivCard) {
error(i18n("Failed to find the PIV card with the serial number: %1", QString::fromStdString(serialNumber())));
finished();
return;
}
QByteArrayList command;
command << "SCD GENKEY";
if (overwriteExistingKey) {
......@@ -185,7 +192,7 @@ void PIVGenerateCardKeyCommand::Private::generateKey()
command << "--algo=" + QByteArray::fromStdString(algorithm);
}
command << "--" << QByteArray::fromStdString(keyRef);
ReaderStatus::mutableInstance()->startSimpleTransaction(command.join(' '), q, "slotResult");
ReaderStatus::mutableInstance()->startSimpleTransaction(pivCard, command.join(' '), q, "slotResult");
}
void PIVGenerateCardKeyCommand::Private::slotResult(const GpgME::Error& err)
......
......@@ -72,18 +72,26 @@ private:
}
private:
void setInitialPin(const char *pinRef, const char *resultSlot)
{
const auto nksCard = ReaderStatus::instance()->getCard<NetKeyCard>(serialNumber());
if (!nksCard) {
error(i18n("Failed to find the NetKey card with the serial number: %1", QString::fromStdString(serialNumber())));
return;
}
const QByteArray command = QByteArray("SCD PASSWD --nullpin ") + pinRef;
ReaderStatus::mutableInstance()->startSimpleTransaction(nksCard, command, dialog, resultSlot);
}
void slotNksPinRequested()
{
ReaderStatus::mutableInstance()
->startSimpleTransaction("SCD PASSWD --nullpin PW1.CH",
dialog, "setNksPinSettingResult");
setInitialPin("PW1.CH", "setNksPinSettingResult");
}
void slotSigGPinRequested()
{
ReaderStatus::mutableInstance()
->startSimpleTransaction("SCD PASSWD --nullpin PW1.CH.SIG",
dialog, "setSigGPinSettingResult");
setInitialPin("PW1.CH.SIG", "setSigGPinSettingResult");
}
void slotDialogRejected()
......
......@@ -11,6 +11,7 @@
#include "cardcommand_p.h"
#include "smartcard/pivcard.h"
#include "smartcard/readerstatus.h"
#include "commands/authenticatepivcardapplicationcommand.h"
......@@ -182,9 +183,16 @@ void SetPIVCardApplicationAdministrationKeyCommand::Private::slotDialogAccepted(
return;
}
auto pivCard = ReaderStatus::instance()->getCard<PIVCard>(serialNumber());
if (!pivCard) {
error(i18n("Failed to find the PIV card with the serial number: %1", QString::fromStdString(serialNumber())));
finished();
return;
}
const QByteArray plusPercentEncodedAdminKey = newAdminKey.toPercentEncoding().replace(' ', '+');
const QByteArray command = QByteArray("SCD SETATTR SET-ADM-KEY ") + plusPercentEncodedAdminKey;
ReaderStatus::mutableInstance()->startSimpleTransaction(command, q, "slotResult");
ReaderStatus::mutableInstance()->startSimpleTransaction(pivCard, command, q, "slotResult");
}
void SetPIVCardApplicationAdministrationKeyCommand::Private::slotDialogRejected()
......
......@@ -106,6 +106,11 @@ static QDebug operator<<(QDebug s, const std::vector< std::pair<std::string, std
return s << ')';
}
struct CardApp {
std::string serialNumber;
std::string appName;
};
static int parse_app_version(const std::string &s)
{
return std::atoi(s.c_str());
......@@ -484,14 +489,15 @@ static std::vector<std::shared_ptr<Card> > update_cardinfo(std::shared_ptr<Conte
} // namespace
struct Transaction {
CardApp cardApp;
QByteArray command;
QPointer<QObject> receiver;
const char *slot;
AssuanTransaction* assuanTransaction;
};
static const Transaction updateTransaction = { "__update__", nullptr, nullptr, nullptr };
static const Transaction quitTransaction = { "__quit__", nullptr, nullptr, nullptr };
static const Transaction updateTransaction = { { "__all__", "__all__" }, "__update__", nullptr, nullptr, nullptr };
static const Transaction quitTransaction = { { "__all__", "__all__" }, "__quit__", nullptr, nullptr, nullptr };
namespace
{
......@@ -788,15 +794,18 @@ bool ReaderStatus::anyCardCanLearnKeys() const
return d->anyCardCanLearnKeysImpl();
}
void ReaderStatus::startSimpleTransaction(const QByteArray &command, QObject *receiver, const char *slot)
void ReaderStatus::startSimpleTransaction(const std::shared_ptr<Card> &card, const QByteArray &command, QObject *receiver, const char *slot)
{
const Transaction t = { command, receiver, slot, nullptr };
const CardApp cardApp = { card->serialNumber(), card->appName() };
const Transaction t = { cardApp, command, receiver, slot, nullptr };
d->addTransaction(t);
}
void ReaderStatus::startTransaction(const QByteArray &command, QObject *receiver, const char *slot, std::unique_ptr<AssuanTransaction> transaction)
void ReaderStatus::startTransaction(const std::shared_ptr<Card> &card, const QByteArray &command, QObject *receiver, const char *slot,
std::unique_ptr<AssuanTransaction> transaction)
{
const Transaction t = { command, receiver, slot, transaction.release() };
const CardApp cardApp = { card->serialNumber(), card->appName() };
const Transaction t = { cardApp, command, receiver, slot, transaction.release() };
d->addTransaction(t);
}
......
......@@ -40,8 +40,9 @@ public:
static const ReaderStatus *instance();
static ReaderStatus *mutableInstance();
void startSimpleTransaction(const QByteArray &cmd, QObject *receiver, const char *slot);
void startTransaction(const QByteArray &cmd, QObject *receiver, const char *slot, std::unique_ptr<GpgME::AssuanTransaction> transaction);
void startSimpleTransaction(const std::shared_ptr<Card> &card, const QByteArray &cmd, QObject *receiver, const char *slot);
void startTransaction(const std::shared_ptr<Card> &card, const QByteArray &cmd, QObject *receiver, const char *slot,
std::unique_ptr<GpgME::AssuanTransaction> transaction);
Card::Status cardStatus(unsigned int slot) const;
std::string firstCardWithNullPin() const;
......
......@@ -36,7 +36,7 @@ using namespace Kleo::Commands;
NetKeyWidget::NetKeyWidget(QWidget *parent) :
QWidget(parent),
mSerialNumber(new QLabel(this)),
mSerialNumberLabel(new QLabel(this)),
mVersionLabel(new QLabel(this)),
mLearnKeysLabel(new QLabel(this)),
mErrorLabel(new QLabel(this)),
......@@ -62,11 +62,11 @@ NetKeyWidget::NetKeyWidget(QWidget *parent) :
mVersionLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
vLay->addWidget(mVersionLabel, 0, Qt::AlignLeft);
mSerialNumber->setTextInteractionFlags(Qt::TextBrowserInteraction);
mSerialNumberLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
auto hLay1 = new QHBoxLayout;
hLay1->addWidget(new QLabel(i18n("Serial number:")));
hLay1->addWidget(mSerialNumber);
hLay1->addWidget(mSerialNumberLabel);
hLay1->addStretch(1);
vLay->addLayout(hLay1);
......@@ -156,9 +156,11 @@ NetKeyWidget::~NetKeyWidget()
void NetKeyWidget::setCard(const NetKeyCard* card)
{
mSerialNumber = card->serialNumber();
mVersionLabel->setText(i18nc("1 is a Version number", "NetKey v%1 Card", card->appVersion()));
mSerialNumber->setText(QString::fromStdString(card->serialNumber()));
mSerialNumberLabel->setText(QString::fromStdString(mSerialNumber));
mNullPinWidget->setSerialNumber(mSerialNumber);
/* According to users of NetKey Cards it is fairly uncommon
* to use SigG Certificates at all. So it should be optional to set the pins. */
mNullPinWidget->setVisible(card->hasNKSNullPin() /*|| card->hasSigGNullPin()*/);
......@@ -218,13 +220,17 @@ void NetKeyWidget::setNksPinSettingResult(const GpgME::Error &err)
void NetKeyWidget::doChangePin(bool sigG)
{
const auto nksCard = ReaderStatus::instance()->getCard<NetKeyCard>(mSerialNumber);
if (!nksCard) {
KMessageBox::error(this, i18n("Failed to find the NetKey card with the serial number: %1", QString::fromStdString(mSerialNumber)));
return;
}
if (sigG) {
ReaderStatus::mutableInstance()
->startSimpleTransaction("SCD PASSWD PW1.CH.SIG",
this, "setSigGPinSettingResult");
ReaderStatus::mutableInstance()->startSimpleTransaction(
nksCard, "SCD PASSWD PW1.CH.SIG", this, "setSigGPinSettingResult");
} else {
ReaderStatus::mutableInstance()
->startSimpleTransaction("SCD PASSWD PW1.CH",
this, "setNksPinSettingResult");
ReaderStatus::mutableInstance()->startSimpleTransaction(
nksCard, "SCD PASSWD PW1.CH", this, "setNksPinSettingResult");
}
}
......@@ -34,7 +34,7 @@ public:
explicit NetKeyWidget(QWidget *parent = nullptr);
~NetKeyWidget();
void setCard(const SmartCard::NetKeyCard* card);
void setCard(const SmartCard::NetKeyCard *card);
private:
void handleResult(const GpgME::Error &err, QPushButton *btn);
......@@ -45,7 +45,8 @@ private Q_SLOTS:
void setNksPinSettingResult(const GpgME::Error &err);
private:
QLabel *mSerialNumber,
std::string mSerialNumber;
QLabel *mSerialNumberLabel,
*mVersionLabel,
*mLearnKeysLabel,
*mErrorLabel;
......
......@@ -10,6 +10,7 @@
#include "kleopatra_debug.h"
#include "smartcard/netkeycard.h"
#include "smartcard/readerstatus.h"
#include <gpgme++/error.h>
......@@ -58,6 +59,11 @@ NullPinWidget::NullPinWidget(QWidget *parent)
vLay->addLayout(hLayBtn);
}
void NullPinWidget::setSerialNumber(const std::string &serialNumber)
{
mSerialNumber = serialNumber;
}
void NullPinWidget::doChangePin(bool sigG)
{
auto ret = KMessageBox::warningContinueCancel(this,
......@@ -75,14 +81,18 @@ void NullPinWidget::doChangePin(bool sigG)
return;
}
const auto nksCard = ReaderStatus::instance()->getCard<NetKeyCard>(mSerialNumber);
if (!nksCard) {
KMessageBox::error(this, i18n("Failed to find the NetKey card with the serial number: %1", QString::fromStdString(mSerialNumber)));
return;
}
if (sigG) {
ReaderStatus::mutableInstance()
->startSimpleTransaction("SCD PASSWD --nullpin PW1.CH.SIG",
this, "setSigGPinSettingResult");
ReaderStatus::mutableInstance()->startSimpleTransaction(
nksCard, "SCD PASSWD --nullpin PW1.CH.SIG", this, "setSigGPinSettingResult");
} else {
ReaderStatus::mutableInstance()
->startSimpleTransaction("SCD PASSWD --nullpin PW1.CH",
this, "setNksPinSettingResult");
ReaderStatus::mutableInstance()->startSimpleTransaction(
nksCard, "SCD PASSWD --nullpin PW1.CH", this, "setNksPinSettingResult");
}
}
......
......@@ -26,6 +26,7 @@ class NullPinWidget: public QWidget
public:
explicit NullPinWidget(QWidget *parent = nullptr);
void setSerialNumber(const std::string &serialNumber);
void setSigGVisible(bool val);
void setNKSVisible(bool val);
......@@ -38,6 +39,7 @@ private Q_SLOTS:
void setNksPinSettingResult(const GpgME::Error &err);
private:
std::string mSerialNumber;
QPushButton *mNKSBtn,
*mSigGBtn;
};
......
......@@ -374,9 +374,14 @@ void PGPCardWidget::changeNameRequested()
const auto lastName = parts.takeLast();
const QString formatted = lastName + QStringLiteral("<<") + parts.join(QLatin1Char('<'));
ReaderStatus::mutableInstance()
->startSimpleTransaction(QStringLiteral("SCD SETATTR DISP-NAME %1").arg(formatted).toUtf8().constData(),
this, "changeNameResult");
const auto pgpCard = ReaderStatus::instance()->getCard<OpenPGPCard>(mRealSerial);
if (!pgpCard) {
KMessageBox::error(this, i18n("Failed to find the OpenPGP card with the serial number: %1", QString::fromStdString(mRealSerial)));
return;
}
const QByteArray command = QByteArrayLiteral("SCD SETATTR DISP-NAME ") + formatted.toUtf8();
ReaderStatus::mutableInstance()->startSimpleTransaction(pgpCard, command, this, "changeNameResult");
}
void PGPCardWidget::changeNameResult(const GpgME::Error &err)
......@@ -416,9 +421,14 @@ void PGPCardWidget::changeUrlRequested()
break;
}
ReaderStatus::mutableInstance()
->startSimpleTransaction(QStringLiteral("SCD SETATTR PUBKEY-URL %1").arg(text).toUtf8().constData(),
this, "changeUrlResult");
const auto pgpCard = ReaderStatus::instance()->getCard<OpenPGPCard>(mRealSerial);
if (!pgpCard) {
KMessageBox::error(this, i18n("Failed to find the OpenPGP card with the serial number: %1", QString::fromStdString(mRealSerial)));
return;
}
const QByteArray command = QByteArrayLiteral("SCD SETATTR PUBKEY-URL ") + text.toUtf8();
ReaderStatus::mutableInstance()->startSimpleTransaction(pgpCard, command, this, "changeUrlResult");
}
void PGPCardWidget::changeUrlResult(const GpgME::Error &err)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment