From eb23dda99b187871745b274c34f1d1cd15d4ded9 Mon Sep 17 00:00:00 2001 From: Janek Bevendorff Date: Mon, 20 Feb 2017 22:07:01 +0100 Subject: [PATCH] Remember if challenge-response was used for each database and allow to re-detect Yubikeys without closing the database first --- src/gui/DatabaseOpenWidget.cpp | 47 ++++++++++++++++++++++++++++------ src/gui/DatabaseOpenWidget.h | 5 +++- src/gui/DatabaseOpenWidget.ui | 21 ++++++++++++++- src/keys/drivers/YubiKey.cpp | 5 ++-- src/keys/drivers/YubiKey.h | 5 ++++ 5 files changed, 71 insertions(+), 12 deletions(-) diff --git a/src/gui/DatabaseOpenWidget.cpp b/src/gui/DatabaseOpenWidget.cpp index f5d582c60..83488317f 100644 --- a/src/gui/DatabaseOpenWidget.cpp +++ b/src/gui/DatabaseOpenWidget.cpp @@ -67,9 +67,10 @@ DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent) connect(m_ui->buttonBox, SIGNAL(accepted()), SLOT(openDatabase())); connect(m_ui->buttonBox, SIGNAL(rejected()), SLOT(reject())); - connect(YubiKey::instance(), SIGNAL(detected(int,bool)), - SLOT(ykDetected(int,bool)), - Qt::QueuedConnection); + connect(m_ui->buttonRedetectYubikey, SIGNAL(clicked()), SLOT(pollYubikey())); + + connect(YubiKey::instance(), SIGNAL(detected(int,bool)), SLOT(yubikeyDetected(int,bool)), Qt::QueuedConnection); + connect(YubiKey::instance(), SIGNAL(notFound()), SLOT(noYubikeyFound()), Qt::QueuedConnection); #ifdef Q_OS_MACOS // add random padding to layouts to align widgets properly @@ -105,9 +106,8 @@ void DatabaseOpenWidget::load(const QString& filename) m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); - /* YubiKey init is slow, detect asynchronously to not block the UI */ m_ui->comboChallengeResponse->clear(); - QtConcurrent::run(YubiKey::instance(), &YubiKey::detect); + pollYubikey(); m_ui->editPassword->setFocus(); } @@ -169,6 +169,7 @@ CompositeKey DatabaseOpenWidget::databaseKey() } QHash lastKeyFiles = config()->get("LastKeyFiles").toHash(); + QHash lastChallengeResponse = config()->get("LastChallengeResponse").toHash(); if (m_ui->checkKeyFile->isChecked()) { FileKey key; @@ -181,13 +182,19 @@ CompositeKey DatabaseOpenWidget::databaseKey() } masterKey.addKey(key); lastKeyFiles[m_filename] = keyFilename; - } - else { + } else { lastKeyFiles.remove(m_filename); } + if (m_ui->checkChallengeResponse->isChecked()) { + lastChallengeResponse[m_filename] = true; + } else { + lastChallengeResponse.remove(m_filename); + } + if (config()->get("RememberLastKeyFiles").toBool()) { config()->set("LastKeyFiles", lastKeyFiles); + config()->set("LastChallengeResponse", lastChallengeResponse); } @@ -240,10 +247,34 @@ void DatabaseOpenWidget::browseKeyFile() } } -void DatabaseOpenWidget::ykDetected(int slot, bool blocking) +void DatabaseOpenWidget::pollYubikey() +{ + // YubiKey init is slow, detect asynchronously to not block the UI + m_ui->buttonRedetectYubikey->setEnabled(false); + m_ui->checkChallengeResponse->setEnabled(false); + m_ui->checkChallengeResponse->setChecked(false); + m_ui->comboChallengeResponse->setEnabled(false); + m_ui->comboChallengeResponse->clear(); + QtConcurrent::run(YubiKey::instance(), &YubiKey::detect); +} + +void DatabaseOpenWidget::yubikeyDetected(int slot, bool blocking) { YkChallengeResponseKey yk(slot, blocking); m_ui->comboChallengeResponse->addItem(yk.getName(), QVariant(slot)); m_ui->comboChallengeResponse->setEnabled(true); m_ui->checkChallengeResponse->setEnabled(true); + m_ui->buttonRedetectYubikey->setEnabled(true); + + if (config()->get("RememberLastKeyFiles").toBool()) { + QHash lastChallengeResponse = config()->get("LastChallengeResponse").toHash(); + if (lastChallengeResponse.contains(m_filename)) { + m_ui->checkChallengeResponse->setChecked(true); + } + } +} + +void DatabaseOpenWidget::noYubikeyFound() +{ + m_ui->buttonRedetectYubikey->setEnabled(true); } diff --git a/src/gui/DatabaseOpenWidget.h b/src/gui/DatabaseOpenWidget.h index fadb5ee70..d02346055 100644 --- a/src/gui/DatabaseOpenWidget.h +++ b/src/gui/DatabaseOpenWidget.h @@ -58,9 +58,12 @@ private Q_SLOTS: void activateChallengeResponse(); void setOkButtonEnabled(); void browseKeyFile(); - void ykDetected(int slot, bool blocking); + void yubikeyDetected(int slot, bool blocking); + void noYubikeyFound(); + void pollYubikey(); protected: + const QScopedPointer m_ui; Database* m_db; QString m_filename; diff --git a/src/gui/DatabaseOpenWidget.ui b/src/gui/DatabaseOpenWidget.ui index 01b82d407..f835fc2f6 100644 --- a/src/gui/DatabaseOpenWidget.ui +++ b/src/gui/DatabaseOpenWidget.ui @@ -7,7 +7,7 @@ 0 0 596 - 262 + 264 @@ -165,6 +165,25 @@ false + + + 0 + 0 + + + + false + + + + + + + false + + + Refresh + diff --git a/src/keys/drivers/YubiKey.cpp b/src/keys/drivers/YubiKey.cpp index 5ca175836..20e91237d 100644 --- a/src/keys/drivers/YubiKey.cpp +++ b/src/keys/drivers/YubiKey.cpp @@ -117,7 +117,6 @@ bool YubiKey::deinit() void YubiKey::detect() { if (init()) { - for (int i = 1; i < 3; i++) { YubiKey::ChallengeResult result; QByteArray rand = randomGen()->randomArray(1); @@ -126,10 +125,12 @@ void YubiKey::detect() result = challenge(i, false, rand, resp); if (result != YubiKey::ERROR) { - Q_EMIT detected(i, result == YubiKey::WOULDBLOCK ? true : false); + emit detected(i, result == YubiKey::WOULDBLOCK ? true : false); + return; } } } + emit notFound(); } /** diff --git a/src/keys/drivers/YubiKey.h b/src/keys/drivers/YubiKey.h index 492fba01d..0441e69a7 100644 --- a/src/keys/drivers/YubiKey.h +++ b/src/keys/drivers/YubiKey.h @@ -56,6 +56,11 @@ Q_SIGNALS: */ void detected(int slot, bool blocking); + /** + * Emitted when no Yubikey could be found. + */ + void notFound(); + private: explicit YubiKey(); static YubiKey* m_instance;