changepincommand.cpp 5.09 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
/*  commands/changepincommand.cpp

    This file is part of Kleopatra, the KDE keymanager
    SPDX-FileCopyrightText: 2020 g10 Code GmbH
    SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>

    SPDX-License-Identifier: GPL-2.0-or-later
*/

#include "changepincommand.h"

#include "cardcommand_p.h"

14
#include "smartcard/openpgpcard.h"
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include "smartcard/pivcard.h"
#include "smartcard/readerstatus.h"

#include <KLocalizedString>

#include <gpgme++/error.h>

#include "kleopatra_debug.h"

using namespace Kleo;
using namespace Kleo::Commands;
using namespace Kleo::SmartCard;
using namespace GpgME;

class ChangePinCommand::Private : public CardCommand::Private
{
    friend class ::Kleo::Commands::ChangePinCommand;
    ChangePinCommand *q_func() const
    {
        return static_cast<ChangePinCommand *>(q);
    }
public:
37
    explicit Private(ChangePinCommand *qq, const std::string &serialNumber, const std::string &appName, QWidget *p);
38
39
40
41
42
43
44
45
46
47
48
    ~Private();

    void init();

private:
    void slotResult(const Error &err);

private:
    void changePin();

private:
49
    std::string appName;
50
    std::string keyRef;
51
    ChangePinMode mode = NormalMode;
52
53
54
55
56
57
58
59
60
61
62
63
64
65
};

ChangePinCommand::Private *ChangePinCommand::d_func()
{
    return static_cast<Private *>(d.get());
}
const ChangePinCommand::Private *ChangePinCommand::d_func() const
{
    return static_cast<const Private *>(d.get());
}

#define d d_func()
#define q q_func()

66
ChangePinCommand::Private::Private(ChangePinCommand *qq, const std::string &serialNumber, const std::string &appName_, QWidget *p)
67
    : CardCommand::Private(qq, serialNumber, p)
68
    , appName(appName_)
69
70
71
72
73
74
75
76
{
}

ChangePinCommand::Private::~Private()
{
    qCDebug(KLEOPATRA_LOG) << "ChangePinCommand::Private::~Private()";
}

77
78
ChangePinCommand::ChangePinCommand(const std::string &serialNumber, const std::string &appName, QWidget *p)
    : CardCommand(new Private(this, serialNumber, appName, p))
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
{
    d->init();
}

void ChangePinCommand::Private::init()
{
}

ChangePinCommand::~ChangePinCommand()
{
    qCDebug(KLEOPATRA_LOG) << "ChangePinCommand::~ChangePinCommand()";
}

void ChangePinCommand::setKeyRef(const std::string &keyRef)
{
    d->keyRef = keyRef;
}

97
98
99
100
101
102
void ChangePinCommand::setMode(ChangePinMode mode)
{
    d->mode = mode;
}


103
104
105
106
107
108
109
void ChangePinCommand::doStart()
{
    qCDebug(KLEOPATRA_LOG) << "ChangePinCommand::doStart()";

    d->changePin();
}

110
111
112
113
void ChangePinCommand::doCancel()
{
}

114
115
116
void ChangePinCommand::Private::changePin()
{
    qCDebug(KLEOPATRA_LOG) << "ChangePinCommand::changePin()";
117

118
    const auto card = SmartCard::ReaderStatus::instance()->getCard(serialNumber(), appName);
119
120
121
122
123
124
    if (!card) {
        error(i18n("Failed to find the smartcard with the serial number: %1", QString::fromStdString(serialNumber())));
        finished();
        return;
    }

125
126
    QByteArrayList command;
    command << "SCD PASSWD";
127
    if (mode == ResetMode) {
128
        command << "--reset";
129
    }
130
    command << QByteArray::fromStdString(keyRef);
131
    ReaderStatus::mutableInstance()->startSimpleTransaction(card, command.join(' '), q, "slotResult");
132
133
134
}

namespace {
135
static QString errorMessage(const std::string &keyRef, ChangePinCommand::ChangePinMode mode, const QString &errorText)
136
137
138
139
140
{
    // see cmd_passwd() in gpg-card.c
    if (keyRef == PIVCard::pukKeyRef()) {
        return i18nc("@info", "Changing the PUK failed: %1", errorText);
    }
141
142
143
    if (keyRef == OpenPGPCard::resetCodeKeyRef()) {
        return i18nc("@info", "Unblocking the PIN failed: %1", errorText);
    }
144
145
146
    if (keyRef == OpenPGPCard::adminPinKeyRef()) {
        return i18nc("@info", "Changing the Admin PIN failed: %1", errorText);
    }
147
    if (keyRef == OpenPGPCard::resetCodeKeyRef() && mode == ChangePinCommand::ResetMode) {
148
149
        return i18nc("@info", "Changing the Reset Code failed: %1", errorText);
    }
150
151
152
    return i18nc("@info", "Changing the PIN failed: %1", errorText);
}

153
static QString successMessage(const std::string &keyRef, ChangePinCommand::ChangePinMode mode)
154
155
156
157
158
{
    // see cmd_passwd() in gpg-card.c
    if (keyRef == PIVCard::pukKeyRef()) {
        return i18nc("@info", "PUK successfully changed.");
    }
159
160
161
    if (keyRef == OpenPGPCard::resetCodeKeyRef()) {
        return i18nc("@info", "Unblocked and set a new PIN successfully.");
    }
162
163
164
    if (keyRef == OpenPGPCard::adminPinKeyRef()) {
        return i18nc("@info", "Admin PIN changed successfully.");
    }
165
    if (keyRef == OpenPGPCard::resetCodeKeyRef() && mode == ChangePinCommand::ResetMode) {
166
167
        return i18nc("@info", "Reset Code changed successfully.");
    }
168
169
170
171
172
173
174
175
176
    return i18nc("@info", "PIN changed successfully.");
}
}

void ChangePinCommand::Private::slotResult(const GpgME::Error& err)
{
    qCDebug(KLEOPATRA_LOG) << "ChangePinCommand::slotResult():"
                           << err.asString() << "(" << err.code() << ")";
    if (err) {
177
        error(errorMessage(keyRef, mode, QString::fromLatin1(err.asString())),
178
179
              i18nc("@title", "Error"));
    } else if (!err.isCanceled()) {
180
        information(successMessage(keyRef, mode), i18nc("@title", "Success"));
181
182
183
184
185
186
187
188
189
        ReaderStatus::mutableInstance()->updateStatus();
    }
    finished();
}

#undef d
#undef q

#include "moc_changepincommand.cpp"