diff options
Diffstat (limited to 'src/gui/databasekey/YubiKeyEditWidget.cpp')
-rw-r--r-- | src/gui/databasekey/YubiKeyEditWidget.cpp | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/src/gui/databasekey/YubiKeyEditWidget.cpp b/src/gui/databasekey/YubiKeyEditWidget.cpp new file mode 100644 index 000000000..855bd7099 --- /dev/null +++ b/src/gui/databasekey/YubiKeyEditWidget.cpp @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2018 KeePassXC Team <team@keepassxc.org> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "YubiKeyEditWidget.h" +#include "ui_YubiKeyEditWidget.h" + +#include "config-keepassx.h" +#include "core/AsyncTask.h" +#include "gui/MainWindow.h" +#include "gui/MessageBox.h" +#include "keys/CompositeKey.h" +#include "keys/YkChallengeResponseKey.h" + +YubiKeyEditWidget::YubiKeyEditWidget(QWidget* parent) + : KeyComponentWidget(parent) + , m_compUi(new Ui::YubiKeyEditWidget()) +{ + setComponentName(tr("YubiKey Challenge-Response")); + setComponentDescription( + tr("<p>If you own a <a href=\"https://www.yubico.com/\">YubiKey</a>, you can use it " + "for additional security.</p><p>The YubiKey requires one of its slots to be programmed as " + "<a href=\"https://www.yubico.com/products/services-software/personalization-tools/challenge-response/\">" + "HMAC-SHA1 Challenge-Response</a>.</p>")); + + connect(YubiKey::instance(), SIGNAL(detectComplete(bool)), SLOT(hardwareKeyResponse(bool)), Qt::QueuedConnection); +} + +YubiKeyEditWidget::~YubiKeyEditWidget() +{ +} + +bool YubiKeyEditWidget::addToCompositeKey(QSharedPointer<CompositeKey> key) +{ + if (!m_isDetected || !m_compEditWidget) { + return false; + } + + int selectionIndex = m_compUi->comboChallengeResponse->currentIndex(); + auto slot = m_compUi->comboChallengeResponse->itemData(selectionIndex).value<YubiKeySlot>(); + key->addChallengeResponseKey(QSharedPointer<YkChallengeResponseKey>::create(slot)); + return true; +} + +bool YubiKeyEditWidget::validate(QString& errorMessage) const +{ + if (!m_isDetected) { + errorMessage = tr("Could not find any hardware keys!"); + return false; + } + + // Perform a test challenge response + int selectionIndex = m_compUi->comboChallengeResponse->currentIndex(); + auto slot = m_compUi->comboChallengeResponse->itemData(selectionIndex).value<YubiKeySlot>(); + bool valid = AsyncTask::runAndWaitForFuture([&slot] { return YubiKey::instance()->testChallenge(slot); }); + if (!valid) { + errorMessage = tr("Selected hardware key slot does not support challenge-response!"); + } + return valid; +} + +QWidget* YubiKeyEditWidget::componentEditWidget() +{ + m_compEditWidget = new QWidget(); + m_compUi->setupUi(m_compEditWidget); + + QSizePolicy sp = m_compUi->yubikeyProgress->sizePolicy(); + sp.setRetainSizeWhenHidden(true); + m_compUi->yubikeyProgress->setSizePolicy(sp); + m_compUi->yubikeyProgress->setVisible(false); + +#ifdef WITH_XC_YUBIKEY + connect(m_compUi->buttonRedetectYubikey, SIGNAL(clicked()), SLOT(pollYubikey())); + pollYubikey(); +#endif + + return m_compEditWidget; +} + +void YubiKeyEditWidget::initComponentEditWidget(QWidget* widget) +{ + Q_UNUSED(widget); + Q_ASSERT(m_compEditWidget); + m_compUi->comboChallengeResponse->setFocus(); +} + +void YubiKeyEditWidget::pollYubikey() +{ +#ifdef WITH_XC_YUBIKEY + if (!m_compEditWidget) { + return; + } + + m_isDetected = false; + m_compUi->comboChallengeResponse->clear(); + m_compUi->comboChallengeResponse->addItem(tr("Detecting hardware keys…")); + m_compUi->buttonRedetectYubikey->setEnabled(false); + m_compUi->comboChallengeResponse->setEnabled(false); + m_compUi->yubikeyProgress->setVisible(true); + + YubiKey::instance()->findValidKeys(); +#endif +} + +void YubiKeyEditWidget::hardwareKeyResponse(bool found) +{ + if (!m_compEditWidget) { + return; + } + + m_compUi->comboChallengeResponse->clear(); + m_compUi->buttonRedetectYubikey->setEnabled(true); + m_compUi->yubikeyProgress->setVisible(false); + + if (!found) { + m_compUi->comboChallengeResponse->addItem(tr("No hardware keys detected")); + m_isDetected = false; + return; + } + + for (auto& slot : YubiKey::instance()->foundKeys()) { + // add detected YubiKey to combo box and encode blocking mode in LSB, slot number in second LSB + m_compUi->comboChallengeResponse->addItem(YubiKey::instance()->getDisplayName(slot), QVariant::fromValue(slot)); + } + + m_isDetected = true; + m_compUi->comboChallengeResponse->setEnabled(true); +} |