File indexing completed on 2024-06-23 05:13:45

0001 /* -*- mode: c++; c-basic-offset:4 -*-
0002     commands/setinitialpincommand.cpp
0003 
0004     This file is part of Kleopatra, the KDE keymanager
0005     SPDX-FileCopyrightText: 2009 Klarälvdalens Datakonsult AB
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 
0010 #include <config-kleopatra.h>
0011 
0012 #include "cardcommand_p.h"
0013 #include "setinitialpincommand.h"
0014 
0015 #include "dialogs/setinitialpindialog.h"
0016 
0017 #include "smartcard/netkeycard.h"
0018 #include "smartcard/readerstatus.h"
0019 
0020 #include <KLocalizedString>
0021 
0022 using namespace Kleo;
0023 using namespace Kleo::Commands;
0024 using namespace Kleo::Dialogs;
0025 using namespace Kleo::SmartCard;
0026 using namespace GpgME;
0027 
0028 class SetInitialPinCommand::Private : public CardCommand::Private
0029 {
0030     friend class ::Kleo::Commands::SetInitialPinCommand;
0031     SetInitialPinCommand *q_func() const
0032     {
0033         return static_cast<SetInitialPinCommand *>(q);
0034     }
0035 
0036 public:
0037     explicit Private(SetInitialPinCommand *qq, const std::string &serialNumber);
0038     ~Private() override;
0039 
0040 private:
0041     void init()
0042     {
0043     }
0044 
0045     void ensureDialogCreated()
0046     {
0047         if (dialog) {
0048             return;
0049         }
0050 
0051         auto dlg = new SetInitialPinDialog;
0052         applyWindowID(dlg);
0053         dlg->setAttribute(Qt::WA_DeleteOnClose);
0054         dlg->setWindowTitle(i18nc("@title:window", "Set Initial Pin"));
0055 
0056         connect(dlg, &SetInitialPinDialog::nksPinRequested, q_func(), [this]() {
0057             slotNksPinRequested();
0058         });
0059         connect(dlg, &SetInitialPinDialog::sigGPinRequested, q_func(), [this]() {
0060             slotSigGPinRequested();
0061         });
0062         connect(dlg, &QDialog::rejected, q_func(), [this]() {
0063             slotDialogRejected();
0064         });
0065         connect(dlg, &QDialog::accepted, q_func(), [this]() {
0066             slotDialogAccepted();
0067         });
0068 
0069         dialog = dlg;
0070     }
0071 
0072     void ensureDialogVisible()
0073     {
0074         ensureDialogCreated();
0075         if (dialog->isVisible()) {
0076             dialog->raise();
0077         } else {
0078             dialog->show();
0079         }
0080     }
0081 
0082 private:
0083     void setInitialPin(const char *pinRef, const ReaderStatus::TransactionFunc &resultSlot)
0084     {
0085         const auto nksCard = ReaderStatus::instance()->getCard<NetKeyCard>(serialNumber());
0086         if (!nksCard) {
0087             error(i18n("Failed to find the NetKey card with the serial number: %1", QString::fromStdString(serialNumber())));
0088             return;
0089         }
0090 
0091         const QByteArray command = QByteArray("SCD PASSWD --nullpin ") + pinRef;
0092         ReaderStatus::mutableInstance()->startSimpleTransaction(nksCard, command, dialog, resultSlot);
0093     }
0094 
0095     void slotNksPinRequested()
0096     {
0097         setInitialPin("PW1.CH", [this](const GpgME::Error &error) {
0098             dialog->setNksPinSettingResult(error);
0099         });
0100     }
0101 
0102     void slotSigGPinRequested()
0103     {
0104         setInitialPin("PW1.CH.SIG", [this](const GpgME::Error &error) {
0105             dialog->setSigGPinSettingResult(error);
0106         });
0107     }
0108 
0109     void slotDialogRejected()
0110     {
0111         if (dialog->isComplete()) {
0112             slotDialogAccepted();
0113         } else {
0114             canceled();
0115         }
0116     }
0117     void slotDialogAccepted()
0118     {
0119         ReaderStatus::mutableInstance()->updateStatus();
0120         finished();
0121     }
0122 
0123 private:
0124     mutable QPointer<SetInitialPinDialog> dialog;
0125 };
0126 
0127 SetInitialPinCommand::Private *SetInitialPinCommand::d_func()
0128 {
0129     return static_cast<Private *>(d.get());
0130 }
0131 const SetInitialPinCommand::Private *SetInitialPinCommand::d_func() const
0132 {
0133     return static_cast<const Private *>(d.get());
0134 }
0135 
0136 #define q q_func()
0137 #define d d_func()
0138 
0139 SetInitialPinCommand::Private::Private(SetInitialPinCommand *qq, const std::string &serialNumber)
0140     : CardCommand::Private(qq, serialNumber, nullptr)
0141     , dialog()
0142 {
0143 }
0144 
0145 SetInitialPinCommand::Private::~Private()
0146 {
0147 }
0148 
0149 SetInitialPinCommand::SetInitialPinCommand(const std::string &serialNumber)
0150     : CardCommand(new Private(this, serialNumber))
0151 {
0152     d->init();
0153 }
0154 
0155 SetInitialPinCommand::~SetInitialPinCommand()
0156 {
0157 }
0158 
0159 QDialog *SetInitialPinCommand::dialog()
0160 {
0161     d->ensureDialogCreated();
0162     return d->dialog;
0163 }
0164 
0165 void SetInitialPinCommand::doStart()
0166 {
0167     d->ensureDialogCreated();
0168 
0169     const auto nksCard = ReaderStatus::instance()->getCard<NetKeyCard>(d->serialNumber());
0170     if (!nksCard) {
0171         d->error(i18n("Failed to find the NetKey card with the serial number: %1", QString::fromStdString(d->serialNumber())));
0172         d->dialog->close();
0173         finished();
0174         return;
0175     }
0176 
0177     const std::vector<Card::PinState> pinStates = nksCard->pinStates();
0178     d->dialog->setNksPinPresent(pinStates.size() >= 1 && pinStates[0] != Card::NullPin);
0179     d->dialog->setSigGPinPresent(pinStates.size() >= 3 && pinStates[2] != Card::NullPin);
0180 
0181     d->ensureDialogVisible();
0182 }
0183 
0184 void SetInitialPinCommand::doCancel()
0185 {
0186     if (d->dialog) {
0187         d->dialog->close();
0188     }
0189 }
0190 
0191 #undef q_func
0192 #undef d_func
0193 
0194 #include "moc_setinitialpincommand.cpp"