1 /* commands/changepincommand.cpp
2
3 This file is part of Kleopatra, the KDE keymanager
4 SPDX-FileCopyrightText: 2020 g10 Code GmbH
5 SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
6
7 SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
10 #include "changepincommand.h"
11
12 #include "cardcommand_p.h"
13
14 #include "smartcard/netkeycard.h"
15 #include "smartcard/openpgpcard.h"
16 #include "smartcard/pivcard.h"
17 #include "smartcard/readerstatus.h"
18
19 #include <KLocalizedString>
20
21 #include <gpgme++/error.h>
22
23 #include "kleopatra_debug.h"
24
25 using namespace Kleo;
26 using namespace Kleo::Commands;
27 using namespace Kleo::SmartCard;
28 using namespace GpgME;
29
30 class ChangePinCommand::Private : public CardCommand::Private
31 {
32 friend class ::Kleo::Commands::ChangePinCommand;
q_func() const33 ChangePinCommand *q_func() const
34 {
35 return static_cast<ChangePinCommand *>(q);
36 }
37 public:
38 explicit Private(ChangePinCommand *qq, const std::string &serialNumber, const std::string &appName, QWidget *p);
39 ~Private() override;
40
41 void init();
42
43 private:
44 void slotResult(const Error &err);
45
46 private:
47 void changePin();
48
49 private:
50 std::string appName;
51 std::string keyRef;
52 ChangePinMode mode = NormalMode;
53 };
54
d_func()55 ChangePinCommand::Private *ChangePinCommand::d_func()
56 {
57 return static_cast<Private *>(d.get());
58 }
d_func() const59 const ChangePinCommand::Private *ChangePinCommand::d_func() const
60 {
61 return static_cast<const Private *>(d.get());
62 }
63
64 #define d d_func()
65 #define q q_func()
66
Private(ChangePinCommand * qq,const std::string & serialNumber,const std::string & appName_,QWidget * p)67 ChangePinCommand::Private::Private(ChangePinCommand *qq, const std::string &serialNumber, const std::string &appName_, QWidget *p)
68 : CardCommand::Private(qq, serialNumber, p)
69 , appName(appName_)
70 {
71 }
72
~Private()73 ChangePinCommand::Private::~Private()
74 {
75 qCDebug(KLEOPATRA_LOG) << "ChangePinCommand::Private::~Private()";
76 }
77
ChangePinCommand(const std::string & serialNumber,const std::string & appName,QWidget * p)78 ChangePinCommand::ChangePinCommand(const std::string &serialNumber, const std::string &appName, QWidget *p)
79 : CardCommand(new Private(this, serialNumber, appName, p))
80 {
81 d->init();
82 }
83
init()84 void ChangePinCommand::Private::init()
85 {
86 }
87
~ChangePinCommand()88 ChangePinCommand::~ChangePinCommand()
89 {
90 qCDebug(KLEOPATRA_LOG) << "ChangePinCommand::~ChangePinCommand()";
91 }
92
setKeyRef(const std::string & keyRef)93 void ChangePinCommand::setKeyRef(const std::string &keyRef)
94 {
95 d->keyRef = keyRef;
96 }
97
setMode(ChangePinMode mode)98 void ChangePinCommand::setMode(ChangePinMode mode)
99 {
100 d->mode = mode;
101 }
102
103
doStart()104 void ChangePinCommand::doStart()
105 {
106 qCDebug(KLEOPATRA_LOG) << "ChangePinCommand::doStart()";
107
108 d->changePin();
109 }
110
doCancel()111 void ChangePinCommand::doCancel()
112 {
113 }
114
changePin()115 void ChangePinCommand::Private::changePin()
116 {
117 qCDebug(KLEOPATRA_LOG) << "ChangePinCommand::changePin()";
118
119 const auto card = SmartCard::ReaderStatus::instance()->getCard(serialNumber(), appName);
120 if (!card) {
121 error(i18n("Failed to find the smartcard with the serial number: %1", QString::fromStdString(serialNumber())));
122 finished();
123 return;
124 }
125
126 QByteArrayList command;
127 command << "SCD PASSWD";
128 if (mode == ResetMode) {
129 command << "--reset";
130 } else if (mode == NullPinMode) {
131 command << "--nullpin";
132 }
133 command << QByteArray::fromStdString(keyRef);
134 ReaderStatus::mutableInstance()->startSimpleTransaction(card, command.join(' '), q, "slotResult");
135 }
136
137 namespace {
errorMessage(const std::string & keyRef,ChangePinCommand::ChangePinMode mode,const QString & errorText)138 static QString errorMessage(const std::string &keyRef, ChangePinCommand::ChangePinMode mode, const QString &errorText)
139 {
140 // see cmd_passwd() in gpg-card.c
141 if (keyRef == PIVCard::pukKeyRef()) {
142 return i18nc("@info", "Changing the PUK failed: %1", errorText);
143 }
144 if (keyRef == OpenPGPCard::resetCodeKeyRef()) {
145 return i18nc("@info", "Unblocking the PIN failed: %1", errorText);
146 }
147 if (keyRef == OpenPGPCard::adminPinKeyRef()) {
148 return i18nc("@info", "Changing the Admin PIN failed: %1", errorText);
149 }
150 if (keyRef == OpenPGPCard::resetCodeKeyRef() && mode == ChangePinCommand::ResetMode) {
151 return i18nc("@info", "Changing the Reset Code failed: %1", errorText);
152 }
153 if (keyRef == NetKeyCard::nksPinKeyRef()) {
154 if (mode == ChangePinCommand::NullPinMode) {
155 return i18nc("@info", "Setting the NKS PIN failed: %1", errorText);
156 } else {
157 return i18nc("@info", "Changing the NKS PIN failed: %1", errorText);
158 }
159 }
160 if (keyRef == NetKeyCard::sigGPinKeyRef()) {
161 if (mode == ChangePinCommand::NullPinMode) {
162 return i18nc("@info", "Setting the SigG PIN failed: %1", errorText);
163 } else {
164 return i18nc("@info", "Changing the SigG PIN failed: %1", errorText);
165 }
166 }
167 return i18nc("@info", "Changing the PIN failed: %1", errorText);
168 }
169
successMessage(const std::string & keyRef,ChangePinCommand::ChangePinMode mode)170 static QString successMessage(const std::string &keyRef, ChangePinCommand::ChangePinMode mode)
171 {
172 // see cmd_passwd() in gpg-card.c
173 if (keyRef == PIVCard::pukKeyRef()) {
174 return i18nc("@info", "PUK successfully changed.");
175 }
176 if (keyRef == OpenPGPCard::resetCodeKeyRef()) {
177 return i18nc("@info", "Unblocked and set a new PIN successfully.");
178 }
179 if (keyRef == OpenPGPCard::adminPinKeyRef()) {
180 return i18nc("@info", "Admin PIN changed successfully.");
181 }
182 if (keyRef == OpenPGPCard::resetCodeKeyRef() && mode == ChangePinCommand::ResetMode) {
183 return i18nc("@info", "Reset Code changed successfully.");
184 }
185 if (keyRef == NetKeyCard::nksPinKeyRef()) {
186 if (mode == ChangePinCommand::NullPinMode) {
187 return i18nc("@info", "NKS PIN set successfully.");
188 } else {
189 return i18nc("@info", "NKS PIN changed successfully.");
190 }
191 }
192 if (keyRef == NetKeyCard::sigGPinKeyRef()) {
193 if (mode == ChangePinCommand::NullPinMode) {
194 return i18nc("@info", "SigG PIN set successfully.");
195 } else {
196 return i18nc("@info", "SigG PIN changed successfully.");
197 }
198 }
199 return i18nc("@info", "PIN changed successfully.");
200 }
201 }
202
slotResult(const GpgME::Error & err)203 void ChangePinCommand::Private::slotResult(const GpgME::Error& err)
204 {
205 qCDebug(KLEOPATRA_LOG) << "ChangePinCommand::slotResult():"
206 << err.asString() << "(" << err.code() << ")";
207 if (err) {
208 error(errorMessage(keyRef, mode, QString::fromLatin1(err.asString())),
209 i18nc("@title", "Error"));
210 } else if (!err.isCanceled()) {
211 information(successMessage(keyRef, mode), i18nc("@title", "Success"));
212 ReaderStatus::mutableInstance()->updateStatus();
213 }
214 finished();
215 }
216
217 #undef d
218 #undef q
219
220 #include "moc_changepincommand.cpp"
221