hack: bypass password challenge verification
Needed to support automatic migration of old Keysmith storage format. This is unfortunate, but we have users and we cannot simply break backwards compatibility with the old storage format (yet).master
parent
464e001caf
commit
82ebbdf4f9
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* SPDX-FileCopyrightText: 2020 Johan Ouwerkerk <jm.ouwerkerk@gmail.com>
|
||||
* SPDX-FileCopyrightText: 2020-2021 Johan Ouwerkerk <jm.ouwerkerk@gmail.com>
|
||||
*/
|
||||
#include "actions_p.h"
|
||||
#include "validation.h"
|
||||
|
@ -347,6 +347,8 @@ namespace accounts
|
|||
quint64 cpuCost = 0ULL;
|
||||
quint64 keyLength = 0ULL;
|
||||
size_t memoryCost = 0ULL;
|
||||
// HACK: disables challenge verification, remove at some point!
|
||||
bool challengeAvailable = settings.contains(QStringLiteral("challenge"));
|
||||
int algorithm = settings.value(QStringLiteral("algorithm")).toInt(&ok);
|
||||
if (ok) {
|
||||
ok = false;
|
||||
|
@ -365,12 +367,15 @@ namespace accounts
|
|||
salt = QByteArray::fromBase64(encodedSalt, QByteArray::Base64Encoding);
|
||||
ok = !salt.isEmpty() && secrets::SecureMasterKey::validate(salt);
|
||||
}
|
||||
if (ok) {
|
||||
|
||||
// HACK: disables challenge verification, remove at some point!
|
||||
if (challengeAvailable && ok) {
|
||||
QByteArray encodedChallenge = settings.value(QStringLiteral("challenge")).toString().toUtf8();
|
||||
challenge = QByteArray::fromBase64(encodedChallenge, QByteArray::Base64Encoding);
|
||||
ok = !challenge.isEmpty();
|
||||
}
|
||||
if (ok) {
|
||||
// HACK: disables challenge verification, remove at some point!
|
||||
if (challengeAvailable && ok) {
|
||||
QByteArray encodedNonce = settings.value(QStringLiteral("nonce")).toString().toUtf8();
|
||||
nonce = QByteArray::fromBase64(encodedNonce, QByteArray::Base64Encoding);
|
||||
ok = !nonce.isEmpty();
|
||||
|
@ -379,13 +384,17 @@ namespace accounts
|
|||
|
||||
const auto params = secrets::KeyDerivationParameters::create(keyLength, algorithm, memoryCost, cpuCost);
|
||||
const auto encryptedChallenge = secrets::EncryptedSecret::from(challenge, nonce);
|
||||
if (!ok || !params || !secrets::SecureMasterKey::validate(*params) || !encryptedChallenge) {
|
||||
|
||||
// HACK: disables challenge verification, remove at some point!
|
||||
if (!ok || !params || !secrets::SecureMasterKey::validate(*params) || (challengeAvailable && !encryptedChallenge)) {
|
||||
qCDebug(logger) << "Unable to request 'existing' password: invalid challenge, nonce, salt or key derivation parameters";
|
||||
return;
|
||||
}
|
||||
|
||||
qCInfo(logger) << "Requesting 'existing' password for accounts";
|
||||
ok = m_secret->requestExistingPassword(*encryptedChallenge, salt, *params);
|
||||
ok = challengeAvailable
|
||||
? m_secret->requestExistingPassword(*encryptedChallenge, salt, *params)
|
||||
: m_secret->requestExistingPassword(salt, *params); // HACK: disables challenge verification, remove at some point!
|
||||
});
|
||||
|
||||
if (!ok) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* SPDX-FileCopyrightText: 2020 Johan Ouwerkerk <jm.ouwerkerk@gmail.com>
|
||||
* SPDX-FileCopyrightText: 2020-2021 Johan Ouwerkerk <jm.ouwerkerk@gmail.com>
|
||||
*/
|
||||
#include "keys.h"
|
||||
|
||||
|
@ -13,8 +13,10 @@ KEYSMITH_LOGGER(logger, ".accounts.keys")
|
|||
namespace accounts
|
||||
{
|
||||
AccountSecret::AccountSecret(const secrets::SecureRandom &random, QObject *parent) :
|
||||
QObject(parent), m_stillAlive(true), m_newPassword(false), m_passwordRequested(false), m_random(random),
|
||||
m_salt(std::nullopt), m_challenge(std::nullopt), m_key(nullptr), m_password(nullptr), m_keyParams(std::nullopt)
|
||||
QObject(parent), m_stillAlive(true), m_newPassword(false), m_passwordRequested(false),
|
||||
m_hackWithoutChallenge(false), // HACK: disables challenge verification, remove at some point!
|
||||
m_random(random), m_salt(std::nullopt), m_challenge(std::nullopt), m_key(nullptr), m_password(nullptr),
|
||||
m_keyParams(std::nullopt)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -81,6 +83,41 @@ namespace accounts
|
|||
return true;
|
||||
}
|
||||
|
||||
// HACK: disables challenge verification, remove at some point!
|
||||
bool AccountSecret::requestExistingPassword(const QByteArray& salt, const secrets::KeyDerivationParameters &keyParams)
|
||||
{
|
||||
qCWarning(logger) << "HACK: running a 'silent' migration for legacy account setups without password challenge";
|
||||
|
||||
if (!m_stillAlive) {
|
||||
qCDebug(logger) << "Ignoring request for 'existing' password: account secret is marked for death";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_passwordRequested) {
|
||||
qCDebug(logger) << "Ignoring request for 'existing' password: conflicting or duplicate request";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!secrets::SecureMasterKey::validate(keyParams)) {
|
||||
qCDebug(logger) << "Unable to request 'existing' password: invalid key derivation parameters";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!secrets::SecureMasterKey::validate(salt)) {
|
||||
qCDebug(logger) << "Unable to request 'existing' password: invalid salt";
|
||||
return false;
|
||||
}
|
||||
|
||||
qCDebug(logger) << "Emitting request for 'existing' password";
|
||||
m_passwordRequested = true;
|
||||
m_newPassword = false;
|
||||
m_keyParams.emplace(keyParams);
|
||||
m_salt.emplace(salt);
|
||||
m_hackWithoutChallenge = true;
|
||||
Q_EMIT existingPasswordNeeded();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AccountSecret::acceptPassword(QString &password, bool answerMatchesRequest)
|
||||
{
|
||||
QByteArray passwordBytes;
|
||||
|
@ -132,7 +169,9 @@ namespace accounts
|
|||
|
||||
bool AccountSecret::answerExistingPassword(QString &password)
|
||||
{
|
||||
bool result = acceptPassword(password, m_keyParams && m_salt && m_challenge);
|
||||
// HACK: disables challenge verification, remove at some point!
|
||||
bool challengeOk = (m_challenge || m_hackWithoutChallenge);
|
||||
bool result = acceptPassword(password, m_keyParams && m_salt && challengeOk);
|
||||
if (result) {
|
||||
Q_EMIT passwordAvailable();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* SPDX-FileCopyrightText: 2020 Johan Ouwerkerk <jm.ouwerkerk@gmail.com>
|
||||
* SPDX-FileCopyrightText: 2020-2021 Johan Ouwerkerk <jm.ouwerkerk@gmail.com>
|
||||
*/
|
||||
#ifndef ACCOUNTS_KEYS_H
|
||||
#define ACCOUNTS_KEYS_H
|
||||
|
@ -29,6 +29,9 @@ namespace accounts
|
|||
bool requestExistingPassword(const secrets::EncryptedSecret &challenge,
|
||||
const QByteArray& salt, const secrets::KeyDerivationParameters &keyParams);
|
||||
|
||||
// HACK: disables challenge verification, remove at some point!
|
||||
bool requestExistingPassword(const QByteArray& salt, const secrets::KeyDerivationParameters &keyParams);
|
||||
|
||||
bool answerExistingPassword(QString &password);
|
||||
bool answerNewPassword(QString &password, const secrets::KeyDerivationParameters &keyParams);
|
||||
|
||||
|
@ -50,6 +53,7 @@ namespace accounts
|
|||
bool m_stillAlive;
|
||||
bool m_newPassword;
|
||||
bool m_passwordRequested;
|
||||
bool m_hackWithoutChallenge; // HACK: disables challenge verification, remove at some point!
|
||||
const secrets::SecureRandom m_random;
|
||||
std::optional<QByteArray> m_salt;
|
||||
std::optional<secrets::EncryptedSecret> m_challenge;
|
||||
|
|
Loading…
Reference in New Issue