use hashed passwords in all commands (#4493)

* protocol changes

* server changes

* client changes for password reset and registration

* add hashed password to change password in client

* always use hashed password to log in

* add warning to client when using plain text password

* require real password for changing email on server

this is backwards compatible as users logged in with a real password on
older clients will not need this, only users logged in with a hashed
password

* implement password dialog when changing email

* require min password length

* use qstringlist to build query instead

* use clear instead of = ""

* add max to password dialog

* use proper const ness in abstractclient

* reject too long passwords instead of trimming
This commit is contained in:
ebbit1q 2022-01-17 02:32:30 +01:00 committed by GitHub
parent fcafcb340a
commit 2fc85e0c08
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 330 additions and 96 deletions

View file

@ -198,6 +198,7 @@ bool Servatrice_DatabaseInterface::usernameIsValid(const QString &user, QString
bool Servatrice_DatabaseInterface::registerUser(const QString &userName,
const QString &realName,
const QString &password,
bool passwordNeedsHash,
const QString &emailAddress,
const QString &country,
bool active)
@ -205,7 +206,12 @@ bool Servatrice_DatabaseInterface::registerUser(const QString &userName,
if (!checkSql())
return false;
QString passwordSha512 = PasswordHasher::computeHash(password, PasswordHasher::generateRandomSalt());
QString passwordSha512;
if (passwordNeedsHash) {
passwordSha512 = PasswordHasher::computeHash(password, PasswordHasher::generateRandomSalt());
} else {
passwordSha512 = password;
}
QString token = active ? QString() : PasswordHasher::generateActivationToken();
QSqlQuery *query =
@ -303,7 +309,7 @@ AuthenticationResult Servatrice_DatabaseInterface::checkUserPassword(Server_Prot
}
if (passwordQuery->next()) {
const QString correctPassword = passwordQuery->value(0).toString();
const QString correctPasswordSha512 = passwordQuery->value(0).toString();
const bool userIsActive = passwordQuery->value(1).toBool();
if (!userIsActive) {
qDebug("Login denied: user not active");
@ -311,11 +317,11 @@ AuthenticationResult Servatrice_DatabaseInterface::checkUserPassword(Server_Prot
}
QString hashedPassword;
if (passwordNeedsHash) {
hashedPassword = PasswordHasher::computeHash(password, correctPassword.left(16));
hashedPassword = PasswordHasher::computeHash(password, correctPasswordSha512.left(16));
} else {
hashedPassword = password;
}
if (correctPassword == hashedPassword) {
if (correctPasswordSha512 == hashedPassword) {
qDebug("Login accepted: password right");
return PasswordRight;
} else {
@ -935,10 +941,30 @@ void Servatrice_DatabaseInterface::logMessage(const int senderId,
execSqlQuery(query);
}
bool Servatrice_DatabaseInterface::changeUserPassword(const QString &user,
const QString &password,
bool passwordNeedsHash)
{
QString passwordSha512 = password;
if (passwordNeedsHash) {
passwordSha512 = PasswordHasher::computeHash(password, PasswordHasher::generateRandomSalt());
}
QSqlQuery *passwordQuery = prepareQuery("update {prefix}_users set password_sha512=:password, "
"passwordLastChangedDate = NOW() where name = :name");
passwordQuery->bindValue(":password", passwordSha512);
passwordQuery->bindValue(":name", user);
if (execSqlQuery(passwordQuery))
return true;
return false;
}
bool Servatrice_DatabaseInterface::changeUserPassword(const QString &user,
const QString &oldPassword,
bool oldPasswordNeedsHash,
const QString &newPassword,
const bool &force = false)
bool newPasswordNeedsHash)
{
if (server->getAuthenticationMethod() != Servatrice::AuthenticationSql)
return false;
@ -953,30 +979,24 @@ bool Servatrice_DatabaseInterface::changeUserPassword(const QString &user,
QSqlQuery *passwordQuery = prepareQuery("select password_sha512 from {prefix}_users where name = :name");
passwordQuery->bindValue(":name", user);
if (!force) {
if (!execSqlQuery(passwordQuery)) {
qDebug("Change password denied: SQL error");
return false;
}
if (!passwordQuery->next())
return false;
const QString correctPassword = passwordQuery->value(0).toString();
if (correctPassword != PasswordHasher::computeHash(oldPassword, correctPassword.left(16)))
return false;
if (!execSqlQuery(passwordQuery)) {
qDebug("Change password denied: SQL error");
return false;
}
QString passwordSha512 = PasswordHasher::computeHash(newPassword, PasswordHasher::generateRandomSalt());
if (!passwordQuery->next())
return false;
passwordQuery = prepareQuery("update {prefix}_users set password_sha512=:password, "
"passwordLastChangedDate = NOW() where name = :name");
passwordQuery->bindValue(":password", passwordSha512);
passwordQuery->bindValue(":name", user);
if (execSqlQuery(passwordQuery))
return true;
const QString correctPasswordSha512 = passwordQuery->value(0).toString();
QString oldPasswordSha512 = oldPassword;
if (oldPasswordNeedsHash) {
QString salt = correctPasswordSha512.left(16);
oldPasswordSha512 = PasswordHasher::computeHash(oldPassword, salt);
}
if (correctPasswordSha512 != oldPasswordSha512)
return false;
return false;
return changeUserPassword(user, newPassword, newPasswordNeedsHash);
}
int Servatrice_DatabaseInterface::getActiveUserCount(QString connectionType)