0
0
mirror of https://github.com/keepassxreboot/keepassxc.git synced 2024-09-19 20:02:18 +02:00

Fix issues with Hardware Key auto detection

* Fix #10656 - Add a small delay when before auto-polling hardware keys to all them to settle immediately after plugging in. This resolves an issue where the key's serial number could not be resolved due to hardware timeout.
* Also fix use of uninitialized variable if polling serial number fails for whatever reason.

* Fix typo in macOS key registration code

* Prevent registering duplicate listeners on window focus. These were not de-registered because we didn't trigger on unfocus. Show/Hide are sufficient triggers to add and remove listeners.
This commit is contained in:
Jonathan White 2024-05-04 08:31:01 -04:00
parent 83623c896f
commit 3ace4c6cf5
3 changed files with 44 additions and 33 deletions

View File

@ -159,51 +159,50 @@ void DatabaseOpenWidget::toggleHardwareKeyComponent(bool state)
bool DatabaseOpenWidget::event(QEvent* event) bool DatabaseOpenWidget::event(QEvent* event)
{ {
bool ret = DialogyWidget::event(event); bool ret = DialogyWidget::event(event);
auto type = event->type();
switch (event->type()) { if (type == QEvent::Show || type == QEvent::WindowActivate) {
case QEvent::Show:
case QEvent::WindowActivate: {
if (isOnQuickUnlockScreen() && (m_db.isNull() || !canPerformQuickUnlock())) { if (isOnQuickUnlockScreen() && (m_db.isNull() || !canPerformQuickUnlock())) {
resetQuickUnlock(); resetQuickUnlock();
} }
toggleQuickUnlockScreen(); toggleQuickUnlockScreen();
m_hideTimer.stop();
if (type == QEvent::Show) {
#ifdef WITH_XC_YUBIKEY #ifdef WITH_XC_YUBIKEY
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
m_deviceListener->registerHotplugCallback(true, m_deviceListener->registerHotplugCallback(true,
true, true,
YubiKeyInterfaceUSB::YUBICO_USB_VID, YubiKeyInterfaceUSB::YUBICO_USB_VID,
DeviceListener::MATCH_ANY, DeviceListener::MATCH_ANY,
&DeviceListenerWin::DEV_CLS_KEYBOARD); &DeviceListenerWin::DEV_CLS_KEYBOARD);
m_deviceListener->registerHotplugCallback(true, m_deviceListener->registerHotplugCallback(true,
true, true,
YubiKeyInterfaceUSB::ONLYKEY_USB_VID, YubiKeyInterfaceUSB::ONLYKEY_USB_VID,
DeviceListener::MATCH_ANY, DeviceListener::MATCH_ANY,
&DeviceListenerWin::DEV_CLS_KEYBOARD); &DeviceListenerWin::DEV_CLS_KEYBOARD);
#else #else
m_deviceListener->registerHotplugCallback(true, true, YubiKeyInterfaceUSB::YUBICO_USB_VID); m_deviceListener->registerHotplugCallback(true, true, YubiKeyInterfaceUSB::YUBICO_USB_VID);
m_deviceListener->registerHotplugCallback(true, true, YubiKeyInterfaceUSB::ONLYKEY_USB_VID); m_deviceListener->registerHotplugCallback(true, true, YubiKeyInterfaceUSB::ONLYKEY_USB_VID);
#endif #endif
#endif #endif
m_hideTimer.stop();
pollHardwareKey();
}
return true; ret = true;
} } else if (type == QEvent::Hide || type == QEvent::WindowDeactivate) {
case QEvent::Hide: {
// Schedule form clearing if we are hidden // Schedule form clearing if we are hidden
if (!isVisible()) { if (!m_hideTimer.isActive()) {
m_hideTimer.start(); m_hideTimer.start();
} }
#ifdef WITH_XC_YUBIKEY #ifdef WITH_XC_YUBIKEY
m_deviceListener->deregisterAllHotplugCallbacks(); if (type == QEvent::Hide) {
m_deviceListener->deregisterAllHotplugCallbacks();
}
#endif #endif
return true; ret = true;
}
default:;
} }
return ret; return ret;
@ -501,7 +500,10 @@ void DatabaseOpenWidget::pollHardwareKey(bool manualTrigger)
m_pollingHardwareKey = true; m_pollingHardwareKey = true;
m_manualHardwareKeyRefresh = manualTrigger; m_manualHardwareKeyRefresh = manualTrigger;
YubiKey::instance()->findValidKeysAsync(); // Add a delay, if this is an automatic trigger, to allow the USB device to settle as
// the device may not report a valid serial number immediately after plugging in
int delay = manualTrigger ? 0 : 500;
QTimer::singleShot(delay, this, [] { YubiKey::instance()->findValidKeysAsync(); });
} }
void DatabaseOpenWidget::hardwareKeyResponse(bool found) void DatabaseOpenWidget::hardwareKeyResponse(bool found)

View File

@ -54,7 +54,7 @@ void DeviceListenerMac::registerHotplugCallback(bool arrived, bool left, int ven
CFRelease(vid); CFRelease(vid);
} }
if (productId > 0) { if (productId > 0) {
auto pid = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vendorId); auto pid = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &productId);
CFDictionaryAddValue(matchingDict, CFSTR(kIOHIDProductIDKey), pid); CFDictionaryAddValue(matchingDict, CFSTR(kIOHIDProductIDKey), pid);
CFRelease(pid); CFRelease(pid);
} }

View File

@ -50,10 +50,22 @@ namespace
yk_close_key(key); yk_close_key(key);
} }
void printError()
{
if (yk_errno == YK_EUSBERR) {
qWarning("Hardware key USB error: %s", yk_usb_strerror());
} else {
qWarning("Hardware key error: %s", yk_strerror(yk_errno));
}
}
unsigned int getSerial(YK_KEY* key) unsigned int getSerial(YK_KEY* key)
{ {
unsigned int serial; unsigned int serial;
yk_get_serial(key, 1, 0, &serial); if (!yk_get_serial(key, 1, 0, &serial)) {
printError();
return 0;
}
return serial; return serial;
} }
@ -70,11 +82,8 @@ namespace
} else if (yk_errno == YK_ENOKEY) { } else if (yk_errno == YK_ENOKEY) {
// No more connected keys // No more connected keys
break; break;
} else if (yk_errno == YK_EUSBERR) {
qWarning("Hardware key USB error: %s", yk_usb_strerror());
} else {
qWarning("Hardware key error: %s", yk_strerror(yk_errno));
} }
printError();
} }
return nullptr; return nullptr;
} }