Fix multiple password changes in one session

This commit is contained in:
savilli 2024-01-19 11:50:55 +01:00 committed by GitHub
parent a8cf10b0b5
commit 432988a4ad
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 23 additions and 15 deletions

@ -19,6 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <sstream>
#include "clientiface.h"
#include "debug.h"
#include "network/connection.h"
#include "network/serveropcodes.h"
#include "remoteplayer.h"
@ -31,6 +32,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "server/player_sao.h"
#include "log.h"
#include "util/srp.h"
#include "util/string.h"
#include "face_position_cache.h"
static std::string string_sanitize_ascii(const std::string &s, u32 max_length)
@ -649,6 +651,14 @@ void RemoteClient::resetChosenMech()
chosen_mech = AUTH_MECHANISM_NONE;
}
void RemoteClient::setEncryptedPassword(const std::string& pwd)
{
FATAL_ERROR_IF(!str_starts_with(pwd, "#1#"), "must be srp");
enc_pwd = pwd;
// We just set SRP encrypted password, we accept only it now
allowed_auth_mechs = AUTH_MECHANISM_SRP;
}
void RemoteClient::setVersionInfo(u8 major, u8 minor, u8 patch, const std::string &full)
{
m_version_major = major;

@ -243,15 +243,14 @@ public:
AuthMechanism chosen_mech = AUTH_MECHANISM_NONE;
void *auth_data = nullptr;
u32 allowed_auth_mechs = 0;
u32 allowed_sudo_mechs = 0;
void resetChosenMech();
bool isSudoMechAllowed(AuthMechanism mech)
{ return allowed_sudo_mechs & mech; }
bool isMechAllowed(AuthMechanism mech)
{ return allowed_auth_mechs & mech; }
void setEncryptedPassword(const std::string& pwd);
RemoteClient();
~RemoteClient() = default;

@ -1515,8 +1515,7 @@ void Server::handleCommand_FirstSrp(NetworkPacket* pkt)
return;
}
std::string initial_ver_key;
initial_ver_key = encode_srp_verifier(verification_key, salt);
std::string encpwd = encode_srp_verifier(verification_key, salt);
// It is possible for multiple connections to get this far with the same
// player name. In the end only one player with a given name will be emerged
@ -1529,9 +1528,11 @@ void Server::handleCommand_FirstSrp(NetworkPacket* pkt)
DenyAccess(peer_id, SERVER_ACCESSDENIED_ALREADY_CONNECTED);
return;
}
m_script->createAuth(playername, initial_ver_key);
m_script->on_authplayer(playername, addr_s, true);
m_script->createAuth(playername, encpwd);
client->setEncryptedPassword(encpwd);
m_script->on_authplayer(playername, addr_s, true);
acceptAuth(peer_id, false);
} else {
if (cstate < CS_SudoMode) {
@ -1550,12 +1551,13 @@ void Server::handleCommand_FirstSrp(NetworkPacket* pkt)
return;
}
std::string pw_db_field = encode_srp_verifier(verification_key, salt);
bool success = m_script->setPassword(playername, pw_db_field);
std::string encpwd = encode_srp_verifier(verification_key, salt);
bool success = m_script->setPassword(playername, encpwd);
if (success) {
actionstream << playername << " changes password" << std::endl;
SendChatMessage(peer_id, ChatMessage(CHATMESSAGE_TYPE_SYSTEM,
L"Password change successful."));
client->setEncryptedPassword(encpwd);
} else {
actionstream << playername <<
" tries to change password but it fails" << std::endl;
@ -1606,7 +1608,8 @@ void Server::handleCommand_SrpBytesA(NetworkPacket* pkt)
AUTH_MECHANISM_LEGACY_PASSWORD : AUTH_MECHANISM_SRP;
if (wantSudo) {
if (!client->isSudoMechAllowed(chosen)) {
// Right now, the auth mechs don't change between login and sudo mode.
if (!client->isMechAllowed(chosen)) {
actionstream << "Server: Player \"" << client->getName() <<
"\" at " << getPeerAddress(peer_id).serializeString() <<
" tried to change password using unallowed mech " << chosen <<

@ -2902,13 +2902,9 @@ void Server::acceptAuth(session_t peer_id, bool forSudoMode)
NetworkPacket resp_pkt(TOCLIENT_AUTH_ACCEPT, 1 + 6 + 8 + 4, peer_id);
// Right now, the auth mechs don't change between login and sudo mode.
u32 sudo_auth_mechs = client->allowed_auth_mechs;
client->allowed_sudo_mechs = sudo_auth_mechs;
resp_pkt << v3f(0,0,0) << (u64) m_env->getServerMap().getSeed()
<< g_settings->getFloat("dedicated_server_step")
<< sudo_auth_mechs;
<< client->allowed_auth_mechs;
Send(&resp_pkt);
m_clients.event(peer_id, CSE_AuthAccept);