Merge pull request #9942 from Chocobo1/pbkdf2

Do password hashing properly
This commit is contained in:
Mike Tzou
2018-12-06 16:22:22 +08:00
committed by GitHub
21 changed files with 367 additions and 137 deletions

View File

@@ -30,7 +30,6 @@
#include <QClipboard>
#include <QCloseEvent>
#include <QCryptographicHash>
#include <QDebug>
#include <QDesktopServices>
#include <QFileDialog>
@@ -69,6 +68,7 @@
#include "base/utils/foreignapps.h"
#include "base/utils/fs.h"
#include "base/utils/misc.h"
#include "base/utils/password.h"
#include "aboutdialog.h"
#include "addnewtorrentdialog.h"
#include "application.h"
@@ -631,45 +631,41 @@ void MainWindow::toolbarFollowSystem()
Preferences::instance()->setToolbarTextPosition(Qt::ToolButtonFollowStyle);
}
void MainWindow::defineUILockPassword()
bool MainWindow::defineUILockPassword()
{
QString oldPassMd5 = Preferences::instance()->getUILockPasswordMD5();
if (oldPassMd5.isNull())
oldPassMd5 = "";
bool ok = false;
QString newClearPassword = AutoExpandableDialog::getText(this, tr("UI lock password"), tr("Please type the UI lock password:"), QLineEdit::Password, oldPassMd5, &ok);
if (ok) {
newClearPassword = newClearPassword.trimmed();
if (newClearPassword.size() < 3) {
QMessageBox::warning(this, tr("Invalid password"), tr("The password should contain at least 3 characters"));
}
else {
if (newClearPassword != oldPassMd5)
Preferences::instance()->setUILockPassword(newClearPassword);
QMessageBox::information(this, tr("Password update"), tr("The UI lock password has been successfully updated"));
}
const QString newPassword = AutoExpandableDialog::getText(this, tr("UI lock password")
, tr("Please type the UI lock password:"), QLineEdit::Password, {}, &ok);
if (!ok)
return false;
if (newPassword.size() < 3) {
QMessageBox::warning(this, tr("Invalid password"), tr("The password should contain at least 3 characters"));
return false;
}
Preferences::instance()->setUILockPassword(Utils::Password::PBKDF2::generate(newPassword));
return true;
}
void MainWindow::clearUILockPassword()
{
QMessageBox::StandardButton answer = QMessageBox::question(this, tr("Clear the password"), tr("Are you sure you want to clear the password?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
const QMessageBox::StandardButton answer = QMessageBox::question(this, tr("Clear the password")
, tr("Are you sure you want to clear the password?"), (QMessageBox::Yes | QMessageBox::No), QMessageBox::No);
if (answer == QMessageBox::Yes)
Preferences::instance()->clearUILockPassword();
Preferences::instance()->setUILockPassword({});
}
void MainWindow::on_actionLock_triggered()
{
Preferences *const pref = Preferences::instance();
// Check if there is a password
if (pref->getUILockPasswordMD5().isEmpty()) {
// Ask for a password
bool ok = false;
QString clearPassword = AutoExpandableDialog::getText(this, tr("UI lock password"), tr("Please type the UI lock password:"), QLineEdit::Password, "", &ok);
if (!ok) return;
pref->setUILockPassword(clearPassword);
if (pref->getUILockPassword().isEmpty()) {
if (!defineUILockPassword())
return;
}
// Lock the interface
m_uiLocked = true;
pref->setUILocked(true);
@@ -1049,27 +1045,24 @@ bool MainWindow::unlockUI()
{
if (m_unlockDlgShowing)
return false;
else
m_unlockDlgShowing = true;
bool ok = false;
QString clearPassword = AutoExpandableDialog::getText(this, tr("UI lock password"), tr("Please type the UI lock password:"), QLineEdit::Password, "", &ok);
m_unlockDlgShowing = false;
const QString password = AutoExpandableDialog::getText(this, tr("UI lock password")
, tr("Please type the UI lock password:"), QLineEdit::Password, {}, &ok);
if (!ok) return false;
Preferences *const pref = Preferences::instance();
QString realPassMd5 = pref->getUILockPasswordMD5();
QCryptographicHash md5(QCryptographicHash::Md5);
md5.addData(clearPassword.toLocal8Bit());
QString passwordMd5 = md5.result().toHex();
if (realPassMd5 == passwordMd5) {
m_uiLocked = false;
pref->setUILocked(false);
m_trayIconMenu->setEnabled(true);
return true;
const QByteArray secret = pref->getUILockPassword();
if (!Utils::Password::PBKDF2::verify(secret, password)) {
QMessageBox::warning(this, tr("Invalid password"), tr("The password is invalid"));
return false;
}
QMessageBox::warning(this, tr("Invalid password"), tr("The password is invalid"));
return false;
m_uiLocked = false;
pref->setUILocked(false);
m_trayIconMenu->setEnabled(true);
return true;
}
void MainWindow::notifyOfUpdate(QString)

View File

@@ -109,7 +109,7 @@ private slots:
void fullDiskError(BitTorrent::TorrentHandle *const torrent, QString msg) const;
void handleDownloadFromUrlFailure(QString, QString) const;
void tabChanged(int newTab);
void defineUILockPassword();
bool defineUILockPassword();
void clearUILockPassword();
bool unlockUI();
void notifyOfUpdate(QString);

View File

@@ -59,6 +59,7 @@
#include "base/torrentfileguard.h"
#include "base/unicodestrings.h"
#include "base/utils/fs.h"
#include "base/utils/password.h"
#include "base/utils/random.h"
#include "addnewtorrentdialog.h"
#include "advancedsettings.h"
@@ -728,7 +729,8 @@ void OptionsDialog::saveOptions()
}
// Authentication
pref->setWebUiUsername(webUiUsername());
pref->setWebUiPassword(webUiPassword());
if (!webUiPassword().isEmpty())
pref->setWebUIPassword(Utils::Password::PBKDF2::generate(webUiPassword()));
pref->setWebUiLocalAuthEnabled(!m_ui->checkBypassLocalAuth->isChecked());
pref->setWebUiAuthSubnetWhitelistEnabled(m_ui->checkBypassAuthSubnetWhitelist->isChecked());
// Security
@@ -1090,7 +1092,6 @@ void OptionsDialog::loadOptions()
setSslCertificate(pref->getWebUiHttpsCertificate());
setSslKey(pref->getWebUiHttpsKey());
m_ui->textWebUiUsername->setText(pref->getWebUiUsername());
m_ui->textWebUiPassword->setText(pref->getWebUiPassword());
m_ui->checkBypassLocalAuth->setChecked(!pref->isWebUiLocalAuthEnabled());
m_ui->checkBypassAuthSubnetWhitelist->setChecked(pref->isWebUiAuthSubnetWhitelistEnabled());
m_ui->IPSubnetWhitelistButton->setEnabled(m_ui->checkBypassAuthSubnetWhitelist->isChecked());
@@ -1743,7 +1744,7 @@ bool OptionsDialog::webUIAuthenticationOk()
QMessageBox::warning(this, tr("Length Error"), tr("The Web UI username must be at least 3 characters long."));
return false;
}
if (webUiPassword().length() < 6) {
if (!webUiPassword().isEmpty() && (webUiPassword().length() < 6)) {
QMessageBox::warning(this, tr("Length Error"), tr("The Web UI password must be at least 6 characters long."));
return false;
}

View File

@@ -3074,15 +3074,12 @@ Specify an IPv4 or IPv6 address. You can specify &quot;0.0.0.0&quot; for any IPv
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="textWebUiPassword">
<property name="text">
<string/>
</property>
<property name="maxLength">
<number>1000</number>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
<property name="placeholderText">
<string>Change current password</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">