mirror of
https://github.com/minetest/minetest.git
synced 2025-07-04 08:50:22 +02:00
Rework user limit and checks around join process
This commit is contained in:
@ -40,10 +40,6 @@ void Server::handleCommand_Deprecated(NetworkPacket* pkt)
|
||||
|
||||
void Server::handleCommand_Init(NetworkPacket* pkt)
|
||||
{
|
||||
|
||||
if(pkt->getSize() < 1)
|
||||
return;
|
||||
|
||||
session_t peer_id = pkt->getPeerId();
|
||||
RemoteClient *client = getClient(peer_id, CS_Created);
|
||||
|
||||
@ -75,15 +71,6 @@ void Server::handleCommand_Init(NetworkPacket* pkt)
|
||||
verbosestream << "Server: Got TOSERVER_INIT from " << addr_s <<
|
||||
" (peer_id=" << peer_id << ")" << std::endl;
|
||||
|
||||
// Do not allow multiple players in simple singleplayer mode.
|
||||
// This isn't a perfect way to do it, but will suffice for now
|
||||
if (m_simple_singleplayer_mode && !m_clients.getClientIDs().empty()) {
|
||||
infostream << "Server: Not allowing another client (" << addr_s <<
|
||||
") to connect in simple singleplayer mode" << std::endl;
|
||||
DenyAccess(peer_id, SERVER_ACCESSDENIED_SINGLEPLAYER);
|
||||
return;
|
||||
}
|
||||
|
||||
if (denyIfBanned(peer_id))
|
||||
return;
|
||||
|
||||
@ -161,18 +148,14 @@ void Server::handleCommand_Init(NetworkPacket* pkt)
|
||||
return;
|
||||
}
|
||||
|
||||
RemotePlayer *player = m_env->getPlayer(playername, true);
|
||||
|
||||
// If player is already connected, cancel
|
||||
if (player && player->getPeerId() != PEER_ID_INEXISTENT) {
|
||||
actionstream << "Server: Player with name \"" << playername <<
|
||||
"\" tried to connect, but player with same name is already connected" << std::endl;
|
||||
DenyAccess(peer_id, SERVER_ACCESSDENIED_ALREADY_CONNECTED);
|
||||
// Do not allow multiple players in simple singleplayer mode
|
||||
if (isSingleplayer() && !m_clients.getClientIDs(CS_HelloSent).empty()) {
|
||||
infostream << "Server: Not allowing another client (" << addr_s <<
|
||||
") to connect in simple singleplayer mode" << std::endl;
|
||||
DenyAccess(peer_id, SERVER_ACCESSDENIED_SINGLEPLAYER);
|
||||
return;
|
||||
}
|
||||
|
||||
m_clients.setPlayerName(peer_id, playername);
|
||||
|
||||
// Or the "singleplayer" name to be used on regular servers
|
||||
if (!isSingleplayer() && strcasecmp(playername, "singleplayer") == 0) {
|
||||
actionstream << "Server: Player with the name \"singleplayer\" tried "
|
||||
"to connect from " << addr_s << std::endl;
|
||||
@ -180,12 +163,25 @@ void Server::handleCommand_Init(NetworkPacket* pkt)
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
RemotePlayer *player = m_env->getPlayer(playername, true);
|
||||
// If player is already connected, cancel
|
||||
if (player && player->getPeerId() != PEER_ID_INEXISTENT) {
|
||||
actionstream << "Server: Player with name \"" << playername <<
|
||||
"\" tried to connect, but player with same name is already connected" << std::endl;
|
||||
DenyAccess(peer_id, SERVER_ACCESSDENIED_ALREADY_CONNECTED);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
client->setName(playerName);
|
||||
|
||||
{
|
||||
std::string reason;
|
||||
if (m_script->on_prejoinplayer(playername, addr_s, &reason)) {
|
||||
actionstream << "Server: Player with the name \"" << playerName <<
|
||||
"\" tried to connect from " << addr_s <<
|
||||
" but it was disallowed for the following reason: " << reason <<
|
||||
" but was disallowed for the following reason: " << reason <<
|
||||
std::endl;
|
||||
DenyAccess(peer_id, SERVER_ACCESSDENIED_CUSTOM_STRING, reason);
|
||||
return;
|
||||
@ -195,14 +191,11 @@ void Server::handleCommand_Init(NetworkPacket* pkt)
|
||||
infostream << "Server: New connection: \"" << playerName << "\" from " <<
|
||||
addr_s << " (peer_id=" << peer_id << ")" << std::endl;
|
||||
|
||||
// Enforce user limit.
|
||||
// Don't enforce for users that have some admin right or mod permits it.
|
||||
if (m_clients.isUserLimitReached() &&
|
||||
playername != g_settings->get("name") &&
|
||||
!m_script->can_bypass_userlimit(playername, addr_s)) {
|
||||
// Early check for user limit, so the client doesn't need to run
|
||||
// through the join process only to be denied.
|
||||
if (checkUserLimit(playerName, addr_s)) {
|
||||
actionstream << "Server: " << playername << " tried to join from " <<
|
||||
addr_s << ", but there are already max_users=" <<
|
||||
g_settings->getU16("max_users") << " players." << std::endl;
|
||||
addr_s << ", but the user limit was reached." << std::endl;
|
||||
DenyAccess(peer_id, SERVER_ACCESSDENIED_TOO_MANY_USERS);
|
||||
return;
|
||||
}
|
||||
@ -355,6 +348,8 @@ void Server::handleCommand_RequestMedia(NetworkPacket* pkt)
|
||||
void Server::handleCommand_ClientReady(NetworkPacket* pkt)
|
||||
{
|
||||
session_t peer_id = pkt->getPeerId();
|
||||
RemoteClient *client = getClient(peer_id, CS_Created);
|
||||
assert(client);
|
||||
|
||||
// decode all information first
|
||||
u8 major_ver, minor_ver, patch_ver, reserved;
|
||||
@ -365,8 +360,17 @@ void Server::handleCommand_ClientReady(NetworkPacket* pkt)
|
||||
if (pkt->getRemainingBytes() >= 2)
|
||||
*pkt >> formspec_ver;
|
||||
|
||||
m_clients.setClientVersion(peer_id, major_ver, minor_ver, patch_ver,
|
||||
full_ver);
|
||||
client->setVersionInfo(major_ver, minor_ver, patch_ver, full_ver);
|
||||
|
||||
// Since only active clients count for the user limit, two could race the
|
||||
// join process so we have to do a final check for the user limit here.
|
||||
std::string addr_s = client->getAddress().serializeString();
|
||||
if (checkUserLimit(client->getName(), addr_s)) {
|
||||
actionstream << "Server: " << client->getName() << " tried to join from " <<
|
||||
addr_s << ", but the user limit was reached (late)." << std::endl;
|
||||
DenyAccess(peer_id, SERVER_ACCESSDENIED_TOO_MANY_USERS);
|
||||
return;
|
||||
}
|
||||
|
||||
// Emerge player
|
||||
PlayerSAO* playersao = StageTwoClientInit(peer_id);
|
||||
@ -1427,7 +1431,7 @@ void Server::handleCommand_FirstSrp(NetworkPacket* pkt)
|
||||
|
||||
std::string salt, verification_key;
|
||||
|
||||
std::string addr_s = getPeerAddress(peer_id).serializeString();
|
||||
std::string addr_s = client->getAddress().serializeString();
|
||||
u8 is_empty;
|
||||
|
||||
*pkt >> salt >> verification_key >> is_empty;
|
||||
@ -1513,9 +1517,11 @@ void Server::handleCommand_SrpBytesA(NetworkPacket* pkt)
|
||||
RemoteClient *client = getClient(peer_id, CS_Invalid);
|
||||
ClientState cstate = client->getState();
|
||||
|
||||
std::string addr_s = client->getAddress().serializeString();
|
||||
|
||||
if (!((cstate == CS_HelloSent) || (cstate == CS_Active))) {
|
||||
actionstream << "Server: got SRP _A packet in wrong state " << cstate <<
|
||||
" from " << getPeerAddress(peer_id).serializeString() <<
|
||||
" from " << addr_s <<
|
||||
". Ignoring." << std::endl;
|
||||
return;
|
||||
}
|
||||
@ -1525,7 +1531,7 @@ void Server::handleCommand_SrpBytesA(NetworkPacket* pkt)
|
||||
if (client->chosen_mech != AUTH_MECHANISM_NONE) {
|
||||
actionstream << "Server: got SRP _A packet, while auth is already "
|
||||
"going on with mech " << client->chosen_mech << " from " <<
|
||||
getPeerAddress(peer_id).serializeString() <<
|
||||
addr_s <<
|
||||
" (wantSudo=" << wantSudo << "). Ignoring." << std::endl;
|
||||
if (wantSudo) {
|
||||
DenySudoAccess(peer_id);
|
||||
@ -1542,7 +1548,7 @@ void Server::handleCommand_SrpBytesA(NetworkPacket* pkt)
|
||||
|
||||
infostream << "Server: TOSERVER_SRP_BYTES_A received with "
|
||||
<< "based_on=" << int(based_on) << " and len_A="
|
||||
<< bytes_A.length() << "." << std::endl;
|
||||
<< bytes_A.length() << std::endl;
|
||||
|
||||
AuthMechanism chosen = (based_on == 0) ?
|
||||
AUTH_MECHANISM_LEGACY_PASSWORD : AUTH_MECHANISM_SRP;
|
||||
@ -1551,17 +1557,17 @@ void Server::handleCommand_SrpBytesA(NetworkPacket* pkt)
|
||||
// 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() <<
|
||||
"\" from " << addr_s <<
|
||||
" tried to change password using unallowed mech " << chosen <<
|
||||
"." << std::endl;
|
||||
std::endl;
|
||||
DenySudoAccess(peer_id);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!client->isMechAllowed(chosen)) {
|
||||
actionstream << "Server: Client tried to authenticate from " <<
|
||||
getPeerAddress(peer_id).serializeString() <<
|
||||
" using unallowed mech " << chosen << "." << std::endl;
|
||||
addr_s <<
|
||||
" using unallowed mech " << chosen << std::endl;
|
||||
DenyAccess(peer_id, SERVER_ACCESSDENIED_UNEXPECTED_DATA);
|
||||
return;
|
||||
}
|
||||
|
Reference in New Issue
Block a user