Make challenge() member thread-safe

This commit is contained in:
Janek Bevendorff 2017-02-24 00:15:57 +01:00
parent 093fe5c7ef
commit 70816f90b2
No known key found for this signature in database
GPG key ID: CFEC2F6850BFFA53
2 changed files with 26 additions and 13 deletions

View file

@ -107,8 +107,10 @@ void YubiKey::detect()
QByteArray resp; QByteArray resp;
result = challenge(i, false, rand, resp); result = challenge(i, false, rand, resp);
if (result == YubiKey::ALREADY_RUNNING) {
if (result != YubiKey::ERROR) { emit alreadyRunning();
return;
} else if (result != YubiKey::ERROR) {
emit detected(i, result == YubiKey::WOULDBLOCK ? true : false); emit detected(i, result == YubiKey::WOULDBLOCK ? true : false);
return; return;
} }
@ -141,13 +143,18 @@ static inline QString printByteArray(const QByteArray& a)
} }
#endif #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; int yk_cmd = (slot == 1) ? SLOT_CHAL_HMAC1 : SLOT_CHAL_HMAC2;
QByteArray paddedChal = chal; QByteArray paddedChal = chal;
/* Ensure that YubiKey::init() succeeded */ // ensure that YubiKey::init() succeeded
if (m_yk == NULL) { if (m_yk == NULL) {
m_mutex.unlock();
return ERROR; return ERROR;
} }
@ -171,13 +178,12 @@ YubiKey::ChallengeResult YubiKey::challenge(int slot, bool mayBlock, const QByte
r = reinterpret_cast<unsigned char*>(resp.data()); r = reinterpret_cast<unsigned char*>(resp.data());
#ifdef QT_DEBUG #ifdef QT_DEBUG
qDebug().nospace() << __func__ << "(" << slot << ") c = " qDebug().nospace() << __func__ << "(" << slot << ") c = " << printByteArray(paddedChal);
<< printByteArray(paddedChal);
#endif #endif
int ret = yk_challenge_response(m_yk, yk_cmd, mayBlock, int ret = yk_challenge_response(m_yk, yk_cmd, mayBlock, paddedChal.size(), c, resp.size(), r);
paddedChal.size(), c,
resp.size(), r); m_mutex.unlock();
if (!ret) { if (!ret) {
if (yk_errno == YK_EWOULDBLOCK) { if (yk_errno == YK_EWOULDBLOCK) {
@ -206,8 +212,7 @@ YubiKey::ChallengeResult YubiKey::challenge(int slot, bool mayBlock, const QByte
resp.resize(20); resp.resize(20);
#ifdef QT_DEBUG #ifdef QT_DEBUG
qDebug().nospace() << __func__ << "(" << slot << ") r = " qDebug().nospace() << __func__ << "(" << slot << ") r = " << printByteArray(resp) << ", ret = " << ret;
<< printByteArray(resp) << ", ret = " << ret;
#endif #endif
return SUCCESS; return SUCCESS;

View file

@ -19,6 +19,7 @@
#define KEEPASSX_YUBIKEY_H #define KEEPASSX_YUBIKEY_H
#include <QObject> #include <QObject>
#include <QMutex>
/** /**
* Singleton class to manage the interface to the hardware * Singleton class to manage the interface to the hardware
@ -28,7 +29,7 @@ class YubiKey : public QObject
Q_OBJECT Q_OBJECT
public: public:
enum ChallengeResult { ERROR = -1, SUCCESS = 0, WOULDBLOCK }; enum ChallengeResult { ERROR = -1, SUCCESS = 0, WOULDBLOCK, ALREADY_RUNNING };
/** /**
* @brief YubiKey::instance - get instance of singleton * @brief YubiKey::instance - get instance of singleton
@ -64,7 +65,7 @@ public:
*/ */
ChallengeResult challenge(int slot, bool mayBlock, ChallengeResult challenge(int slot, bool mayBlock,
const QByteArray& chal, const QByteArray& chal,
QByteArray& resp) const; QByteArray& resp);
/** /**
* @brief YubiKey::getSerial - serial number of YubiKey * @brief YubiKey::getSerial - serial number of YubiKey
@ -92,6 +93,11 @@ Q_SIGNALS:
*/ */
void notFound(); void notFound();
/**
* Emitted when detection is already running.
*/
void alreadyRunning();
private: private:
explicit YubiKey(); explicit YubiKey();
static YubiKey* m_instance; static YubiKey* m_instance;
@ -100,6 +106,8 @@ private:
void* m_yk_void; void* m_yk_void;
void* m_ykds_void; void* m_ykds_void;
QMutex m_mutex;
Q_DISABLE_COPY(YubiKey) Q_DISABLE_COPY(YubiKey)
}; };