mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-07-26 08:15:32 -04:00
Both slots on Yubikey are now polled for challenge/response
This commit is contained in:
parent
2e81751131
commit
3bc8a79b9b
4 changed files with 56 additions and 19 deletions
|
@ -70,9 +70,6 @@ DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent)
|
||||||
|
|
||||||
connect(m_ui->buttonRedetectYubikey, SIGNAL(clicked()), SLOT(pollYubikey()));
|
connect(m_ui->buttonRedetectYubikey, SIGNAL(clicked()), SLOT(pollYubikey()));
|
||||||
connect(m_ui->comboChallengeResponse, SIGNAL(activated(int)), SLOT(activateChallengeResponse()));
|
connect(m_ui->comboChallengeResponse, SIGNAL(activated(int)), SLOT(activateChallengeResponse()));
|
||||||
|
|
||||||
connect(YubiKey::instance(), SIGNAL(detected(int,bool)), SLOT(yubikeyDetected(int,bool)), Qt::QueuedConnection);
|
|
||||||
connect(YubiKey::instance(), SIGNAL(notFound()), SLOT(noYubikeyFound()), Qt::QueuedConnection);
|
|
||||||
#else
|
#else
|
||||||
m_ui->checkChallengeResponse->setVisible(false);
|
m_ui->checkChallengeResponse->setVisible(false);
|
||||||
m_ui->buttonRedetectYubikey->setVisible(false);
|
m_ui->buttonRedetectYubikey->setVisible(false);
|
||||||
|
@ -98,10 +95,24 @@ void DatabaseOpenWidget::showEvent(QShowEvent* event)
|
||||||
m_ui->editPassword->setFocus();
|
m_ui->editPassword->setFocus();
|
||||||
|
|
||||||
#ifdef WITH_XC_YUBIKEY
|
#ifdef WITH_XC_YUBIKEY
|
||||||
|
connect(YubiKey::instance(), SIGNAL(detected(int,bool)), SLOT(yubikeyDetected(int,bool)), Qt::QueuedConnection);
|
||||||
|
connect(YubiKey::instance(), SIGNAL(detectComplete()), SLOT(yubikeyDetectComplete()), Qt::QueuedConnection);
|
||||||
|
connect(YubiKey::instance(), SIGNAL(notFound()), SLOT(noYubikeyFound()), Qt::QueuedConnection);
|
||||||
|
|
||||||
pollYubikey();
|
pollYubikey();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DatabaseOpenWidget::hideEvent(QHideEvent* event)
|
||||||
|
{
|
||||||
|
DialogyWidget::hideEvent(event);
|
||||||
|
|
||||||
|
#ifdef WITH_XC_YUBIKEY
|
||||||
|
// Don't listen to any Yubikey events if we are hidden
|
||||||
|
disconnect(YubiKey::instance(), 0, this, 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void DatabaseOpenWidget::load(const QString& filename)
|
void DatabaseOpenWidget::load(const QString& filename)
|
||||||
{
|
{
|
||||||
m_filename = filename;
|
m_filename = filename;
|
||||||
|
@ -283,10 +294,6 @@ void DatabaseOpenWidget::yubikeyDetected(int slot, bool blocking)
|
||||||
YkChallengeResponseKey yk(slot, blocking);
|
YkChallengeResponseKey yk(slot, blocking);
|
||||||
// add detected YubiKey to combo box and encode blocking mode in LSB, slot number in second LSB
|
// add detected YubiKey to combo box and encode blocking mode in LSB, slot number in second LSB
|
||||||
m_ui->comboChallengeResponse->addItem(yk.getName(), QVariant((slot << 1) | blocking));
|
m_ui->comboChallengeResponse->addItem(yk.getName(), QVariant((slot << 1) | blocking));
|
||||||
m_ui->comboChallengeResponse->setEnabled(true);
|
|
||||||
m_ui->checkChallengeResponse->setEnabled(true);
|
|
||||||
m_ui->buttonRedetectYubikey->setEnabled(true);
|
|
||||||
m_ui->yubikeyProgress->setVisible(false);
|
|
||||||
|
|
||||||
if (config()->get("RememberLastKeyFiles").toBool()) {
|
if (config()->get("RememberLastKeyFiles").toBool()) {
|
||||||
QHash<QString, QVariant> lastChallengeResponse = config()->get("LastChallengeResponse").toHash();
|
QHash<QString, QVariant> lastChallengeResponse = config()->get("LastChallengeResponse").toHash();
|
||||||
|
@ -296,6 +303,14 @@ void DatabaseOpenWidget::yubikeyDetected(int slot, bool blocking)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DatabaseOpenWidget::yubikeyDetectComplete()
|
||||||
|
{
|
||||||
|
m_ui->comboChallengeResponse->setEnabled(true);
|
||||||
|
m_ui->checkChallengeResponse->setEnabled(true);
|
||||||
|
m_ui->buttonRedetectYubikey->setEnabled(true);
|
||||||
|
m_ui->yubikeyProgress->setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
void DatabaseOpenWidget::noYubikeyFound()
|
void DatabaseOpenWidget::noYubikeyFound()
|
||||||
{
|
{
|
||||||
m_ui->buttonRedetectYubikey->setEnabled(true);
|
m_ui->buttonRedetectYubikey->setEnabled(true);
|
||||||
|
|
|
@ -51,6 +51,7 @@ signals:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void showEvent(QShowEvent* event) override;
|
void showEvent(QShowEvent* event) override;
|
||||||
|
void hideEvent(QHideEvent* event) override;
|
||||||
CompositeKey databaseKey();
|
CompositeKey databaseKey();
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
|
@ -63,6 +64,7 @@ private slots:
|
||||||
void activateChallengeResponse();
|
void activateChallengeResponse();
|
||||||
void browseKeyFile();
|
void browseKeyFile();
|
||||||
void yubikeyDetected(int slot, bool blocking);
|
void yubikeyDetected(int slot, bool blocking);
|
||||||
|
void yubikeyDetectComplete();
|
||||||
void noYubikeyFound();
|
void noYubikeyFound();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <ykdef.h>
|
#include <ykdef.h>
|
||||||
#include <ykstatus.h>
|
#include <ykstatus.h>
|
||||||
|
|
||||||
|
#include "core/Tools.h"
|
||||||
#include "core/Global.h"
|
#include "core/Global.h"
|
||||||
#include "crypto/Random.h"
|
#include "crypto/Random.h"
|
||||||
|
|
||||||
|
@ -112,23 +113,36 @@ bool YubiKey::deinit()
|
||||||
|
|
||||||
void YubiKey::detect()
|
void YubiKey::detect()
|
||||||
{
|
{
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
if (init()) {
|
if (init()) {
|
||||||
for (int i = 1; i < 3; i++) {
|
|
||||||
YubiKey::ChallengeResult result;
|
YubiKey::ChallengeResult result;
|
||||||
QByteArray rand = randomGen()->randomArray(1);
|
QByteArray rand = randomGen()->randomArray(1);
|
||||||
QByteArray resp;
|
QByteArray resp;
|
||||||
|
|
||||||
|
// Check slot 1 and 2 for Challenge-Response HMAC capability
|
||||||
|
for (int i = 1; i <= 2; ++i) {
|
||||||
result = challenge(i, false, rand, resp);
|
result = challenge(i, false, rand, resp);
|
||||||
if (result == YubiKey::ALREADY_RUNNING) {
|
if (result == ALREADY_RUNNING) {
|
||||||
emit alreadyRunning();
|
// Try this slot again after waiting
|
||||||
return;
|
Tools::sleep(300);
|
||||||
} else if (result != YubiKey::ERROR) {
|
result = challenge(i, false, rand, resp);
|
||||||
emit detected(i, result == YubiKey::WOULDBLOCK);
|
}
|
||||||
return;
|
|
||||||
}
|
if (result != ALREADY_RUNNING && result != ERROR) {
|
||||||
|
emit detected(i, result == WOULDBLOCK);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
// Wait between slots to let the yubikey settle
|
||||||
|
Tools::sleep(150);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
emit notFound();
|
emit notFound();
|
||||||
|
} else {
|
||||||
|
emit detectComplete();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool YubiKey::getSerial(unsigned int& serial)
|
bool YubiKey::getSerial(unsigned int& serial)
|
||||||
|
@ -160,6 +174,7 @@ YubiKey::ChallengeResult YubiKey::challenge(int slot, bool mayBlock, const QByte
|
||||||
}
|
}
|
||||||
|
|
||||||
// yk_challenge_response() insists on 64 byte response buffer */
|
// yk_challenge_response() insists on 64 byte response buffer */
|
||||||
|
response.clear();
|
||||||
response.resize(64);
|
response.resize(64);
|
||||||
|
|
||||||
/* The challenge sent to the yubikey should always be 64 bytes for
|
/* The challenge sent to the yubikey should always be 64 bytes for
|
||||||
|
|
|
@ -87,6 +87,11 @@ signals:
|
||||||
*/
|
*/
|
||||||
void detected(int slot, bool blocking);
|
void detected(int slot, bool blocking);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emitted when detection is complete
|
||||||
|
*/
|
||||||
|
void detectComplete();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emitted when the YubiKey was challenged and has returned a response.
|
* Emitted when the YubiKey was challenged and has returned a response.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue