From 70816f90b2c4488c9636ca60124eb897c7da6371 Mon Sep 17 00:00:00 2001 From: Janek Bevendorff Date: Fri, 24 Feb 2017 00:15:57 +0100 Subject: [PATCH] Make challenge() member thread-safe --- src/keys/drivers/YubiKey.cpp | 27 ++++++++++++++++----------- src/keys/drivers/YubiKey.h | 12 ++++++++++-- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/keys/drivers/YubiKey.cpp b/src/keys/drivers/YubiKey.cpp index b287c13b2..1d4445cd6 100644 --- a/src/keys/drivers/YubiKey.cpp +++ b/src/keys/drivers/YubiKey.cpp @@ -107,8 +107,10 @@ void YubiKey::detect() QByteArray resp; result = challenge(i, false, rand, resp); - - if (result != YubiKey::ERROR) { + if (result == YubiKey::ALREADY_RUNNING) { + emit alreadyRunning(); + return; + } else if (result != YubiKey::ERROR) { emit detected(i, result == YubiKey::WOULDBLOCK ? true : false); return; } @@ -141,13 +143,18 @@ static inline QString printByteArray(const QByteArray& a) } #endif -YubiKey::ChallengeResult YubiKey::challenge(int slot, bool mayBlock, const QByteArray& chal, QByteArray& resp) const +YubiKey::ChallengeResult YubiKey::challenge(int slot, bool mayBlock, const QByteArray& chal, QByteArray& resp) { + if (!m_mutex.tryLock()) { + return ALREADY_RUNNING; + } + int yk_cmd = (slot == 1) ? SLOT_CHAL_HMAC1 : SLOT_CHAL_HMAC2; QByteArray paddedChal = chal; - /* Ensure that YubiKey::init() succeeded */ + // ensure that YubiKey::init() succeeded if (m_yk == NULL) { + m_mutex.unlock(); return ERROR; } @@ -171,13 +178,12 @@ YubiKey::ChallengeResult YubiKey::challenge(int slot, bool mayBlock, const QByte r = reinterpret_cast(resp.data()); #ifdef QT_DEBUG - qDebug().nospace() << __func__ << "(" << slot << ") c = " - << printByteArray(paddedChal); + qDebug().nospace() << __func__ << "(" << slot << ") c = " << printByteArray(paddedChal); #endif - int ret = yk_challenge_response(m_yk, yk_cmd, mayBlock, - paddedChal.size(), c, - resp.size(), r); + int ret = yk_challenge_response(m_yk, yk_cmd, mayBlock, paddedChal.size(), c, resp.size(), r); + + m_mutex.unlock(); if (!ret) { if (yk_errno == YK_EWOULDBLOCK) { @@ -206,8 +212,7 @@ YubiKey::ChallengeResult YubiKey::challenge(int slot, bool mayBlock, const QByte resp.resize(20); #ifdef QT_DEBUG - qDebug().nospace() << __func__ << "(" << slot << ") r = " - << printByteArray(resp) << ", ret = " << ret; + qDebug().nospace() << __func__ << "(" << slot << ") r = " << printByteArray(resp) << ", ret = " << ret; #endif return SUCCESS; diff --git a/src/keys/drivers/YubiKey.h b/src/keys/drivers/YubiKey.h index acf4feb72..6c3504ed1 100644 --- a/src/keys/drivers/YubiKey.h +++ b/src/keys/drivers/YubiKey.h @@ -19,6 +19,7 @@ #define KEEPASSX_YUBIKEY_H #include +#include /** * Singleton class to manage the interface to the hardware @@ -28,7 +29,7 @@ class YubiKey : public QObject Q_OBJECT public: - enum ChallengeResult { ERROR = -1, SUCCESS = 0, WOULDBLOCK }; + enum ChallengeResult { ERROR = -1, SUCCESS = 0, WOULDBLOCK, ALREADY_RUNNING }; /** * @brief YubiKey::instance - get instance of singleton @@ -64,7 +65,7 @@ public: */ ChallengeResult challenge(int slot, bool mayBlock, const QByteArray& chal, - QByteArray& resp) const; + QByteArray& resp); /** * @brief YubiKey::getSerial - serial number of YubiKey @@ -92,6 +93,11 @@ Q_SIGNALS: */ void notFound(); + /** + * Emitted when detection is already running. + */ + void alreadyRunning(); + private: explicit YubiKey(); static YubiKey* m_instance; @@ -100,6 +106,8 @@ private: void* m_yk_void; void* m_ykds_void; + QMutex m_mutex; + Q_DISABLE_COPY(YubiKey) };