File indexing completed on 2024-06-23 05:13:45
0001 /* commands/setpivcardapplicationadministrationkeycommand.cpp 0002 0003 This file is part of Kleopatra, the KDE keymanager 0004 SPDX-FileCopyrightText: 2020 g10 Code GmbH 0005 SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 0010 #include "setpivcardapplicationadministrationkeycommand.h" 0011 0012 #include "cardcommand_p.h" 0013 0014 #include "smartcard/pivcard.h" 0015 #include "smartcard/readerstatus.h" 0016 0017 #include "commands/authenticatepivcardapplicationcommand.h" 0018 0019 #include "dialogs/pivcardapplicationadministrationkeyinputdialog.h" 0020 0021 #include <Libkleo/Formatting> 0022 0023 #include <KLocalizedString> 0024 0025 #include <gpgme++/error.h> 0026 0027 #include "kleopatra_debug.h" 0028 0029 using namespace Kleo; 0030 using namespace Kleo::Commands; 0031 using namespace Kleo::Dialogs; 0032 using namespace Kleo::SmartCard; 0033 using namespace GpgME; 0034 0035 class SetPIVCardApplicationAdministrationKeyCommand::Private : public CardCommand::Private 0036 { 0037 friend class ::Kleo::Commands::SetPIVCardApplicationAdministrationKeyCommand; 0038 SetPIVCardApplicationAdministrationKeyCommand *q_func() const 0039 { 0040 return static_cast<SetPIVCardApplicationAdministrationKeyCommand *>(q); 0041 } 0042 0043 public: 0044 explicit Private(SetPIVCardApplicationAdministrationKeyCommand *qq, const std::string &serialNumber, QWidget *p); 0045 ~Private() override; 0046 0047 void init(); 0048 0049 private: 0050 void slotDialogAccepted(); 0051 void slotDialogRejected(); 0052 void slotResult(const Error &err); 0053 0054 private: 0055 void authenticate(); 0056 void authenticationFinished(); 0057 void authenticationCanceled(); 0058 void setAdminKey(); 0059 void ensureDialogCreated(); 0060 0061 private: 0062 QByteArray newAdminKey; 0063 QPointer<PIVCardApplicationAdministrationKeyInputDialog> dialog; 0064 bool hasBeenCanceled = false; 0065 }; 0066 0067 SetPIVCardApplicationAdministrationKeyCommand::Private *SetPIVCardApplicationAdministrationKeyCommand::d_func() 0068 { 0069 return static_cast<Private *>(d.get()); 0070 } 0071 const SetPIVCardApplicationAdministrationKeyCommand::Private *SetPIVCardApplicationAdministrationKeyCommand::d_func() const 0072 { 0073 return static_cast<const Private *>(d.get()); 0074 } 0075 0076 #define d d_func() 0077 #define q q_func() 0078 0079 SetPIVCardApplicationAdministrationKeyCommand::Private::Private(SetPIVCardApplicationAdministrationKeyCommand *qq, const std::string &serialNumber, QWidget *p) 0080 : CardCommand::Private(qq, serialNumber, p) 0081 , dialog() 0082 { 0083 } 0084 0085 SetPIVCardApplicationAdministrationKeyCommand::Private::~Private() 0086 { 0087 qCDebug(KLEOPATRA_LOG) << "SetPIVCardApplicationAdministrationKeyCommand::Private::~Private()"; 0088 } 0089 0090 SetPIVCardApplicationAdministrationKeyCommand::SetPIVCardApplicationAdministrationKeyCommand(const std::string &serialNumber, QWidget *p) 0091 : CardCommand(new Private(this, serialNumber, p)) 0092 { 0093 d->init(); 0094 } 0095 0096 void SetPIVCardApplicationAdministrationKeyCommand::Private::init() 0097 { 0098 } 0099 0100 SetPIVCardApplicationAdministrationKeyCommand::~SetPIVCardApplicationAdministrationKeyCommand() 0101 { 0102 qCDebug(KLEOPATRA_LOG) << "SetPIVCardApplicationAdministrationKeyCommand::~SetPIVCardApplicationAdministrationKeyCommand()"; 0103 } 0104 0105 void SetPIVCardApplicationAdministrationKeyCommand::doStart() 0106 { 0107 qCDebug(KLEOPATRA_LOG) << "SetPIVCardApplicationAdministrationKeyCommand::doStart()"; 0108 0109 d->authenticate(); 0110 } 0111 0112 void SetPIVCardApplicationAdministrationKeyCommand::doCancel() 0113 { 0114 } 0115 0116 void SetPIVCardApplicationAdministrationKeyCommand::Private::authenticate() 0117 { 0118 qCDebug(KLEOPATRA_LOG) << "SetPIVCardApplicationAdministrationKeyCommand::authenticate()"; 0119 0120 auto cmd = new AuthenticatePIVCardApplicationCommand(serialNumber(), parentWidgetOrView()); 0121 cmd->setAutoResetCardToOpenPGP(false); 0122 cmd->setPrompt(i18n("Please enter the old PIV Card Application Administration Key in hex-encoded form.")); 0123 connect(cmd, &AuthenticatePIVCardApplicationCommand::finished, q, [this]() { 0124 authenticationFinished(); 0125 }); 0126 connect(cmd, &AuthenticatePIVCardApplicationCommand::canceled, q, [this]() { 0127 authenticationCanceled(); 0128 }); 0129 cmd->start(); 0130 } 0131 0132 void SetPIVCardApplicationAdministrationKeyCommand::Private::authenticationFinished() 0133 { 0134 qCDebug(KLEOPATRA_LOG) << "SetPIVCardApplicationAdministrationKeyCommand::authenticationFinished()"; 0135 if (!hasBeenCanceled) { 0136 setAdminKey(); 0137 } 0138 } 0139 0140 void SetPIVCardApplicationAdministrationKeyCommand::Private::authenticationCanceled() 0141 { 0142 qCDebug(KLEOPATRA_LOG) << "SetPIVCardApplicationAdministrationKeyCommand::authenticationCanceled()"; 0143 hasBeenCanceled = true; 0144 canceled(); 0145 } 0146 0147 void SetPIVCardApplicationAdministrationKeyCommand::Private::setAdminKey() 0148 { 0149 qCDebug(KLEOPATRA_LOG) << "SetPIVCardApplicationAdministrationKeyCommand::setAdminKey()"; 0150 0151 ensureDialogCreated(); 0152 Q_ASSERT(dialog); 0153 dialog->show(); 0154 } 0155 0156 void SetPIVCardApplicationAdministrationKeyCommand::Private::ensureDialogCreated() 0157 { 0158 if (dialog) { 0159 return; 0160 } 0161 0162 dialog = new PIVCardApplicationAdministrationKeyInputDialog(parentWidgetOrView()); 0163 dialog->setAttribute(Qt::WA_DeleteOnClose); 0164 dialog->setLabelText(newAdminKey.isEmpty() ? i18n("Please enter the new PIV Card Application Administration Key in hex-encoded form. " 0165 "The key needs to consist of 24 bytes, i.e. 48 hex-characters.") 0166 : i18n("Please enter the new PIV Card Application Administration Key again.")); 0167 0168 connect(dialog, &QDialog::accepted, q, [this]() { 0169 slotDialogAccepted(); 0170 }); 0171 connect(dialog, &QDialog::rejected, q, [this]() { 0172 slotDialogRejected(); 0173 }); 0174 } 0175 0176 void SetPIVCardApplicationAdministrationKeyCommand::Private::slotDialogAccepted() 0177 { 0178 if (newAdminKey.isEmpty()) { 0179 newAdminKey = dialog->adminKey(); 0180 dialog = nullptr; 0181 setAdminKey(); 0182 return; 0183 } 0184 0185 const QByteArray newAdminKey2 = dialog->adminKey(); 0186 if (newAdminKey != newAdminKey2) { 0187 error(i18nc("@info", "The two keys you have entered do not match. Please retry.")); 0188 newAdminKey.clear(); 0189 dialog = nullptr; 0190 setAdminKey(); 0191 return; 0192 } 0193 0194 auto pivCard = ReaderStatus::instance()->getCard<PIVCard>(serialNumber()); 0195 if (!pivCard) { 0196 error(i18n("Failed to find the PIV card with the serial number: %1", QString::fromStdString(serialNumber()))); 0197 finished(); 0198 return; 0199 } 0200 0201 const QByteArray plusPercentEncodedAdminKey = newAdminKey.toPercentEncoding().replace(' ', '+'); 0202 const QByteArray command = QByteArray("SCD SETATTR SET-ADM-KEY ") + plusPercentEncodedAdminKey; 0203 ReaderStatus::mutableInstance()->startSimpleTransaction(pivCard, command, q, [this](const GpgME::Error &err) { 0204 slotResult(err); 0205 }); 0206 } 0207 0208 void SetPIVCardApplicationAdministrationKeyCommand::Private::slotDialogRejected() 0209 { 0210 finished(); 0211 } 0212 0213 void SetPIVCardApplicationAdministrationKeyCommand::Private::slotResult(const GpgME::Error &err) 0214 { 0215 qCDebug(KLEOPATRA_LOG) << "SetPIVCardApplicationAdministrationKeyCommand::slotResult():" << Formatting::errorAsString(err) << "(" << err.code() << ")"; 0216 if (err) { 0217 error(i18nc("@info", "Setting the PIV Card Application Administration Key failed: %1", Formatting::errorAsString(err))); 0218 } else if (!err.isCanceled()) { 0219 success(i18nc("@info", "PIV Card Application Administration Key set successfully.")); 0220 ReaderStatus::mutableInstance()->updateStatus(); 0221 } 0222 finished(); 0223 } 0224 0225 #undef d 0226 #undef q 0227 0228 #include "moc_setpivcardapplicationadministrationkeycommand.cpp"