allow login using hashed passwords (#4464)
* Support getting a user's password salt via initial websocket connection (added to Event_ServerIdentification) * Nonsense stuff to figure out later * move passwordhasher to correct location * protobuf changes * add ext to protobuf * implement request password salt server side * add supportspasswordhash to server identification * check backwards compatibility * reset some changes to master * implement get password salt client side * implement checking hashed passwords on server login * check for registration requirement on getting password salt * properly check password salt response and show errors * remove unused property * add password salt to list of response types Co-authored-by: ZeldaZach <zahalpern+github@gmail.com>
This commit is contained in:
parent
b0845837c2
commit
45d86e7ab7
23 changed files with 193 additions and 26 deletions
|
@ -40,6 +40,7 @@ enum ClientStatus
|
|||
StatusRequestingForgotPassword,
|
||||
StatusSubmitForgotPasswordReset,
|
||||
StatusSubmitForgotPasswordChallenge,
|
||||
StatusGettingPasswordSalt,
|
||||
};
|
||||
|
||||
class AbstractClient : public QObject
|
||||
|
|
|
@ -42,7 +42,8 @@ AuthenticationResult LocalServer_DatabaseInterface::checkUserPassword(Server_Pro
|
|||
const QString & /* password */,
|
||||
const QString & /* clientId */,
|
||||
QString & /* reasonStr */,
|
||||
int & /* secondsLeft */)
|
||||
int & /* banSecondsLeft */,
|
||||
bool /* passwordNeedsHash */)
|
||||
{
|
||||
return UnknownUser;
|
||||
}
|
||||
|
|
|
@ -32,7 +32,8 @@ public:
|
|||
const QString &password,
|
||||
const QString &clientId,
|
||||
QString &reasonStr,
|
||||
int &secondsLeft);
|
||||
int &secondsLeft,
|
||||
bool passwordNeedsHash);
|
||||
int getNextGameId()
|
||||
{
|
||||
return localServer->getNextLocalGameId();
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
#include "remoteclient.h"
|
||||
|
||||
#include "main.h"
|
||||
#include "pb/commands.pb.h"
|
||||
#include "passwordhasher.h"
|
||||
#include "pb/event_server_identification.pb.h"
|
||||
#include "pb/response_activate.pb.h"
|
||||
#include "pb/response_forgotpasswordrequest.pb.h"
|
||||
#include "pb/response_login.pb.h"
|
||||
#include "pb/response_password_salt.pb.h"
|
||||
#include "pb/response_register.pb.h"
|
||||
#include "pb/server_message.pb.h"
|
||||
#include "pb/session_commands.pb.h"
|
||||
|
@ -175,15 +176,30 @@ void RemoteClient::processServerIdentificationEvent(const Event_ServerIdentifica
|
|||
return;
|
||||
}
|
||||
|
||||
doLogin();
|
||||
if (!password.isEmpty() && event.server_options() & Event_ServerIdentification::SupportsPasswordHash) {
|
||||
// TODO store and log in using stored hashed password
|
||||
doRequestPasswordSalt(); // log in using password salt
|
||||
} else {
|
||||
// TODO add setting for client to reject unhashed logins
|
||||
doLogin();
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteClient::doLogin()
|
||||
void RemoteClient::doRequestPasswordSalt()
|
||||
{
|
||||
setStatus(StatusGettingPasswordSalt);
|
||||
Command_RequestPasswordSalt cmdRqSalt;
|
||||
cmdRqSalt.set_user_name(userName.toStdString());
|
||||
|
||||
PendingCommand *pend = prepareSessionCommand(cmdRqSalt);
|
||||
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(passwordSaltResponse(Response)));
|
||||
sendCommand(pend);
|
||||
}
|
||||
|
||||
Command_Login RemoteClient::generateCommandLogin()
|
||||
{
|
||||
setStatus(StatusLoggingIn);
|
||||
Command_Login cmdLogin;
|
||||
cmdLogin.set_user_name(userName.toStdString());
|
||||
cmdLogin.set_password(password.toStdString());
|
||||
cmdLogin.set_clientid(getSrvClientID(lastHostname).toStdString());
|
||||
cmdLogin.set_clientver(VERSION_STRING);
|
||||
|
||||
|
@ -192,6 +208,29 @@ void RemoteClient::doLogin()
|
|||
for (i = clientFeatures.begin(); i != clientFeatures.end(); ++i)
|
||||
cmdLogin.add_clientfeatures(i.key().toStdString().c_str());
|
||||
}
|
||||
|
||||
return cmdLogin;
|
||||
}
|
||||
|
||||
void RemoteClient::doLogin()
|
||||
{
|
||||
setStatus(StatusLoggingIn);
|
||||
Command_Login cmdLogin = generateCommandLogin();
|
||||
cmdLogin.set_password(password.toStdString());
|
||||
|
||||
PendingCommand *pend = prepareSessionCommand(cmdLogin);
|
||||
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(loginResponse(Response)));
|
||||
sendCommand(pend);
|
||||
}
|
||||
|
||||
void RemoteClient::doLogin(const QString &passwordSalt)
|
||||
{
|
||||
setStatus(StatusLoggingIn);
|
||||
Command_Login cmdLogin = generateCommandLogin();
|
||||
|
||||
const auto hashedPassword = PasswordHasher::computeHash(password, passwordSalt);
|
||||
cmdLogin.set_hashed_password(hashedPassword.toStdString());
|
||||
|
||||
PendingCommand *pend = prepareSessionCommand(cmdLogin);
|
||||
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(loginResponse(Response)));
|
||||
sendCommand(pend);
|
||||
|
@ -202,6 +241,22 @@ void RemoteClient::processConnectionClosedEvent(const Event_ConnectionClosed & /
|
|||
doDisconnectFromServer();
|
||||
}
|
||||
|
||||
void RemoteClient::passwordSaltResponse(const Response &response)
|
||||
{
|
||||
if (response.response_code() == Response::RespOk) {
|
||||
const Response_PasswordSalt &resp = response.GetExtension(Response_PasswordSalt::ext);
|
||||
QString salt = QString::fromStdString(resp.password_salt());
|
||||
if (salt.isEmpty()) { // the server does not recognize the user but allows them to enter unregistered
|
||||
password = ""; // the password will not be used
|
||||
doLogin();
|
||||
} else {
|
||||
doLogin(salt);
|
||||
}
|
||||
} else if (response.response_code() != Response::RespNotConnected) {
|
||||
emit loginError(response.response_code(), {}, 0, {});
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteClient::loginResponse(const Response &response)
|
||||
{
|
||||
const Response_Login &resp = response.GetExtension(Response_Login::ext);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define REMOTECLIENT_H
|
||||
|
||||
#include "abstractclient.h"
|
||||
#include "pb/commands.pb.h"
|
||||
|
||||
#include <QTcpSocket>
|
||||
#include <QWebSocket>
|
||||
|
@ -55,6 +56,7 @@ private slots:
|
|||
void ping();
|
||||
void processServerIdentificationEvent(const Event_ServerIdentification &event);
|
||||
void processConnectionClosedEvent(const Event_ConnectionClosed &event);
|
||||
void passwordSaltResponse(const Response &response);
|
||||
void loginResponse(const Response &response);
|
||||
void registerResponse(const Response &response);
|
||||
void activateResponse(const Response &response);
|
||||
|
@ -68,7 +70,10 @@ private slots:
|
|||
int _gender,
|
||||
const QString &_country,
|
||||
const QString &_realname);
|
||||
void doRequestPasswordSalt();
|
||||
void doLogin();
|
||||
void doLogin(const QString &passwordSalt);
|
||||
Command_Login generateCommandLogin();
|
||||
void doDisconnectFromServer();
|
||||
void doActivateToServer(const QString &_token);
|
||||
void doRequestForgotPasswordToServer(const QString &hostname, unsigned int port, const QString &_userName);
|
||||
|
|
|
@ -6,8 +6,10 @@ add_subdirectory(pb)
|
|||
|
||||
SET(common_SOURCES
|
||||
decklist.cpp
|
||||
expression.cpp
|
||||
featureset.cpp
|
||||
get_pb_extension.cpp
|
||||
passwordhasher.cpp
|
||||
rng_abstract.cpp
|
||||
rng_sfmt.cpp
|
||||
server.cpp
|
||||
|
@ -17,8 +19,8 @@ SET(common_SOURCES
|
|||
server_card.cpp
|
||||
server_cardzone.cpp
|
||||
server_counter.cpp
|
||||
server_game.cpp
|
||||
server_database_interface.cpp
|
||||
server_game.cpp
|
||||
server_player.cpp
|
||||
server_protocolhandler.cpp
|
||||
server_remoteuserinterface.cpp
|
||||
|
@ -26,7 +28,6 @@ SET(common_SOURCES
|
|||
server_room.cpp
|
||||
serverinfo_user_container.cpp
|
||||
sfmt/SFMT.c
|
||||
expression.cpp
|
||||
)
|
||||
|
||||
set(ORACLE_LIBS)
|
||||
|
|
|
@ -15,6 +15,7 @@ QMap<QString, bool> FeatureSet::getDefaultFeatureList()
|
|||
|
||||
void FeatureSet::initalizeFeatureList(QMap<QString, bool> &featureList)
|
||||
{
|
||||
// default features [name], [is required to connect]
|
||||
featureList.insert("client_id", false);
|
||||
featureList.insert("client_ver", false);
|
||||
featureList.insert("feature_set", false);
|
||||
|
@ -25,6 +26,7 @@ void FeatureSet::initalizeFeatureList(QMap<QString, bool> &featureList)
|
|||
featureList.insert("idle_client", false);
|
||||
featureList.insert("forgot_password", false);
|
||||
featureList.insert("websocket", false);
|
||||
featureList.insert("hashed_password_login", false);
|
||||
// These are temp to force users onto a newer client
|
||||
featureList.insert("2.7.0_min_version", false);
|
||||
featureList.insert("2.8.0_min_version", false);
|
||||
|
|
|
@ -115,6 +115,7 @@ SET(PROTO_FILES
|
|||
moderator_commands.proto
|
||||
move_card_to_zone.proto
|
||||
response_activate.proto
|
||||
response_adjust_mod.proto
|
||||
response_ban_history.proto
|
||||
response_deck_download.proto
|
||||
response_deck_list.proto
|
||||
|
@ -126,13 +127,13 @@ SET(PROTO_FILES
|
|||
response_join_room.proto
|
||||
response_list_users.proto
|
||||
response_login.proto
|
||||
response_password_salt.proto
|
||||
response_register.proto
|
||||
response_replay_download.proto
|
||||
response_replay_list.proto
|
||||
response_adjust_mod.proto
|
||||
response_viewlog_history.proto
|
||||
response_warn_history.proto
|
||||
response_warn_list.proto
|
||||
response_viewlog_history.proto
|
||||
response.proto
|
||||
room_commands.proto
|
||||
room_event.proto
|
||||
|
|
|
@ -5,7 +5,12 @@ message Event_ServerIdentification {
|
|||
extend SessionEvent {
|
||||
optional Event_ServerIdentification ext = 500;
|
||||
}
|
||||
enum ServerOptions {
|
||||
NoOptions = 0;
|
||||
SupportsPasswordHash = 1;
|
||||
}
|
||||
optional string server_name = 1;
|
||||
optional string server_version = 2;
|
||||
optional uint32 protocol_version = 3;
|
||||
optional ServerOptions server_options = 4 [default = NoOptions];
|
||||
}
|
||||
|
|
|
@ -61,6 +61,7 @@ message Response {
|
|||
WARN_LIST = 1014;
|
||||
VIEW_LOG = 1015;
|
||||
FORGOT_PASSWORD_REQUEST = 1016;
|
||||
PASSWORD_SALT = 1017;
|
||||
REPLAY_LIST = 1100;
|
||||
REPLAY_DOWNLOAD = 1101;
|
||||
}
|
||||
|
|
9
common/pb/response_password_salt.proto
Normal file
9
common/pb/response_password_salt.proto
Normal file
|
@ -0,0 +1,9 @@
|
|||
syntax = "proto2";
|
||||
import "response.proto";
|
||||
|
||||
message Response_PasswordSalt {
|
||||
extend Response {
|
||||
optional Response_PasswordSalt ext = 1017;
|
||||
}
|
||||
optional string password_salt = 1;
|
||||
}
|
|
@ -27,6 +27,7 @@ message SessionCommand {
|
|||
FORGOT_PASSWORD_REQUEST = 1021;
|
||||
FORGOT_PASSWORD_RESET = 1022;
|
||||
FORGOT_PASSWORD_CHALLENGE = 1023;
|
||||
REQUEST_PASSWORD_SALT = 1024;
|
||||
REPLAY_LIST = 1100;
|
||||
REPLAY_DOWNLOAD = 1101;
|
||||
REPLAY_MODIFY_MATCH = 1102;
|
||||
|
@ -50,6 +51,7 @@ message Command_Login {
|
|||
optional string clientid = 3;
|
||||
optional string clientver = 4;
|
||||
repeated string clientfeatures = 5;
|
||||
optional string hashed_password = 6;
|
||||
}
|
||||
|
||||
message Command_Message {
|
||||
|
@ -191,3 +193,10 @@ message Command_ForgotPasswordChallenge {
|
|||
optional string clientid = 2;
|
||||
optional string email = 3;
|
||||
}
|
||||
|
||||
message Command_RequestPasswordSalt {
|
||||
extend SessionCommand {
|
||||
optional Command_RequestPasswordSalt ext = 1024;
|
||||
}
|
||||
required string user_name = 1;
|
||||
}
|
||||
|
|
|
@ -79,6 +79,7 @@ Server_DatabaseInterface *Server::getDatabaseInterface() const
|
|||
AuthenticationResult Server::loginUser(Server_ProtocolHandler *session,
|
||||
QString &name,
|
||||
const QString &password,
|
||||
bool passwordNeedsHash,
|
||||
QString &reasonStr,
|
||||
int &secondsLeft,
|
||||
QString &clientid,
|
||||
|
@ -99,8 +100,8 @@ AuthenticationResult Server::loginUser(Server_ProtocolHandler *session,
|
|||
|
||||
Server_DatabaseInterface *databaseInterface = getDatabaseInterface();
|
||||
|
||||
AuthenticationResult authState =
|
||||
databaseInterface->checkUserPassword(session, name, password, clientid, reasonStr, secondsLeft);
|
||||
AuthenticationResult authState = databaseInterface->checkUserPassword(session, name, password, clientid, reasonStr,
|
||||
secondsLeft, passwordNeedsHash);
|
||||
if (authState == NotLoggedIn || authState == UserIsBanned || authState == UsernameInvalid ||
|
||||
authState == UserIsInactive)
|
||||
return authState;
|
||||
|
|
|
@ -62,6 +62,7 @@ public:
|
|||
AuthenticationResult loginUser(Server_ProtocolHandler *session,
|
||||
QString &name,
|
||||
const QString &password,
|
||||
bool passwordNeedsHash,
|
||||
QString &reason,
|
||||
int &secondsLeft,
|
||||
QString &clientid,
|
||||
|
|
|
@ -18,7 +18,8 @@ public:
|
|||
const QString &password,
|
||||
const QString &clientId,
|
||||
QString &reasonStr,
|
||||
int &secondsLeft) = 0;
|
||||
int &secondsLeft,
|
||||
bool passwordNeedsHash) = 0;
|
||||
virtual bool checkUserIsBanned(const QString & /* ipAddress */,
|
||||
const QString & /* userName */,
|
||||
const QString & /* clientId */,
|
||||
|
@ -35,6 +36,10 @@ public:
|
|||
{
|
||||
return false;
|
||||
}
|
||||
virtual QString getUserSalt(const QString & /* user */)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
virtual QMap<QString, ServerInfo_User> getBuddyList(const QString & /* name */)
|
||||
{
|
||||
return QMap<QString, ServerInfo_User>();
|
||||
|
|
|
@ -440,21 +440,32 @@ Response::ResponseCode Server_ProtocolHandler::cmdPing(const Command_Ping & /*cm
|
|||
|
||||
Response::ResponseCode Server_ProtocolHandler::cmdLogin(const Command_Login &cmd, ResponseContainer &rc)
|
||||
{
|
||||
|
||||
QString userName = QString::fromStdString(cmd.user_name()).simplified();
|
||||
QString clientId = QString::fromStdString(cmd.clientid()).simplified();
|
||||
QString clientVersion = QString::fromStdString(cmd.clientver()).simplified();
|
||||
|
||||
if (userInfo != 0)
|
||||
QString password;
|
||||
bool needsHash = false;
|
||||
if (cmd.has_password()) {
|
||||
password = QString::fromStdString(cmd.password());
|
||||
needsHash = true;
|
||||
} else if (cmd.has_hashed_password()) {
|
||||
password = QString::fromStdString(cmd.hashed_password());
|
||||
} else {
|
||||
return Response::RespContextError;
|
||||
}
|
||||
|
||||
if (userInfo != 0) {
|
||||
return Response::RespContextError;
|
||||
}
|
||||
|
||||
// check client feature set against server feature set
|
||||
FeatureSet features;
|
||||
QMap<QString, bool> receivedClientFeatures;
|
||||
QMap<QString, bool> missingClientFeatures;
|
||||
|
||||
for (int i = 0; i < cmd.clientfeatures().size(); ++i)
|
||||
for (int i = 0; i < cmd.clientfeatures().size(); ++i) {
|
||||
receivedClientFeatures.insert(QString::fromStdString(cmd.clientfeatures(i)).simplified(), false);
|
||||
}
|
||||
|
||||
missingClientFeatures =
|
||||
features.identifyMissingFeatures(receivedClientFeatures, server->getServerRequiredFeatureList());
|
||||
|
@ -464,8 +475,9 @@ Response::ResponseCode Server_ProtocolHandler::cmdLogin(const Command_Login &cmd
|
|||
Response_Login *re = new Response_Login;
|
||||
re->set_denied_reason_str("Client upgrade required");
|
||||
QMap<QString, bool>::iterator i;
|
||||
for (i = missingClientFeatures.begin(); i != missingClientFeatures.end(); ++i)
|
||||
for (i = missingClientFeatures.begin(); i != missingClientFeatures.end(); ++i) {
|
||||
re->add_missing_features(i.key().toStdString().c_str());
|
||||
}
|
||||
rc.setResponseExtension(re);
|
||||
return Response::RespClientUpdateRequired;
|
||||
}
|
||||
|
@ -474,8 +486,8 @@ Response::ResponseCode Server_ProtocolHandler::cmdLogin(const Command_Login &cmd
|
|||
QString reasonStr;
|
||||
int banSecondsLeft = 0;
|
||||
QString connectionType = getConnectionType();
|
||||
AuthenticationResult res = server->loginUser(this, userName, QString::fromStdString(cmd.password()), reasonStr,
|
||||
banSecondsLeft, clientId, clientVersion, connectionType);
|
||||
AuthenticationResult res = server->loginUser(this, userName, password, needsHash, reasonStr, banSecondsLeft,
|
||||
clientId, clientVersion, connectionType);
|
||||
switch (res) {
|
||||
case UserIsBanned: {
|
||||
Response_Login *re = new Response_Login;
|
||||
|
|
|
@ -6,7 +6,6 @@ PROJECT(Servatrice VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${
|
|||
|
||||
SET(servatrice_SOURCES
|
||||
src/main.cpp
|
||||
src/passwordhasher.cpp
|
||||
src/servatrice.cpp
|
||||
src/servatrice_connection_pool.cpp
|
||||
src/servatrice_database_interface.cpp
|
||||
|
|
|
@ -287,7 +287,8 @@ AuthenticationResult Servatrice_DatabaseInterface::checkUserPassword(Server_Prot
|
|||
const QString &password,
|
||||
const QString &clientId,
|
||||
QString &reasonStr,
|
||||
int &banSecondsLeft)
|
||||
int &banSecondsLeft,
|
||||
bool passwordNeedsHash)
|
||||
{
|
||||
switch (server->getAuthenticationMethod()) {
|
||||
case Servatrice::AuthenticationNone:
|
||||
|
@ -324,7 +325,13 @@ AuthenticationResult Servatrice_DatabaseInterface::checkUserPassword(Server_Prot
|
|||
qDebug("Login denied: user not active");
|
||||
return UserIsInactive;
|
||||
}
|
||||
if (correctPassword == PasswordHasher::computeHash(password, correctPassword.left(16))) {
|
||||
QString hashedPassword;
|
||||
if (passwordNeedsHash) {
|
||||
hashedPassword = PasswordHasher::computeHash(password, correctPassword.left(16));
|
||||
} else {
|
||||
hashedPassword = password;
|
||||
}
|
||||
if (correctPassword == hashedPassword) {
|
||||
qDebug("Login accepted: password right");
|
||||
return PasswordRight;
|
||||
} else {
|
||||
|
@ -490,6 +497,28 @@ bool Servatrice_DatabaseInterface::userExists(const QString &user)
|
|||
return false;
|
||||
}
|
||||
|
||||
QString Servatrice_DatabaseInterface::getUserSalt(const QString &user)
|
||||
{
|
||||
if (server->getAuthenticationMethod() == Servatrice::AuthenticationSql) {
|
||||
checkSql();
|
||||
|
||||
QSqlQuery *query =
|
||||
prepareQuery("SELECT SUBSTRING(password_sha512, 1, 16) FROM {prefix}_users WHERE name = :name");
|
||||
|
||||
query->bindValue(":name", user);
|
||||
if (!execSqlQuery(query)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!query->next()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return query->value(0).toString();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
int Servatrice_DatabaseInterface::getUserIdInDB(const QString &name)
|
||||
{
|
||||
if (server->getAuthenticationMethod() == Servatrice::AuthenticationSql) {
|
||||
|
|
|
@ -35,7 +35,8 @@ protected:
|
|||
const QString &password,
|
||||
const QString &clientId,
|
||||
QString &reasonStr,
|
||||
int &secondsLeft);
|
||||
int &banSecondsLeft,
|
||||
bool passwordNeedsHash);
|
||||
|
||||
public slots:
|
||||
void initDatabase(const QSqlDatabase &_sqlDatabase);
|
||||
|
@ -59,6 +60,7 @@ public:
|
|||
|
||||
bool activeUserExists(const QString &user);
|
||||
bool userExists(const QString &user);
|
||||
QString getUserSalt(const QString &user);
|
||||
int getUserIdInDB(const QString &name);
|
||||
QMap<QString, ServerInfo_User> getBuddyList(const QString &name);
|
||||
QMap<QString, ServerInfo_User> getIgnoreList(const QString &name);
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "pb/response_deck_list.pb.h"
|
||||
#include "pb/response_deck_upload.pb.h"
|
||||
#include "pb/response_forgotpasswordrequest.pb.h"
|
||||
#include "pb/response_password_salt.pb.h"
|
||||
#include "pb/response_register.pb.h"
|
||||
#include "pb/response_replay_download.pb.h"
|
||||
#include "pb/response_replay_list.pb.h"
|
||||
|
@ -95,6 +96,9 @@ bool AbstractServerSocketInterface::initSession()
|
|||
identEvent.set_server_name(servatrice->getServerName().toStdString());
|
||||
identEvent.set_server_version(VERSION_STRING);
|
||||
identEvent.set_protocol_version(protocolVersion);
|
||||
if (servatrice->getAuthenticationMethod() == Servatrice::AuthenticationSql) {
|
||||
identEvent.set_server_options(Event_ServerIdentification::SupportsPasswordHash);
|
||||
}
|
||||
SessionEvent *identSe = prepareSessionEvent(identEvent);
|
||||
sendProtocolItem(*identSe);
|
||||
delete identSe;
|
||||
|
@ -193,6 +197,9 @@ Response::ResponseCode AbstractServerSocketInterface::processExtendedSessionComm
|
|||
return cmdAccountImage(cmd.GetExtension(Command_AccountImage::ext), rc);
|
||||
case SessionCommand::ACCOUNT_PASSWORD:
|
||||
return cmdAccountPassword(cmd.GetExtension(Command_AccountPassword::ext), rc);
|
||||
case SessionCommand::REQUEST_PASSWORD_SALT:
|
||||
return cmdRequestPasswordSalt(cmd.GetExtension(Command_RequestPasswordSalt::ext), rc);
|
||||
break;
|
||||
default:
|
||||
return Response::RespFunctionNotAllowed;
|
||||
}
|
||||
|
@ -1480,6 +1487,25 @@ AbstractServerSocketInterface::cmdForgotPasswordChallenge(const Command_ForgotPa
|
|||
return continuePasswordRequest(userName, clientId, rc, true);
|
||||
}
|
||||
|
||||
Response::ResponseCode AbstractServerSocketInterface::cmdRequestPasswordSalt(const Command_RequestPasswordSalt &cmd,
|
||||
ResponseContainer &rc)
|
||||
{
|
||||
const QString userName = QString::fromStdString(cmd.user_name());
|
||||
QString passwordSalt = sqlInterface->getUserSalt(userName);
|
||||
if (passwordSalt.isEmpty()) {
|
||||
if (server->getRegOnlyServerEnabled()) {
|
||||
return Response::RespRegistrationRequired;
|
||||
} else {
|
||||
// user does not exist but is allowed to log in unregistered without password
|
||||
return Response::RespOk;
|
||||
}
|
||||
}
|
||||
auto *re = new Response_PasswordSalt;
|
||||
re->set_password_salt(passwordSalt.toStdString());
|
||||
rc.setResponseExtension(re);
|
||||
return Response::RespOk;
|
||||
}
|
||||
|
||||
// ADMIN FUNCTIONS.
|
||||
// Permission is checked by the calling function.
|
||||
|
||||
|
|
|
@ -116,6 +116,7 @@ private:
|
|||
Response::ResponseCode cmdForgotPasswordReset(const Command_ForgotPasswordReset &cmd, ResponseContainer &rc);
|
||||
Response::ResponseCode cmdForgotPasswordChallenge(const Command_ForgotPasswordChallenge &cmd,
|
||||
ResponseContainer &rc);
|
||||
Response::ResponseCode cmdRequestPasswordSalt(const Command_RequestPasswordSalt &cmd, ResponseContainer &rc);
|
||||
Response::ResponseCode processExtendedSessionCommand(int cmdType, const SessionCommand &cmd, ResponseContainer &rc);
|
||||
Response::ResponseCode
|
||||
processExtendedModeratorCommand(int cmdType, const ModeratorCommand &cmd, ResponseContainer &rc);
|
||||
|
@ -198,7 +199,7 @@ class WebsocketServerSocketInterface : public AbstractServerSocketInterface
|
|||
public:
|
||||
WebsocketServerSocketInterface(Servatrice *_server,
|
||||
Servatrice_DatabaseInterface *_databaseInterface,
|
||||
QObject *parent = 0);
|
||||
QObject *parent = nullptr);
|
||||
~WebsocketServerSocketInterface();
|
||||
|
||||
QHostAddress getPeerAddress() const
|
||||
|
|
Loading…
Reference in a new issue