Use QSharedPointer instead of cloning YkChallengeResponseKey and make it a QObject to allow emitting signals
This commit is contained in:
@@ -25,7 +25,6 @@ class ChallengeResponseKey
|
||||
public:
|
||||
virtual ~ChallengeResponseKey() {}
|
||||
virtual QByteArray rawKey() const = 0;
|
||||
virtual ChallengeResponseKey* clone() const = 0;
|
||||
virtual bool challenge(const QByteArray& challenge) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -46,7 +46,6 @@ CompositeKey::~CompositeKey()
|
||||
void CompositeKey::clear()
|
||||
{
|
||||
qDeleteAll(m_keys);
|
||||
qDeleteAll(m_challengeResponseKeys);
|
||||
m_keys.clear();
|
||||
m_challengeResponseKeys.clear();
|
||||
}
|
||||
@@ -73,8 +72,8 @@ CompositeKey& CompositeKey::operator=(const CompositeKey& key)
|
||||
for (const Key* subKey : asConst(key.m_keys)) {
|
||||
addKey(*subKey);
|
||||
}
|
||||
for (const ChallengeResponseKey* subKey : asConst(key.m_challengeResponseKeys)) {
|
||||
addChallengeResponseKey(*subKey);
|
||||
for (const auto subKey : asConst(key.m_challengeResponseKeys)) {
|
||||
addChallengeResponseKey(subKey);
|
||||
}
|
||||
|
||||
return *this;
|
||||
@@ -176,9 +175,8 @@ QByteArray CompositeKey::transformKeyRaw(const QByteArray& key, const QByteArray
|
||||
|
||||
bool CompositeKey::challenge(const QByteArray& seed, QByteArray& result) const
|
||||
{
|
||||
/* If no challenge response was requested, return nothing to
|
||||
* maintain backwards compatability with regular databases.
|
||||
*/
|
||||
// if no challenge response was requested, return nothing to
|
||||
// maintain backwards compatibility with regular databases.
|
||||
if (m_challengeResponseKeys.length() == 0) {
|
||||
result.clear();
|
||||
return true;
|
||||
@@ -186,9 +184,9 @@ bool CompositeKey::challenge(const QByteArray& seed, QByteArray& result) const
|
||||
|
||||
CryptoHash cryptoHash(CryptoHash::Sha256);
|
||||
|
||||
for (ChallengeResponseKey* key : m_challengeResponseKeys) {
|
||||
/* If the device isn't present or fails, return an error */
|
||||
if (key->challenge(seed) == false) {
|
||||
for (const auto key : m_challengeResponseKeys) {
|
||||
// if the device isn't present or fails, return an error
|
||||
if (!key->challenge(seed)) {
|
||||
return false;
|
||||
}
|
||||
cryptoHash.addData(key->rawKey());
|
||||
@@ -203,11 +201,12 @@ void CompositeKey::addKey(const Key& key)
|
||||
m_keys.append(key.clone());
|
||||
}
|
||||
|
||||
void CompositeKey::addChallengeResponseKey(const ChallengeResponseKey& key)
|
||||
void CompositeKey::addChallengeResponseKey(QSharedPointer<ChallengeResponseKey> key)
|
||||
{
|
||||
m_challengeResponseKeys.append(key.clone());
|
||||
m_challengeResponseKeys.append(key);
|
||||
}
|
||||
|
||||
|
||||
int CompositeKey::transformKeyBenchmark(int msec)
|
||||
{
|
||||
TransformKeyBenchmarkThread thread1(msec);
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QSharedPointer>
|
||||
|
||||
#include "keys/Key.h"
|
||||
#include "keys/ChallengeResponseKey.h"
|
||||
@@ -41,7 +42,7 @@ public:
|
||||
bool challenge(const QByteArray& seed, QByteArray &result) const;
|
||||
|
||||
void addKey(const Key& key);
|
||||
void addChallengeResponseKey(const ChallengeResponseKey& key);
|
||||
void addChallengeResponseKey(QSharedPointer<ChallengeResponseKey> key);
|
||||
|
||||
static int transformKeyBenchmark(int msec);
|
||||
static CompositeKey readFromLine(QString line);
|
||||
@@ -51,7 +52,7 @@ private:
|
||||
quint64 rounds, bool* ok, QString* errorString);
|
||||
|
||||
QList<Key*> m_keys;
|
||||
QList<ChallengeResponseKey*> m_challengeResponseKeys;
|
||||
QList<QSharedPointer<ChallengeResponseKey>> m_challengeResponseKeys;
|
||||
};
|
||||
|
||||
#endif // KEEPASSX_COMPOSITEKEY_H
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <QFile>
|
||||
#include <QXmlStreamReader>
|
||||
|
||||
@@ -26,11 +25,7 @@
|
||||
#include "keys/YkChallengeResponseKey.h"
|
||||
#include "keys/drivers/YubiKey.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QObject>
|
||||
|
||||
YkChallengeResponseKey::YkChallengeResponseKey(int slot,
|
||||
bool blocking)
|
||||
YkChallengeResponseKey::YkChallengeResponseKey(int slot, bool blocking)
|
||||
: m_slot(slot),
|
||||
m_blocking(blocking)
|
||||
{
|
||||
@@ -41,40 +36,41 @@ QByteArray YkChallengeResponseKey::rawKey() const
|
||||
return m_key;
|
||||
}
|
||||
|
||||
YkChallengeResponseKey* YkChallengeResponseKey::clone() const
|
||||
{
|
||||
return new YkChallengeResponseKey(*this);
|
||||
}
|
||||
|
||||
|
||||
/** Assumes yubikey()->init() was called */
|
||||
/**
|
||||
* Assumes yubikey()->init() was called
|
||||
*/
|
||||
bool YkChallengeResponseKey::challenge(const QByteArray& chal)
|
||||
{
|
||||
return challenge(chal, 1);
|
||||
}
|
||||
|
||||
bool YkChallengeResponseKey::challenge(const QByteArray& chal, int retries)
|
||||
#include <QDebug>
|
||||
bool YkChallengeResponseKey::challenge(const QByteArray& chal, unsigned retries)
|
||||
{
|
||||
if (YubiKey::instance()->challenge(m_slot, true, chal, m_key) != YubiKey::ERROR) {
|
||||
return true;
|
||||
}
|
||||
Q_ASSERT(retries > 0);
|
||||
|
||||
/* If challenge failed, retry to detect YubiKeys in the event the YubiKey
|
||||
* was un-plugged and re-plugged */
|
||||
while (retries > 0) {
|
||||
#ifdef QT_DEBUG
|
||||
qDebug() << "Attempt" << retries << "to re-detect YubiKey(s)";
|
||||
#endif
|
||||
retries--;
|
||||
do {
|
||||
--retries;
|
||||
|
||||
if (YubiKey::instance()->init() != true) {
|
||||
if (m_blocking) {
|
||||
emit userInteractionRequired();
|
||||
}
|
||||
|
||||
auto result = YubiKey::instance()->challenge(m_slot, true, chal, m_key);
|
||||
|
||||
if (m_blocking) {
|
||||
emit userConfirmed();
|
||||
}
|
||||
|
||||
if (result != YubiKey::ERROR) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// if challenge failed, retry to detect YubiKeys in the event the YubiKey was un-plugged and re-plugged
|
||||
if (retries > 0 && YubiKey::instance()->init() != true) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (YubiKey::instance()->challenge(m_slot, true, chal, m_key) != YubiKey::ERROR) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} while (retries > 0);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -22,20 +22,34 @@
|
||||
#include "keys/ChallengeResponseKey.h"
|
||||
#include "keys/drivers/YubiKey.h"
|
||||
|
||||
class YkChallengeResponseKey : public ChallengeResponseKey
|
||||
#include <QObject>
|
||||
|
||||
class YkChallengeResponseKey : public QObject, public ChallengeResponseKey
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
YkChallengeResponseKey(int slot = -1,
|
||||
bool blocking = false);
|
||||
YkChallengeResponseKey(int slot = -1, bool blocking = false);
|
||||
|
||||
QByteArray rawKey() const;
|
||||
YkChallengeResponseKey* clone() const;
|
||||
bool challenge(const QByteArray& chal);
|
||||
bool challenge(const QByteArray& chal, int retries);
|
||||
bool challenge(const QByteArray& chal, unsigned retries);
|
||||
QString getName() const;
|
||||
bool isBlocking() const;
|
||||
|
||||
signals:
|
||||
/**
|
||||
* Emitted whenever user interaction is required to proceed with the challenge-response protocol.
|
||||
* You can use this to show a helpful dialog informing the user that his assistance is required.
|
||||
*/
|
||||
void userInteractionRequired();
|
||||
|
||||
/**
|
||||
* Emitted when the user has provided their required input.
|
||||
*/
|
||||
void userConfirmed();
|
||||
|
||||
private:
|
||||
QByteArray m_key;
|
||||
int m_slot;
|
||||
|
||||
Reference in New Issue
Block a user