keepassxc

Форк
0
/
YubiKeyEditWidget.cpp 
190 строк · 6.8 Кб
1
/*
2
 *  Copyright (C) 2018 KeePassXC Team <team@keepassxc.org>
3
 *
4
 *  This program is free software: you can redistribute it and/or modify
5
 *  it under the terms of the GNU General Public License as published by
6
 *  the Free Software Foundation, either version 2 or (at your option)
7
 *  version 3 of the License.
8
 *
9
 *  This program is distributed in the hope that it will be useful,
10
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 *  GNU General Public License for more details.
13
 *
14
 *  You should have received a copy of the GNU General Public License
15
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
 */
17

18
#include "YubiKeyEditWidget.h"
19

20
#include "ui_KeyComponentWidget.h"
21
#include "ui_YubiKeyEditWidget.h"
22

23
#include "core/AsyncTask.h"
24
#include "gui/Icons.h"
25
#include "keys/ChallengeResponseKey.h"
26
#include "keys/CompositeKey.h"
27
#ifdef WITH_XC_YUBIKEY
28
#include "keys/drivers/YubiKeyInterfaceUSB.h"
29
#endif
30

31
YubiKeyEditWidget::YubiKeyEditWidget(QWidget* parent)
32
    : KeyComponentWidget(parent)
33
    , m_compUi(new Ui::YubiKeyEditWidget())
34
#ifdef WITH_XC_YUBIKEY
35
    , m_deviceListener(new DeviceListener(this))
36
#endif
37
{
38
    initComponent();
39
#ifdef WITH_XC_YUBIKEY
40
    connect(YubiKey::instance(), SIGNAL(detectComplete(bool)), SLOT(hardwareKeyResponse(bool)), Qt::QueuedConnection);
41
    connect(m_deviceListener, &DeviceListener::devicePlugged, this, [&](bool, void*, void*) { pollYubikey(); });
42
#endif
43
}
44

45
YubiKeyEditWidget::~YubiKeyEditWidget() = default;
46

47
bool YubiKeyEditWidget::addToCompositeKey(QSharedPointer<CompositeKey> key)
48
{
49
    if (!m_isDetected || !m_compEditWidget) {
50
        return false;
51
    }
52

53
    int selectionIndex = m_compUi->comboChallengeResponse->currentIndex();
54
    auto slot = m_compUi->comboChallengeResponse->itemData(selectionIndex).value<YubiKeySlot>();
55
    key->addChallengeResponseKey(QSharedPointer<ChallengeResponseKey>::create(slot));
56
    return true;
57
}
58

59
bool YubiKeyEditWidget::validate(QString& errorMessage) const
60
{
61
    if (!m_isDetected) {
62
        errorMessage = tr("Could not find any hardware keys!");
63
        return false;
64
    }
65

66
    // Perform a test challenge response
67
    int selectionIndex = m_compUi->comboChallengeResponse->currentIndex();
68
    auto slot = m_compUi->comboChallengeResponse->itemData(selectionIndex).value<YubiKeySlot>();
69
    bool valid = AsyncTask::runAndWaitForFuture([&slot] { return YubiKey::instance()->testChallenge(slot); });
70
    if (!valid) {
71
        errorMessage = tr("Selected hardware key slot does not support challenge-response!");
72
    }
73
    return valid;
74
}
75

76
QWidget* YubiKeyEditWidget::componentEditWidget()
77
{
78
    m_compEditWidget = new QWidget();
79
    m_compUi->setupUi(m_compEditWidget);
80

81
    QSizePolicy sp = m_compUi->yubikeyProgress->sizePolicy();
82
    sp.setRetainSizeWhenHidden(true);
83
    m_compUi->yubikeyProgress->setSizePolicy(sp);
84
    m_compUi->yubikeyProgress->setVisible(false);
85

86
    return m_compEditWidget;
87
}
88

89
void YubiKeyEditWidget::showEvent(QShowEvent* event)
90
{
91
    KeyComponentWidget::showEvent(event);
92

93
#ifdef WITH_XC_YUBIKEY
94
#ifdef Q_OS_WIN
95
    m_deviceListener->registerHotplugCallback(true,
96
                                              true,
97
                                              YubiKeyInterfaceUSB::YUBICO_USB_VID,
98
                                              DeviceListener::MATCH_ANY,
99
                                              &DeviceListenerWin::DEV_CLS_KEYBOARD);
100
    m_deviceListener->registerHotplugCallback(true,
101
                                              true,
102
                                              YubiKeyInterfaceUSB::ONLYKEY_USB_VID,
103
                                              DeviceListener::MATCH_ANY,
104
                                              &DeviceListenerWin::DEV_CLS_KEYBOARD);
105
#else
106
    m_deviceListener->registerHotplugCallback(true, true, YubiKeyInterfaceUSB::YUBICO_USB_VID);
107
    m_deviceListener->registerHotplugCallback(true, true, YubiKeyInterfaceUSB::ONLYKEY_USB_VID);
108
#endif
109
#endif
110
}
111

112
void YubiKeyEditWidget::hideEvent(QHideEvent* event)
113
{
114
    KeyComponentWidget::hideEvent(event);
115
#ifdef WITH_XC_YUBIKEY
116
    m_deviceListener->deregisterAllHotplugCallbacks();
117
#endif
118
}
119

120
void YubiKeyEditWidget::initComponentEditWidget(QWidget* widget)
121
{
122
    Q_UNUSED(widget);
123
    Q_ASSERT(m_compEditWidget);
124
    m_compUi->comboChallengeResponse->setFocus();
125
    m_compUi->refreshHardwareKeys->setIcon(icons()->icon("yubikey-refresh", true));
126
    connect(m_compUi->refreshHardwareKeys, &QPushButton::clicked, this, &YubiKeyEditWidget::pollYubikey);
127
    pollYubikey();
128
}
129

130
void YubiKeyEditWidget::initComponent()
131
{
132
    // These need to be set in total for each credential type for translation purposes
133
    m_ui->groupBox->setTitle(tr("Challenge-Response"));
134
    m_ui->addButton->setText(tr("Add Challenge-Response"));
135
    m_ui->changeButton->setText(tr("Change Challenge-Response"));
136
    m_ui->removeButton->setText(tr("Remove Challenge-Response"));
137
    m_ui->changeOrRemoveLabel->setText(tr("Challenge-Response set, click to change or remove"));
138

139
    m_ui->componentDescription->setText(
140
        tr("<p>If you own a <a href=\"https://www.yubico.com/\">YubiKey</a> or "
141
           "<a href=\"https://onlykey.io\">OnlyKey</a>, you can use it for additional security.</p>"
142
           "<p>The key requires one of its slots to be programmed as "
143
           "<a href=\"https://docs.yubico.com/yesdk/users-manual/application-otp/challenge-response.html\">"
144
           "HMAC-SHA1 Challenge-Response</a>.</p>"));
145
}
146

147
void YubiKeyEditWidget::pollYubikey()
148
{
149
#ifdef WITH_XC_YUBIKEY
150
    if (!m_compEditWidget) {
151
        return;
152
    }
153

154
    m_isDetected = false;
155
    m_compUi->comboChallengeResponse->clear();
156
    m_compUi->comboChallengeResponse->addItem(tr("Detecting hardware keys…"));
157
    m_compUi->comboChallengeResponse->setEnabled(false);
158
    m_compUi->yubikeyProgress->setVisible(true);
159
    m_compUi->refreshHardwareKeys->setEnabled(false);
160

161
    YubiKey::instance()->findValidKeysAsync();
162
#endif
163
}
164

165
void YubiKeyEditWidget::hardwareKeyResponse(bool found)
166
{
167
    if (!m_compEditWidget) {
168
        return;
169
    }
170

171
    m_compUi->comboChallengeResponse->clear();
172
    m_compUi->refreshHardwareKeys->setEnabled(true);
173

174
    if (!found) {
175
        m_compUi->yubikeyProgress->setVisible(false);
176
        m_compUi->comboChallengeResponse->addItem(tr("No hardware keys detected"));
177
        m_isDetected = false;
178
        return;
179
    }
180

181
    const auto foundKeys = YubiKey::instance()->foundKeys();
182
    for (auto i = foundKeys.cbegin(); i != foundKeys.cend(); ++i) {
183
        // add detected YubiKey to combo box and encode blocking mode in LSB, slot number in second LSB
184
        m_compUi->comboChallengeResponse->addItem(i.value(), QVariant::fromValue(i.key()));
185
    }
186

187
    m_isDetected = true;
188
    m_compUi->yubikeyProgress->setVisible(false);
189
    m_compUi->comboChallengeResponse->setEnabled(true);
190
}
191

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.