mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-01-23 13:11:12 -05:00
Add configurable password strength check on database password (#9782)
* Set default value of DatabasePasswordMinimumQuality to 3 (do not accept a master password that is less than Good) * Add custom message box button "Continue with weak password"
This commit is contained in:
parent
b2e6dc5fda
commit
d44486ce94
@ -1843,6 +1843,18 @@ Are you sure you want to continue without a password?</source>
|
|||||||
<source>Failed to change database credentials</source>
|
<source>Failed to change database credentials</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Weak password</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>You must enter a stronger password to protect your database.</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>This is a weak password! For better protection of your secrets, you should choose a stronger password.</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>DatabaseSettingsWidgetEncryption</name>
|
<name>DatabaseSettingsWidgetEncryption</name>
|
||||||
@ -6511,6 +6523,10 @@ Do you want to overwrite it?</source>
|
|||||||
<source>Continue</source>
|
<source>Continue</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Continue with weak password</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>QObject</name>
|
<name>QObject</name>
|
||||||
|
@ -144,6 +144,7 @@ static const QHash<Config::ConfigKey, ConfigDirective> configStrings = {
|
|||||||
{Config::Security_NoConfirmMoveEntryToRecycleBin,{QS("Security/NoConfirmMoveEntryToRecycleBin"), Roaming, true}},
|
{Config::Security_NoConfirmMoveEntryToRecycleBin,{QS("Security/NoConfirmMoveEntryToRecycleBin"), Roaming, true}},
|
||||||
{Config::Security_EnableCopyOnDoubleClick,{QS("Security/EnableCopyOnDoubleClick"), Roaming, false}},
|
{Config::Security_EnableCopyOnDoubleClick,{QS("Security/EnableCopyOnDoubleClick"), Roaming, false}},
|
||||||
{Config::Security_QuickUnlock, {QS("Security/QuickUnlock"), Local, true}},
|
{Config::Security_QuickUnlock, {QS("Security/QuickUnlock"), Local, true}},
|
||||||
|
{Config::Security_DatabasePasswordMinimumQuality, {QS("Security/DatabasePasswordMinimumQuality"), Local, 0}},
|
||||||
|
|
||||||
// Browser
|
// Browser
|
||||||
{Config::Browser_Enabled, {QS("Browser/Enabled"), Roaming, false}},
|
{Config::Browser_Enabled, {QS("Browser/Enabled"), Roaming, false}},
|
||||||
|
@ -124,6 +124,7 @@ public:
|
|||||||
Security_NoConfirmMoveEntryToRecycleBin,
|
Security_NoConfirmMoveEntryToRecycleBin,
|
||||||
Security_EnableCopyOnDoubleClick,
|
Security_EnableCopyOnDoubleClick,
|
||||||
Security_QuickUnlock,
|
Security_QuickUnlock,
|
||||||
|
Security_DatabasePasswordMinimumQuality,
|
||||||
|
|
||||||
Browser_Enabled,
|
Browser_Enabled,
|
||||||
Browser_ShowNotification,
|
Browser_ShowNotification,
|
||||||
|
@ -66,6 +66,7 @@ void MessageBox::initializeButtonDefs()
|
|||||||
{Disable, {QMessageBox::tr("Disable"), QMessageBox::ButtonRole::AcceptRole}},
|
{Disable, {QMessageBox::tr("Disable"), QMessageBox::ButtonRole::AcceptRole}},
|
||||||
{Merge, {QMessageBox::tr("Merge"), QMessageBox::ButtonRole::AcceptRole}},
|
{Merge, {QMessageBox::tr("Merge"), QMessageBox::ButtonRole::AcceptRole}},
|
||||||
{Continue, {QMessageBox::tr("Continue"), QMessageBox::ButtonRole::AcceptRole}},
|
{Continue, {QMessageBox::tr("Continue"), QMessageBox::ButtonRole::AcceptRole}},
|
||||||
|
{ContinueWithWeakPass, {QMessageBox::tr("Continue with weak password"), QMessageBox::ButtonRole::AcceptRole}},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,10 +58,11 @@ public:
|
|||||||
Disable = 1 << 25,
|
Disable = 1 << 25,
|
||||||
Merge = 1 << 26,
|
Merge = 1 << 26,
|
||||||
Continue = 1 << 27,
|
Continue = 1 << 27,
|
||||||
|
ContinueWithWeakPass = 1 << 28,
|
||||||
|
|
||||||
// Internal loop markers. Update Last when new KeePassXC button is added
|
// Internal loop markers. Update Last when new KeePassXC button is added
|
||||||
First = Ok,
|
First = Ok,
|
||||||
Last = Continue,
|
Last = ContinueWithWeakPass,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Action
|
enum Action
|
||||||
|
@ -62,6 +62,14 @@ bool PasswordEditWidget::isEmpty() const
|
|||||||
return (visiblePage() == Page::Edit) && m_compUi->enterPasswordEdit->text().isEmpty();
|
return (visiblePage() == Page::Edit) && m_compUi->enterPasswordEdit->text().isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PasswordHealth::Quality PasswordEditWidget::getPasswordQuality() const
|
||||||
|
{
|
||||||
|
QString pwd = m_compUi->enterPasswordEdit->text();
|
||||||
|
PasswordHealth passwordHealth(pwd);
|
||||||
|
|
||||||
|
return passwordHealth.quality();
|
||||||
|
}
|
||||||
|
|
||||||
QWidget* PasswordEditWidget::componentEditWidget()
|
QWidget* PasswordEditWidget::componentEditWidget()
|
||||||
{
|
{
|
||||||
m_compEditWidget = new QWidget();
|
m_compEditWidget = new QWidget();
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
|
|
||||||
#include "KeyComponentWidget.h"
|
#include "KeyComponentWidget.h"
|
||||||
|
|
||||||
|
#include "core/PasswordHealth.h"
|
||||||
|
|
||||||
namespace Ui
|
namespace Ui
|
||||||
{
|
{
|
||||||
class PasswordEditWidget;
|
class PasswordEditWidget;
|
||||||
@ -38,6 +40,7 @@ public:
|
|||||||
void setPasswordVisible(bool visible);
|
void setPasswordVisible(bool visible);
|
||||||
bool isPasswordVisible() const;
|
bool isPasswordVisible() const;
|
||||||
bool isEmpty() const;
|
bool isEmpty() const;
|
||||||
|
PasswordHealth::Quality getPasswordQuality() const;
|
||||||
bool validate(QString& errorMessage) const override;
|
bool validate(QString& errorMessage) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -17,7 +17,9 @@
|
|||||||
|
|
||||||
#include "DatabaseSettingsWidgetDatabaseKey.h"
|
#include "DatabaseSettingsWidgetDatabaseKey.h"
|
||||||
|
|
||||||
|
#include "core/Config.h"
|
||||||
#include "core/Database.h"
|
#include "core/Database.h"
|
||||||
|
#include "core/PasswordHealth.h"
|
||||||
#include "gui/MessageBox.h"
|
#include "gui/MessageBox.h"
|
||||||
#include "gui/databasekey/KeyFileEditWidget.h"
|
#include "gui/databasekey/KeyFileEditWidget.h"
|
||||||
#include "gui/databasekey/PasswordEditWidget.h"
|
#include "gui/databasekey/PasswordEditWidget.h"
|
||||||
@ -153,6 +155,7 @@ bool DatabaseSettingsWidgetDatabaseKey::save()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show warning if database password has not been set
|
||||||
if (m_passwordEditWidget->visiblePage() == KeyComponentWidget::Page::AddNew || m_passwordEditWidget->isEmpty()) {
|
if (m_passwordEditWidget->visiblePage() == KeyComponentWidget::Page::AddNew || m_passwordEditWidget->isEmpty()) {
|
||||||
QScopedPointer<QMessageBox> msgBox(new QMessageBox(this));
|
QScopedPointer<QMessageBox> msgBox(new QMessageBox(this));
|
||||||
msgBox->setIcon(QMessageBox::Warning);
|
msgBox->setIcon(QMessageBox::Warning);
|
||||||
@ -171,6 +174,33 @@ bool DatabaseSettingsWidgetDatabaseKey::save()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show warning if database password is weak
|
||||||
|
if (!m_passwordEditWidget->isEmpty()
|
||||||
|
&& m_passwordEditWidget->getPasswordQuality() < PasswordHealth::Quality::Good) {
|
||||||
|
auto dialogResult = MessageBox::warning(this,
|
||||||
|
tr("Weak password"),
|
||||||
|
tr("This is a weak password! For better protection of your secrets, "
|
||||||
|
"you should choose a stronger password."),
|
||||||
|
MessageBox::ContinueWithWeakPass | MessageBox::Cancel,
|
||||||
|
MessageBox::Cancel);
|
||||||
|
|
||||||
|
if (dialogResult == MessageBox::Cancel) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If enforced in the config file, deny users from continuing with a weak password
|
||||||
|
auto minQuality =
|
||||||
|
static_cast<PasswordHealth::Quality>(config()->get(Config::Security_DatabasePasswordMinimumQuality).toInt());
|
||||||
|
if (!m_passwordEditWidget->isEmpty() && m_passwordEditWidget->getPasswordQuality() < minQuality) {
|
||||||
|
MessageBox::critical(this,
|
||||||
|
tr("Weak password"),
|
||||||
|
tr("You must enter a stronger password to protect your database."),
|
||||||
|
MessageBox::Ok,
|
||||||
|
MessageBox::Ok);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!addToCompositeKey(m_keyFileEditWidget, newKey, oldFileKey)) {
|
if (!addToCompositeKey(m_keyFileEditWidget, newKey, oldFileKey)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -286,7 +286,10 @@ void TestGui::testCreateDatabase()
|
|||||||
tmpFile.close();
|
tmpFile.close();
|
||||||
fileDialog()->setNextFileName(tmpFile.fileName());
|
fileDialog()->setNextFileName(tmpFile.fileName());
|
||||||
|
|
||||||
|
// click Continue on the warning due to weak password
|
||||||
|
MessageBox::setNextAnswer(MessageBox::ContinueWithWeakPass);
|
||||||
QTest::keyClick(fileEdit, Qt::Key::Key_Enter);
|
QTest::keyClick(fileEdit, Qt::Key::Key_Enter);
|
||||||
|
|
||||||
tmpFile.remove(););
|
tmpFile.remove(););
|
||||||
|
|
||||||
triggerAction("actionDatabaseNew");
|
triggerAction("actionDatabaseNew");
|
||||||
|
@ -1879,6 +1879,8 @@ bool TestGuiFdoSecrets::driveNewDatabaseWizard()
|
|||||||
tmpFile.close();
|
tmpFile.close();
|
||||||
fileDialog()->setNextFileName(tmpFile.fileName());
|
fileDialog()->setNextFileName(tmpFile.fileName());
|
||||||
|
|
||||||
|
// click Continue on the warning due to weak password
|
||||||
|
MessageBox::setNextAnswer(MessageBox::ContinueWithWeakPass);
|
||||||
wizard->accept();
|
wizard->accept();
|
||||||
|
|
||||||
tmpFile.remove();
|
tmpFile.remove();
|
||||||
|
Loading…
Reference in New Issue
Block a user