Clean up some auth packet handling related code

This commit is contained in:
sfan5 2022-04-27 19:55:13 +02:00
parent 00f71c3b9d
commit a65f6f07f3
9 changed files with 52 additions and 98 deletions

@ -472,20 +472,14 @@ void RemoteClient::notifyEvent(ClientStateEvent event)
{ {
case CSE_AuthAccept: case CSE_AuthAccept:
m_state = CS_AwaitingInit2; m_state = CS_AwaitingInit2;
if (chosen_mech == AUTH_MECHANISM_SRP || resetChosenMech();
chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD)
srp_verifier_delete((SRPVerifier *) auth_data);
chosen_mech = AUTH_MECHANISM_NONE;
break; break;
case CSE_Disconnect: case CSE_Disconnect:
m_state = CS_Disconnecting; m_state = CS_Disconnecting;
break; break;
case CSE_SetDenied: case CSE_SetDenied:
m_state = CS_Denied; m_state = CS_Denied;
if (chosen_mech == AUTH_MECHANISM_SRP || resetChosenMech();
chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD)
srp_verifier_delete((SRPVerifier *) auth_data);
chosen_mech = AUTH_MECHANISM_NONE;
break; break;
default: default:
myerror << "HelloSent: Invalid client state transition! " << event; myerror << "HelloSent: Invalid client state transition! " << event;
@ -561,9 +555,7 @@ void RemoteClient::notifyEvent(ClientStateEvent event)
break; break;
case CSE_SudoSuccess: case CSE_SudoSuccess:
m_state = CS_SudoMode; m_state = CS_SudoMode;
if (chosen_mech == AUTH_MECHANISM_SRP) resetChosenMech();
srp_verifier_delete((SRPVerifier *) auth_data);
chosen_mech = AUTH_MECHANISM_NONE;
break; break;
/* Init GotInit2 SetDefinitionsSent SetMediaSent SetDenied */ /* Init GotInit2 SetDefinitionsSent SetMediaSent SetDenied */
default: default:
@ -598,7 +590,7 @@ void RemoteClient::notifyEvent(ClientStateEvent event)
void RemoteClient::resetChosenMech() void RemoteClient::resetChosenMech()
{ {
if (chosen_mech == AUTH_MECHANISM_SRP) { if (auth_data) {
srp_verifier_delete((SRPVerifier *) auth_data); srp_verifier_delete((SRPVerifier *) auth_data);
auth_data = nullptr; auth_data = nullptr;
} }

@ -183,7 +183,7 @@ void Client::handleCommand_AccessDenied(NetworkPacket* pkt)
m_access_denied_reason = "Unknown"; m_access_denied_reason = "Unknown";
if (pkt->getCommand() != TOCLIENT_ACCESS_DENIED) { if (pkt->getCommand() != TOCLIENT_ACCESS_DENIED) {
// 13/03/15 Legacy code from 0.4.12 and lesser but is still used // Legacy code from 0.4.12 and older but is still used
// in some places of the server code // in some places of the server code
if (pkt->getSize() >= 2) { if (pkt->getSize() >= 2) {
std::wstring wide_reason; std::wstring wide_reason;
@ -196,14 +196,14 @@ void Client::handleCommand_AccessDenied(NetworkPacket* pkt)
if (pkt->getSize() < 1) if (pkt->getSize() < 1)
return; return;
u8 denyCode = SERVER_ACCESSDENIED_UNEXPECTED_DATA; u8 denyCode;
*pkt >> denyCode; *pkt >> denyCode;
if (denyCode == SERVER_ACCESSDENIED_SHUTDOWN || if (denyCode == SERVER_ACCESSDENIED_SHUTDOWN ||
denyCode == SERVER_ACCESSDENIED_CRASH) { denyCode == SERVER_ACCESSDENIED_CRASH) {
*pkt >> m_access_denied_reason; *pkt >> m_access_denied_reason;
if (m_access_denied_reason.empty()) { if (m_access_denied_reason.empty())
m_access_denied_reason = accessDeniedStrings[denyCode]; m_access_denied_reason = accessDeniedStrings[denyCode];
}
u8 reconnect; u8 reconnect;
*pkt >> reconnect; *pkt >> reconnect;
m_access_denied_reconnect = reconnect & 1; m_access_denied_reconnect = reconnect & 1;
@ -220,11 +220,10 @@ void Client::handleCommand_AccessDenied(NetworkPacket* pkt)
// Until then (which may be never), this is outside // Until then (which may be never), this is outside
// of the defined protocol. // of the defined protocol.
*pkt >> m_access_denied_reason; *pkt >> m_access_denied_reason;
if (m_access_denied_reason.empty()) { if (m_access_denied_reason.empty())
m_access_denied_reason = "Unknown"; m_access_denied_reason = "Unknown";
} }
} }
}
void Client::handleCommand_RemoveNode(NetworkPacket* pkt) void Client::handleCommand_RemoveNode(NetworkPacket* pkt)
{ {

@ -1006,7 +1006,7 @@ enum AuthMechanism
AUTH_MECHANISM_FIRST_SRP = 1 << 2, AUTH_MECHANISM_FIRST_SRP = 1 << 2,
}; };
enum AccessDeniedCode { enum AccessDeniedCode : u8 {
SERVER_ACCESSDENIED_WRONG_PASSWORD, SERVER_ACCESSDENIED_WRONG_PASSWORD,
SERVER_ACCESSDENIED_UNEXPECTED_DATA, SERVER_ACCESSDENIED_UNEXPECTED_DATA,
SERVER_ACCESSDENIED_SINGLEPLAYER, SERVER_ACCESSDENIED_SINGLEPLAYER,
@ -1029,18 +1029,18 @@ enum NetProtoCompressionMode {
const static std::string accessDeniedStrings[SERVER_ACCESSDENIED_MAX] = { const static std::string accessDeniedStrings[SERVER_ACCESSDENIED_MAX] = {
"Invalid password", "Invalid password",
"Your client sent something the server didn't expect. Try reconnecting or updating your client", "Your client sent something the server didn't expect. Try reconnecting or updating your client.",
"The server is running in simple singleplayer mode. You cannot connect.", "The server is running in simple singleplayer mode. You cannot connect.",
"Your client's version is not supported.\nPlease contact server administrator.", "Your client's version is not supported.\nPlease contact the server administrator.",
"Player name contains disallowed characters.", "Player name contains disallowed characters",
"Player name not allowed.", "Player name not allowed",
"Too many users.", "Too many users",
"Empty passwords are disallowed. Set a password and try again.", "Empty passwords are disallowed. Set a password and try again.",
"Another client is connected with this name. If your client closed unexpectedly, try again in a minute.", "Another client is connected with this name. If your client closed unexpectedly, try again in a minute.",
"Server authentication failed. This is likely a server error.", "Internal server error",
"", "",
"Server shutting down.", "Server shutting down",
"This server has experienced an internal error. You will now be disconnected." "The server has experienced an internal error. You will now be disconnected."
}; };
enum PlayerListModifer : u8 enum PlayerListModifer : u8

@ -176,7 +176,7 @@ const ClientCommandFactory clientCommandFactoryTable[TOCLIENT_NUM_MSG_TYPES] =
{ "TOCLIENT_ACTIVE_OBJECT_MESSAGES", 0, true }, // 0x32 (may be sent as unrel over channel 1 too) { "TOCLIENT_ACTIVE_OBJECT_MESSAGES", 0, true }, // 0x32 (may be sent as unrel over channel 1 too)
{ "TOCLIENT_HP", 0, true }, // 0x33 { "TOCLIENT_HP", 0, true }, // 0x33
{ "TOCLIENT_MOVE_PLAYER", 0, true }, // 0x34 { "TOCLIENT_MOVE_PLAYER", 0, true }, // 0x34
{ "TOCLIENT_ACCESS_DENIED_LEGACY", 0, true }, // 0x35 null_command_factory, // 0x35
{ "TOCLIENT_FOV", 0, true }, // 0x36 { "TOCLIENT_FOV", 0, true }, // 0x36
{ "TOCLIENT_DEATHSCREEN", 0, true }, // 0x37 { "TOCLIENT_DEATHSCREEN", 0, true }, // 0x37
{ "TOCLIENT_MEDIA", 2, true }, // 0x38 { "TOCLIENT_MEDIA", 2, true }, // 0x38

@ -227,7 +227,7 @@ void Server::handleCommand_Init(NetworkPacket* pkt)
Compose auth methods for answer Compose auth methods for answer
*/ */
std::string encpwd; // encrypted Password field for the user std::string encpwd; // encrypted Password field for the user
bool has_auth = m_script->getAuth(playername, &encpwd, NULL); bool has_auth = m_script->getAuth(playername, &encpwd, nullptr);
u32 auth_mechs = 0; u32 auth_mechs = 0;
client->chosen_mech = AUTH_MECHANISM_NONE; client->chosen_mech = AUTH_MECHANISM_NONE;
@ -1461,11 +1461,9 @@ void Server::handleCommand_FirstSrp(NetworkPacket* pkt)
session_t peer_id = pkt->getPeerId(); session_t peer_id = pkt->getPeerId();
RemoteClient *client = getClient(peer_id, CS_Invalid); RemoteClient *client = getClient(peer_id, CS_Invalid);
ClientState cstate = client->getState(); ClientState cstate = client->getState();
const std::string playername = client->getName();
std::string playername = client->getName(); std::string salt, verification_key;
std::string salt;
std::string verification_key;
std::string addr_s = getPeerAddress(peer_id).serializeString(); std::string addr_s = getPeerAddress(peer_id).serializeString();
u8 is_empty; u8 is_empty;
@ -1551,8 +1549,6 @@ void Server::handleCommand_SrpBytesA(NetworkPacket* pkt)
RemoteClient *client = getClient(peer_id, CS_Invalid); RemoteClient *client = getClient(peer_id, CS_Invalid);
ClientState cstate = client->getState(); ClientState cstate = client->getState();
bool wantSudo = (cstate == CS_Active);
if (!((cstate == CS_HelloSent) || (cstate == CS_Active))) { if (!((cstate == CS_HelloSent) || (cstate == CS_Active))) {
actionstream << "Server: got SRP _A packet in wrong state " << cstate << actionstream << "Server: got SRP _A packet in wrong state " << cstate <<
" from " << getPeerAddress(peer_id).serializeString() << " from " << getPeerAddress(peer_id).serializeString() <<
@ -1560,6 +1556,8 @@ void Server::handleCommand_SrpBytesA(NetworkPacket* pkt)
return; return;
} }
const bool wantSudo = (cstate == CS_Active);
if (client->chosen_mech != AUTH_MECHANISM_NONE) { if (client->chosen_mech != AUTH_MECHANISM_NONE) {
actionstream << "Server: got SRP _A packet, while auth is already " actionstream << "Server: got SRP _A packet, while auth is already "
"going on with mech " << client->chosen_mech << " from " << "going on with mech " << client->chosen_mech << " from " <<
@ -1606,8 +1604,7 @@ void Server::handleCommand_SrpBytesA(NetworkPacket* pkt)
client->chosen_mech = chosen; client->chosen_mech = chosen;
std::string salt; std::string salt, verifier;
std::string verifier;
if (based_on == 0) { if (based_on == 0) {
@ -1657,10 +1654,10 @@ void Server::handleCommand_SrpBytesM(NetworkPacket* pkt)
session_t peer_id = pkt->getPeerId(); session_t peer_id = pkt->getPeerId();
RemoteClient *client = getClient(peer_id, CS_Invalid); RemoteClient *client = getClient(peer_id, CS_Invalid);
ClientState cstate = client->getState(); ClientState cstate = client->getState();
std::string addr_s = getPeerAddress(pkt->getPeerId()).serializeString(); const std::string addr_s = client->getAddress().serializeString();
std::string playername = client->getName(); const std::string playername = client->getName();
bool wantSudo = (cstate == CS_Active); const bool wantSudo = (cstate == CS_Active);
verbosestream << "Server: Received TOSERVER_SRP_BYTES_M." << std::endl; verbosestream << "Server: Received TOSERVER_SRP_BYTES_M." << std::endl;
@ -1720,8 +1717,7 @@ void Server::handleCommand_SrpBytesM(NetworkPacket* pkt)
if (client->create_player_on_auth_success) { if (client->create_player_on_auth_success) {
m_script->createAuth(playername, client->enc_pwd); m_script->createAuth(playername, client->enc_pwd);
std::string checkpwd; // not used, but needed for passing something if (!m_script->getAuth(playername, nullptr, nullptr)) {
if (!m_script->getAuth(playername, &checkpwd, NULL)) {
errorstream << "Server: " << playername << errorstream << "Server: " << playername <<
" cannot be authenticated (auth handler does not work?)" << " cannot be authenticated (auth handler does not work?)" <<
std::endl; std::endl;

@ -325,12 +325,15 @@ int ModApiServer::l_disconnect_player(lua_State *L)
else else
message.append("Disconnected."); message.append("Disconnected.");
RemotePlayer *player = dynamic_cast<ServerEnvironment *>(getEnv(L))->getPlayer(name); Server *server = getServer(L);
if (player == NULL) {
RemotePlayer *player = server->getEnv().getPlayer(name);
if (!player) {
lua_pushboolean(L, false); // No such player lua_pushboolean(L, false); // No such player
return 1; return 1;
} }
getServer(L)->DenyAccess_Legacy(player->getPeerId(), utf8_to_wide(message));
server->DenyAccess(player->getPeerId(), SERVER_ACCESSDENIED_CUSTOM_STRING, message);
lua_pushboolean(L, true); lua_pushboolean(L, true);
return 1; return 1;
} }

@ -1038,8 +1038,7 @@ void Server::Receive()
} catch (const ClientStateError &e) { } catch (const ClientStateError &e) {
errorstream << "ProcessData: peer=" << peer_id << " what()=" errorstream << "ProcessData: peer=" << peer_id << " what()="
<< e.what() << std::endl; << e.what() << std::endl;
DenyAccess_Legacy(peer_id, L"Your client sent something server didn't expect." DenyAccess(peer_id, SERVER_ACCESSDENIED_UNEXPECTED_DATA);
L"Try reconnecting or updating your client");
} catch (const con::PeerNotFoundException &e) { } catch (const con::PeerNotFoundException &e) {
// Do nothing // Do nothing
} catch (const con::NoIncomingDataException &e) { } catch (const con::NoIncomingDataException &e) {
@ -1068,15 +1067,13 @@ PlayerSAO* Server::StageTwoClientInit(session_t peer_id)
if (player && player->getPeerId() != PEER_ID_INEXISTENT) { if (player && player->getPeerId() != PEER_ID_INEXISTENT) {
actionstream << "Server: Failed to emerge player \"" << playername actionstream << "Server: Failed to emerge player \"" << playername
<< "\" (player allocated to an another client)" << std::endl; << "\" (player allocated to an another client)" << std::endl;
DenyAccess_Legacy(peer_id, L"Another client is connected with this " DenyAccess(peer_id, SERVER_ACCESSDENIED_ALREADY_CONNECTED);
L"name. If your client closed unexpectedly, try again in "
L"a minute.");
} else { } else {
errorstream << "Server: " << playername << ": Failed to emerge player" errorstream << "Server: " << playername << ": Failed to emerge player"
<< std::endl; << std::endl;
DenyAccess_Legacy(peer_id, L"Could not allocate player."); DenyAccess(peer_id, SERVER_ACCESSDENIED_SERVER_FAIL);
} }
return NULL; return nullptr;
} }
/* /*
@ -1141,18 +1138,16 @@ void Server::ProcessData(NetworkPacket *pkt)
Address address = getPeerAddress(peer_id); Address address = getPeerAddress(peer_id);
std::string addr_s = address.serializeString(); std::string addr_s = address.serializeString();
// FIXME: Isn't it a bit excessive to check this for every packet?
if (m_banmanager->isIpBanned(addr_s)) { if (m_banmanager->isIpBanned(addr_s)) {
std::string ban_name = m_banmanager->getBanName(addr_s); std::string ban_name = m_banmanager->getBanName(addr_s);
infostream << "Server: A banned client tried to connect from " infostream << "Server: A banned client tried to connect from "
<< addr_s << "; banned name was " << addr_s << "; banned name was " << ban_name << std::endl;
<< ban_name << std::endl; DenyAccess(peer_id, SERVER_ACCESSDENIED_CUSTOM_STRING,
// This actually doesn't seem to transfer to the client "Your IP is banned. Banned name was " + ban_name);
DenyAccess_Legacy(peer_id, L"Your ip is banned. Banned name was "
+ utf8_to_wide(ban_name));
return; return;
} }
} } catch (con::PeerNotFoundException &e) {
catch(con::PeerNotFoundException &e) {
/* /*
* no peer for this packet found * no peer for this packet found
* most common reason is peer timeout, e.g. peer didn't * most common reason is peer timeout, e.g. peer didn't
@ -1406,13 +1401,6 @@ void Server::SendAccessDenied(session_t peer_id, AccessDeniedCode reason,
Send(&pkt); Send(&pkt);
} }
void Server::SendAccessDenied_Legacy(session_t peer_id,const std::wstring &reason)
{
NetworkPacket pkt(TOCLIENT_ACCESS_DENIED_LEGACY, 0, peer_id);
pkt << reason;
Send(&pkt);
}
void Server::SendDeathscreen(session_t peer_id, bool set_camera_point_target, void Server::SendDeathscreen(session_t peer_id, bool set_camera_point_target,
v3f camera_point_target) v3f camera_point_target)
{ {
@ -2777,29 +2765,10 @@ void Server::DenySudoAccess(session_t peer_id)
} }
void Server::DenyAccessVerCompliant(session_t peer_id, u16 proto_ver, AccessDeniedCode reason,
const std::string &str_reason, bool reconnect)
{
SendAccessDenied(peer_id, reason, str_reason, reconnect);
m_clients.event(peer_id, CSE_SetDenied);
DisconnectPeer(peer_id);
}
void Server::DenyAccess(session_t peer_id, AccessDeniedCode reason, void Server::DenyAccess(session_t peer_id, AccessDeniedCode reason,
const std::string &custom_reason) const std::string &custom_reason, bool reconnect)
{ {
SendAccessDenied(peer_id, reason, custom_reason); SendAccessDenied(peer_id, reason, custom_reason, reconnect);
m_clients.event(peer_id, CSE_SetDenied);
DisconnectPeer(peer_id);
}
// 13/03/15: remove this function when protocol version 25 will become
// the minimum version for MT users, maybe in 1 year
void Server::DenyAccess_Legacy(session_t peer_id, const std::wstring &reason)
{
SendAccessDenied_Legacy(peer_id, reason);
m_clients.event(peer_id, CSE_SetDenied); m_clients.event(peer_id, CSE_SetDenied);
DisconnectPeer(peer_id); DisconnectPeer(peer_id);
} }
@ -2985,8 +2954,8 @@ std::wstring Server::handleChat(const std::string &name,
return ws.str(); return ws.str();
} }
case RPLAYER_CHATRESULT_KICK: case RPLAYER_CHATRESULT_KICK:
DenyAccess_Legacy(player->getPeerId(), DenyAccess(player->getPeerId(), SERVER_ACCESSDENIED_CUSTOM_STRING,
L"You have been kicked due to message flooding."); "You have been kicked due to message flooding.");
return L""; return L"";
case RPLAYER_CHATRESULT_OK: case RPLAYER_CHATRESULT_OK:
break; break;

@ -341,12 +341,9 @@ public:
void deletingPeer(con::Peer *peer, bool timeout); void deletingPeer(con::Peer *peer, bool timeout);
void DenySudoAccess(session_t peer_id); void DenySudoAccess(session_t peer_id);
void DenyAccessVerCompliant(session_t peer_id, u16 proto_ver, AccessDeniedCode reason,
const std::string &str_reason = "", bool reconnect = false);
void DenyAccess(session_t peer_id, AccessDeniedCode reason, void DenyAccess(session_t peer_id, AccessDeniedCode reason,
const std::string &custom_reason = ""); const std::string &custom_reason = "", bool reconnect = false);
void acceptAuth(session_t peer_id, bool forSudoMode); void acceptAuth(session_t peer_id, bool forSudoMode);
void DenyAccess_Legacy(session_t peer_id, const std::wstring &reason);
void DisconnectPeer(session_t peer_id); void DisconnectPeer(session_t peer_id);
bool getClientConInfo(session_t peer_id, con::rtt_stat_type type, float *retval); bool getClientConInfo(session_t peer_id, con::rtt_stat_type type, float *retval);
bool getClientInfo(session_t peer_id, ClientInfo &ret); bool getClientInfo(session_t peer_id, ClientInfo &ret);

@ -552,10 +552,8 @@ bool ServerEnvironment::removePlayerFromDatabase(const std::string &name)
void ServerEnvironment::kickAllPlayers(AccessDeniedCode reason, void ServerEnvironment::kickAllPlayers(AccessDeniedCode reason,
const std::string &str_reason, bool reconnect) const std::string &str_reason, bool reconnect)
{ {
for (RemotePlayer *player : m_players) { for (RemotePlayer *player : m_players)
m_server->DenyAccessVerCompliant(player->getPeerId(), m_server->DenyAccess(player->getPeerId(), reason, str_reason, reconnect);
player->protocol_version, reason, str_reason, reconnect);
}
} }
void ServerEnvironment::saveLoadedPlayers(bool force) void ServerEnvironment::saveLoadedPlayers(bool force)