From 45d86e7ab75caa7de0ccab493f3c75ceee1ddcef Mon Sep 17 00:00:00 2001 From: ebbit1q Date: Wed, 10 Nov 2021 02:00:41 +0100 Subject: [PATCH] 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 --- cockatrice/src/abstractclient.h | 1 + cockatrice/src/localserver.cpp | 3 +- cockatrice/src/localserver.h | 3 +- cockatrice/src/remoteclient.cpp | 65 +++++++++++++++++-- cockatrice/src/remoteclient.h | 5 ++ common/CMakeLists.txt | 5 +- common/featureset.cpp | 2 + {servatrice/src => common}/passwordhasher.cpp | 0 {servatrice/src => common}/passwordhasher.h | 0 common/pb/CMakeLists.txt | 5 +- common/pb/event_server_identification.proto | 5 ++ common/pb/response.proto | 1 + common/pb/response_password_salt.proto | 9 +++ common/pb/session_commands.proto | 9 +++ common/server.cpp | 5 +- common/server.h | 1 + common/server_database_interface.h | 7 +- common/server_protocolhandler.cpp | 26 ++++++-- servatrice/CMakeLists.txt | 1 - .../src/servatrice_database_interface.cpp | 33 +++++++++- .../src/servatrice_database_interface.h | 4 +- servatrice/src/serversocketinterface.cpp | 26 ++++++++ servatrice/src/serversocketinterface.h | 3 +- 23 files changed, 193 insertions(+), 26 deletions(-) rename {servatrice/src => common}/passwordhasher.cpp (100%) rename {servatrice/src => common}/passwordhasher.h (100%) create mode 100644 common/pb/response_password_salt.proto diff --git a/cockatrice/src/abstractclient.h b/cockatrice/src/abstractclient.h index 75956f76..f58c4186 100644 --- a/cockatrice/src/abstractclient.h +++ b/cockatrice/src/abstractclient.h @@ -40,6 +40,7 @@ enum ClientStatus StatusRequestingForgotPassword, StatusSubmitForgotPasswordReset, StatusSubmitForgotPasswordChallenge, + StatusGettingPasswordSalt, }; class AbstractClient : public QObject diff --git a/cockatrice/src/localserver.cpp b/cockatrice/src/localserver.cpp index f4e4ebfa..cf3b01d0 100644 --- a/cockatrice/src/localserver.cpp +++ b/cockatrice/src/localserver.cpp @@ -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; } diff --git a/cockatrice/src/localserver.h b/cockatrice/src/localserver.h index 7b62dcbe..a48abdca 100644 --- a/cockatrice/src/localserver.h +++ b/cockatrice/src/localserver.h @@ -32,7 +32,8 @@ public: const QString &password, const QString &clientId, QString &reasonStr, - int &secondsLeft); + int &secondsLeft, + bool passwordNeedsHash); int getNextGameId() { return localServer->getNextLocalGameId(); diff --git a/cockatrice/src/remoteclient.cpp b/cockatrice/src/remoteclient.cpp index 47f22744..5f2dabfa 100644 --- a/cockatrice/src/remoteclient.cpp +++ b/cockatrice/src/remoteclient.cpp @@ -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); diff --git a/cockatrice/src/remoteclient.h b/cockatrice/src/remoteclient.h index 9ae7e628..d1e1eec7 100644 --- a/cockatrice/src/remoteclient.h +++ b/cockatrice/src/remoteclient.h @@ -2,6 +2,7 @@ #define REMOTECLIENT_H #include "abstractclient.h" +#include "pb/commands.pb.h" #include #include @@ -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); diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index cf04f195..65064274 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -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) diff --git a/common/featureset.cpp b/common/featureset.cpp index 0151d5c0..d4b161cf 100644 --- a/common/featureset.cpp +++ b/common/featureset.cpp @@ -15,6 +15,7 @@ QMap FeatureSet::getDefaultFeatureList() void FeatureSet::initalizeFeatureList(QMap &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 &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); diff --git a/servatrice/src/passwordhasher.cpp b/common/passwordhasher.cpp similarity index 100% rename from servatrice/src/passwordhasher.cpp rename to common/passwordhasher.cpp diff --git a/servatrice/src/passwordhasher.h b/common/passwordhasher.h similarity index 100% rename from servatrice/src/passwordhasher.h rename to common/passwordhasher.h diff --git a/common/pb/CMakeLists.txt b/common/pb/CMakeLists.txt index 9c120b90..eccae53d 100644 --- a/common/pb/CMakeLists.txt +++ b/common/pb/CMakeLists.txt @@ -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 diff --git a/common/pb/event_server_identification.proto b/common/pb/event_server_identification.proto index 6548043e..987ab20d 100644 --- a/common/pb/event_server_identification.proto +++ b/common/pb/event_server_identification.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]; } diff --git a/common/pb/response.proto b/common/pb/response.proto index a4de4cb9..8ff96c1c 100644 --- a/common/pb/response.proto +++ b/common/pb/response.proto @@ -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; } diff --git a/common/pb/response_password_salt.proto b/common/pb/response_password_salt.proto new file mode 100644 index 00000000..3fc22853 --- /dev/null +++ b/common/pb/response_password_salt.proto @@ -0,0 +1,9 @@ +syntax = "proto2"; +import "response.proto"; + +message Response_PasswordSalt { + extend Response { + optional Response_PasswordSalt ext = 1017; + } + optional string password_salt = 1; +} diff --git a/common/pb/session_commands.proto b/common/pb/session_commands.proto index f231abef..0260aa98 100644 --- a/common/pb/session_commands.proto +++ b/common/pb/session_commands.proto @@ -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; +} diff --git a/common/server.cpp b/common/server.cpp index 2a637e4e..af940142 100644 --- a/common/server.cpp +++ b/common/server.cpp @@ -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; diff --git a/common/server.h b/common/server.h index 259318ac..dc722042 100644 --- a/common/server.h +++ b/common/server.h @@ -62,6 +62,7 @@ public: AuthenticationResult loginUser(Server_ProtocolHandler *session, QString &name, const QString &password, + bool passwordNeedsHash, QString &reason, int &secondsLeft, QString &clientid, diff --git a/common/server_database_interface.h b/common/server_database_interface.h index a95603e3..95fc2916 100644 --- a/common/server_database_interface.h +++ b/common/server_database_interface.h @@ -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 getBuddyList(const QString & /* name */) { return QMap(); diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 9036d607..56c37dcd 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -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 receivedClientFeatures; QMap 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::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; diff --git a/servatrice/CMakeLists.txt b/servatrice/CMakeLists.txt index 37360bef..56995867 100644 --- a/servatrice/CMakeLists.txt +++ b/servatrice/CMakeLists.txt @@ -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 diff --git a/servatrice/src/servatrice_database_interface.cpp b/servatrice/src/servatrice_database_interface.cpp index aceb4c46..601f5099 100644 --- a/servatrice/src/servatrice_database_interface.cpp +++ b/servatrice/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) { diff --git a/servatrice/src/servatrice_database_interface.h b/servatrice/src/servatrice_database_interface.h index 2c225b82..5d6f0abe 100644 --- a/servatrice/src/servatrice_database_interface.h +++ b/servatrice/src/servatrice_database_interface.h @@ -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 getBuddyList(const QString &name); QMap getIgnoreList(const QString &name); diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index 914a573a..417a21e8 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -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. diff --git a/servatrice/src/serversocketinterface.h b/servatrice/src/serversocketinterface.h index cc209b33..62acf225 100644 --- a/servatrice/src/serversocketinterface.h +++ b/servatrice/src/serversocketinterface.h @@ -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