From 912c51e025b00a6f8085ae5f865cd0f13435161b Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Thu, 30 Sep 2021 22:13:55 -0400 Subject: [PATCH] Some more cleanup --- share/translations/keepassxc_en.ts | 137 +++++++++++++++------- src/cli/Utils.cpp | 2 +- src/gui/DatabaseOpenWidget.cpp | 5 +- src/gui/MainWindow.cpp | 6 +- src/keys/drivers/YubiKey.cpp | 21 +--- src/keys/drivers/YubiKeyInterface.cpp | 8 +- src/keys/drivers/YubiKeyInterface.h | 13 +- src/keys/drivers/YubiKeyInterfacePCSC.cpp | 12 +- src/keys/drivers/YubiKeyInterfacePCSC.h | 1 + src/keys/drivers/YubiKeyInterfaceUSB.cpp | 5 +- src/keys/drivers/YubiKeyInterfaceUSB.h | 1 + 11 files changed, 123 insertions(+), 88 deletions(-) diff --git a/share/translations/keepassxc_en.ts b/share/translations/keepassxc_en.ts index d7fc4b5456..b505dc9303 100644 --- a/share/translations/keepassxc_en.ts +++ b/share/translations/keepassxc_en.ts @@ -1442,10 +1442,6 @@ If you do not have a key file, please leave the field empty. Key file to unlock the database - - Please touch the button on your YubiKey! - Please touch the button on your YubiKey! - Detecting hardware keys… @@ -1479,6 +1475,10 @@ If you do not have a key file, please leave the field empty. You are using an old key file format which KeePassXC may<br>stop supporting in the future.<br><br>Please consider generating a new key file by going to:<br><strong>Database &gt; Database Security &gt; Change Key File.</strong><br> + + Please present or touch your YubiKey to continue… + + DatabaseSettingWidgetMetaData @@ -4755,10 +4755,6 @@ Are you sure you want to continue with this file? Quit KeePassXC Quit KeePassXC - - Please touch the button on your YubiKey! - Please touch the button on your YubiKey! - &Donate &Donate @@ -5119,6 +5115,10 @@ Expect some bugs and minor issues, this version is meant for testing purposes. + + Please present or touch your YubiKey to continue… + + ManageDatabase @@ -6889,10 +6889,6 @@ Kernel: %3 %4 Invalid YubiKey serial %1 - - Please touch the button on your YubiKey to continue… - - Do you want to create a database with an empty password? [y/N]: @@ -7233,6 +7229,10 @@ Please consider generating a new key file. Warning: Failed to prevent screenshots on a top level window! + + Please present or touch your YubiKey to continue… + + QtIOCompressor @@ -8268,104 +8268,157 @@ Example: JBSWY3DPEHPK3PXP YubiKey - %1 [%2] Configured Slot - %3 + %1 No interface, slot %2 - %1 Invalid slot specified - %2 + General: - The YubiKey interface has not been initialized. + Could not find interface for hardware key with serial number %1. Please connect it to continue. + + + YubiKeyEditWidget - Hardware key is currently in use. + Refresh + Refresh + + + Refresh hardware tokens - Could not find hardware key with serial number %1. Please plug it in to continue. + Hardware key slot selection - Hardware key timed out waiting for user interaction. + Could not find any hardware keys! - Failed to complete a challenge-response, the specific error was: %1 + Selected hardware key slot does not support challenge-response! - %1 [%2] Challenge-Response - Slot %3 - %4 + Detecting hardware keys… - Press - Challenge-Response Key interaction request - Press + No hardware keys detected + - Passive - Challenge-Response Key no interaction required - Passive + Challenge-Response + - A USB error occurred when accessing the hardware key: %1 + Add Challenge-Response + + + + Change Challenge-Response + + + + Remove Challenge-Response + + + + Challenge-Response set, click to change or remove + + + + <p>If you own a <a href="https://www.yubico.com/">YubiKey</a> or <a href="https://onlykey.io">OnlyKey</a>, you can use it for additional security.</p><p>The key requires one of its slots to be programmed as <a href="https://www.yubico.com/products/services-software/challenge-response/">HMAC-SHA1 Challenge-Response</a>.</p> - YubiKeyEditWidget + YubiKeyInterface - Refresh - Refresh + %1 Invalid slot specified - %2 + + + + YubiKeyInterfacePCSC - Refresh hardware tokens + (PCSC) %1 [%2] Challenge-Response - Slot %3 - Hardware key slot selection + The YubiKey PCSC interface has not been initialized. - Could not find any hardware keys! + Hardware key is currently in use. - Selected hardware key slot does not support challenge-response! + Could not find or access hardware key with serial number %1. Please present it to continue. - Detecting hardware keys… + Hardware key is locked or timed out. Unlock or re-present it to continue. - No hardware keys detected + Hardware key was not found or is misconfigured. - Challenge-Response + Failed to complete a challenge-response, the PCSC error code was: %1 + + + YubiKeyInterfaceUSB - Add Challenge-Response + Unknown + Unknown + + + (USB) %1 [%2] Configured Slot - %3 - Change Challenge-Response + (USB) %1 [%2] Challenge-Response - Slot %3 - %4 - Remove Challenge-Response + Press + USB Challenge-Response Key interaction request + Press + + + Passive + USB Challenge-Response Key no interaction required + Passive + + + The YubiKey USB interface has not been initialized. - Challenge-Response set, click to change or remove + Hardware key is currently in use. - <p>If you own a <a href="https://www.yubico.com/">YubiKey</a> or <a href="https://onlykey.io">OnlyKey</a>, you can use it for additional security.</p><p>The key requires one of its slots to be programmed as <a href="https://www.yubico.com/products/services-software/challenge-response/">HMAC-SHA1 Challenge-Response</a>.</p> + Could not find hardware key with serial number %1. Please plug it in to continue. + + + + Hardware key timed out waiting for user interaction. + + + + A USB error occurred when accessing the hardware key: %1 + + + + Failed to complete a challenge-response, the specific error was: %1 diff --git a/src/cli/Utils.cpp b/src/cli/Utils.cpp index a27c293c1a..69c8437236 100644 --- a/src/cli/Utils.cpp +++ b/src/cli/Utils.cpp @@ -168,7 +168,7 @@ namespace Utils } auto conn = QObject::connect(YubiKey::instance(), &YubiKey::userInteractionRequest, [&] { - err << QObject::tr("Please interface with your YubiKey to continue…") << "\n\n" << flush; + err << QObject::tr("Please present or touch your YubiKey to continue…") << "\n\n" << flush; }); auto key = QSharedPointer(new ChallengeResponseKey({serial, slot})); diff --git a/src/gui/DatabaseOpenWidget.cpp b/src/gui/DatabaseOpenWidget.cpp index 3b810ed190..43e529551e 100644 --- a/src/gui/DatabaseOpenWidget.cpp +++ b/src/gui/DatabaseOpenWidget.cpp @@ -84,8 +84,9 @@ DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent) connect(YubiKey::instance(), &YubiKey::userInteractionRequest, this, [this] { // Show the press notification if we are in an independent window (e.g., DatabaseOpenDialog) if (window() != getMainWindow()) { - m_ui->messageWidget->showMessage( - tr("Please interface with your YubiKey!"), MessageWidget::Information, MessageWidget::DisableAutoHide); + m_ui->messageWidget->showMessage(tr("Please present or touch your YubiKey to continue…"), + MessageWidget::Information, + MessageWidget::DisableAutoHide); } }); connect(YubiKey::instance(), &YubiKey::challengeCompleted, this, [this] { m_ui->messageWidget->hide(); }); diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 033de2f6a5..a7cfe075eb 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -1708,8 +1708,10 @@ void MainWindow::hideGlobalMessage() void MainWindow::showYubiKeyPopup() { - displayGlobalMessage( - tr("Please interface with your YubiKey!"), MessageWidget::Information, false, MessageWidget::DisableAutoHide); + displayGlobalMessage(tr("Please present or touch your YubiKey to continue…"), + MessageWidget::Information, + false, + MessageWidget::DisableAutoHide); setEnabled(false); } diff --git a/src/keys/drivers/YubiKey.cpp b/src/keys/drivers/YubiKey.cpp index 58f3129cb1..be90b461dd 100644 --- a/src/keys/drivers/YubiKey.cpp +++ b/src/keys/drivers/YubiKey.cpp @@ -97,32 +97,23 @@ QList YubiKey::foundKeys() QList foundKeys; auto keys = YubiKeyInterfaceUSB::instance()->foundKeys(); - QList handledSerials; - for (auto serial : keys.keys()) { - // This check is needed to prevent duplicate keys - // when more than one slot is configured - if(handledSerials.contains(serial)) { - continue; - } - + QList handledSerials = keys.uniqueKeys(); + for (auto serial : handledSerials) { for (const auto& key : keys.values(serial)) { - foundKeys.append({serial, key.slot}); + foundKeys.append({serial, key.first}); } - handledSerials.append(serial); } keys = YubiKeyInterfacePCSC::instance()->foundKeys(); - for (auto serial : keys.keys()) { + for (auto serial : keys.uniqueKeys()) { // Ignore keys that were detected on USB interface already - // This also prevents duplicate keys (see above) - if(handledSerials.contains(serial)) { + if (handledSerials.contains(serial)) { continue; } for (const auto& key : keys.values(serial)) { - foundKeys.append({serial, key.slot}); + foundKeys.append({serial, key.first}); } - handledSerials.append(serial); } return foundKeys; diff --git a/src/keys/drivers/YubiKeyInterface.cpp b/src/keys/drivers/YubiKeyInterface.cpp index 8e4323b007..1164c12640 100644 --- a/src/keys/drivers/YubiKeyInterface.cpp +++ b/src/keys/drivers/YubiKeyInterface.cpp @@ -30,7 +30,7 @@ bool YubiKeyInterface::isInitialized() const return m_initialized; } -QMultiHash YubiKeyInterface::foundKeys() +QMultiMap> YubiKeyInterface::foundKeys() { return m_foundKeys; } @@ -38,7 +38,7 @@ QMultiHash YubiKeyInterface::foundKeys( bool YubiKeyInterface::hasFoundKey(YubiKeySlot slot) { for (const auto& key : m_foundKeys.values(slot.first)) { - if (slot.second == key.slot) { + if (slot.second == key.first) { return true; } } @@ -48,8 +48,8 @@ bool YubiKeyInterface::hasFoundKey(YubiKeySlot slot) QString YubiKeyInterface::getDisplayName(YubiKeySlot slot) { for (const auto& key : m_foundKeys.values(slot.first)) { - if (slot.second == key.slot) { - return key.desc; + if (slot.second == key.first) { + return key.second; } } return tr("%1 Invalid slot specified - %2").arg(QString::number(slot.first), QString::number(slot.second)); diff --git a/src/keys/drivers/YubiKeyInterface.h b/src/keys/drivers/YubiKeyInterface.h index d1053f21a9..e87c3e9f17 100644 --- a/src/keys/drivers/YubiKeyInterface.h +++ b/src/keys/drivers/YubiKeyInterface.h @@ -21,7 +21,7 @@ #include "YubiKey.h" -#include +#include /** * Abstract base class to manage the interfaces to hardware key(s) @@ -31,15 +31,8 @@ class YubiKeyInterface : public QObject Q_OBJECT public: - struct KeyData - { - unsigned int serial; - int slot; - QString desc; - }; - bool isInitialized() const; - QMultiHash foundKeys(); + QMultiMap> foundKeys(); bool hasFoundKey(YubiKeySlot slot); QString getDisplayName(YubiKeySlot slot); @@ -75,7 +68,7 @@ class YubiKeyInterface : public QObject Botan::secure_vector& response) = 0; virtual bool performTestChallenge(void* key, int slot, bool* wouldBlock) = 0; - QMultiHash m_foundKeys; + QMultiMap> m_foundKeys; QMutex m_mutex; QTimer m_interactionTimer; diff --git a/src/keys/drivers/YubiKeyInterfacePCSC.cpp b/src/keys/drivers/YubiKeyInterfacePCSC.cpp index 81294b7d44..1904953f54 100644 --- a/src/keys/drivers/YubiKeyInterfacePCSC.cpp +++ b/src/keys/drivers/YubiKeyInterfacePCSC.cpp @@ -624,17 +624,11 @@ void YubiKeyInterfacePCSC::findValidKeys() Due to this, the key is unlocked and we display it as such. When the key times out in the time between the key listing and the database unlock /save, an intercation request will be displayed. */ - QList> ykSlots; for (int slot = 1; slot <= 2; ++slot) { if (performTestChallenge(&satr, slot, &wouldBlock)) { - auto display = - tr("(PCSC) %1 [%2] Challenge-Response - Slot %3 - %4") - .arg(name, - QString::number(serial), - QString::number(slot), - tr("Present", - "PCSC Challenge-Response Key presentation to reader required")); - m_foundKeys.insert(serial, {serial, slot, display}); + auto display = tr("(PCSC) %1 [%2] Challenge-Response - Slot %3") + .arg(name, QString::number(serial), QString::number(slot)); + m_foundKeys.insert(serial, {slot, display}); } } } diff --git a/src/keys/drivers/YubiKeyInterfacePCSC.h b/src/keys/drivers/YubiKeyInterfacePCSC.h index 05ce74712b..56f7c3e5e5 100644 --- a/src/keys/drivers/YubiKeyInterfacePCSC.h +++ b/src/keys/drivers/YubiKeyInterfacePCSC.h @@ -45,6 +45,7 @@ typedef QPair SCardAID; */ class YubiKeyInterfacePCSC : public YubiKeyInterface { + Q_OBJECT public: static YubiKeyInterfacePCSC* instance(); diff --git a/src/keys/drivers/YubiKeyInterfaceUSB.cpp b/src/keys/drivers/YubiKeyInterfaceUSB.cpp index cb04a5544c..264caf2bca 100644 --- a/src/keys/drivers/YubiKeyInterfaceUSB.cpp +++ b/src/keys/drivers/YubiKeyInterfaceUSB.cpp @@ -150,7 +150,6 @@ void YubiKeyInterfaceUSB::findValidKeys() QString::number(ykds_version_build(st))); bool wouldBlock; - QList> ykSlots; for (int slot = 1; slot <= 2; ++slot) { auto config = (slot == 1 ? CONFIG1_VALID : CONFIG2_VALID); if (!(ykds_touch_level(st) & config)) { @@ -162,7 +161,7 @@ void YubiKeyInterfaceUSB::findValidKeys() if (pid <= NEO_OTP_U2F_CCID_PID) { auto display = tr("(USB) %1 [%2] Configured Slot - %3") .arg(name, QString::number(serial), QString::number(slot)); - ykSlots.append({slot, display}); + m_foundKeys.insert(serial, {slot, display}); } else if (performTestChallenge(yk_key, slot, &wouldBlock)) { auto display = tr("(USB) %1 [%2] Challenge-Response - Slot %3 - %4") @@ -171,7 +170,7 @@ void YubiKeyInterfaceUSB::findValidKeys() QString::number(slot), wouldBlock ? tr("Press", "USB Challenge-Response Key interaction request") : tr("Passive", "USB Challenge-Response Key no interaction required")); - m_foundKeys.insert(serial, {serial, slot, display}); + m_foundKeys.insert(serial, {slot, display}); } } diff --git a/src/keys/drivers/YubiKeyInterfaceUSB.h b/src/keys/drivers/YubiKeyInterfaceUSB.h index 7aef12baaa..6d0381c033 100644 --- a/src/keys/drivers/YubiKeyInterfaceUSB.h +++ b/src/keys/drivers/YubiKeyInterfaceUSB.h @@ -28,6 +28,7 @@ */ class YubiKeyInterfaceUSB : public YubiKeyInterface { + Q_OBJECT public: static YubiKeyInterfaceUSB* instance();