Network: Auto-kick clients after too many failed rcon/settings attempts
This commit is contained in:
@@ -1039,9 +1039,12 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_SETTINGS_PASSWO
|
||||
DEBUG(net, 0, "[settings-ctrl] wrong password from client-id %d", this->client_id);
|
||||
NetworkServerSendRcon(this->client_id, CC_ERROR, "Access Denied");
|
||||
this->settings_authed = false;
|
||||
NetworkRecvStatus status = this->HandleAuthFailure(this->settings_auth_failures);
|
||||
if (status != NETWORK_RECV_STATUS_OKAY) return status;
|
||||
} else {
|
||||
DEBUG(net, 0, "[settings-ctrl] client-id %d", this->client_id);
|
||||
this->settings_authed = true;
|
||||
this->settings_auth_failures = 0;
|
||||
}
|
||||
|
||||
return this->SendSettingsAccessUpdate(this->settings_authed);
|
||||
@@ -1592,7 +1595,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_RCON(Packet *p)
|
||||
|
||||
if (_settings_client.network.rcon_password.empty()) {
|
||||
NetworkServerSendRcon(this->client_id, CC_ERROR, "Access Denied");
|
||||
return NETWORK_RECV_STATUS_OKAY;
|
||||
return this->HandleAuthFailure(this->rcon_auth_failures);
|
||||
}
|
||||
|
||||
std::vector<byte> password = p->Recv_buffer();
|
||||
@@ -1601,7 +1604,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_RCON(Packet *p)
|
||||
if (password != this->rcon_password_hash_cache.GetHash(_settings_client.network.rcon_password, this->rcon_hash_bits)) {
|
||||
DEBUG(net, 0, "[rcon] wrong password from client-id %d", this->client_id);
|
||||
NetworkServerSendRcon(this->client_id, CC_ERROR, "Access Denied");
|
||||
return NETWORK_RECV_STATUS_OKAY;
|
||||
return this->HandleAuthFailure(this->rcon_auth_failures);
|
||||
}
|
||||
|
||||
DEBUG(net, 3, "[rcon] Client-id %d executed: %s", this->client_id, command.c_str());
|
||||
@@ -1609,6 +1612,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_RCON(Packet *p)
|
||||
_redirect_console_to_client = this->client_id;
|
||||
IConsoleCmdExec(command.c_str());
|
||||
_redirect_console_to_client = INVALID_CLIENT_ID;
|
||||
this->rcon_auth_failures = 0;
|
||||
return NETWORK_RECV_STATUS_OKAY;
|
||||
}
|
||||
|
||||
@@ -1638,6 +1642,17 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_MOVE(Packet *p)
|
||||
return NETWORK_RECV_STATUS_OKAY;
|
||||
}
|
||||
|
||||
NetworkRecvStatus ServerNetworkGameSocketHandler::HandleAuthFailure(uint &failure_count)
|
||||
{
|
||||
failure_count++;
|
||||
if (_settings_client.network.max_auth_failures != 0 && failure_count >= _settings_client.network.max_auth_failures) {
|
||||
DEBUG(net, 0, "Kicked client-id #%d due to too many failed authentication attempts", this->client_id);
|
||||
return this->SendError(NETWORK_ERROR_KICKED);
|
||||
} else {
|
||||
return NETWORK_RECV_STATUS_OKAY;
|
||||
}
|
||||
}
|
||||
|
||||
const char *ServerNetworkGameSocketHandler::GetClientStatusName(ClientStatus status)
|
||||
{
|
||||
static const char* _client_status_names[] {
|
||||
|
@@ -100,6 +100,9 @@ public:
|
||||
uint desync_frame_seed = 0;
|
||||
uint desync_frame_state_checksum = 0;
|
||||
|
||||
uint rcon_auth_failures = 0;
|
||||
uint settings_auth_failures = 0;
|
||||
|
||||
ServerNetworkGameSocketHandler(SOCKET s);
|
||||
~ServerNetworkGameSocketHandler();
|
||||
|
||||
@@ -131,6 +134,8 @@ public:
|
||||
NetworkRecvStatus SendConfigUpdate();
|
||||
NetworkRecvStatus SendSettingsAccessUpdate(bool ok);
|
||||
|
||||
NetworkRecvStatus HandleAuthFailure(uint &failure_count);
|
||||
|
||||
std::string GetDebugInfo() const override;
|
||||
|
||||
static void Send();
|
||||
|
@@ -383,6 +383,7 @@ struct NetworkSettings {
|
||||
std::string network_id; ///< network ID for servers
|
||||
std::string company_password_storage_token; ///< company password storage token
|
||||
std::string company_password_storage_secret; ///< company password storage secret
|
||||
uint8 max_auth_failures; ///< maximum auth failures before client is kicked
|
||||
bool autoclean_companies; ///< automatically remove companies that are not in use
|
||||
uint8 autoclean_unprotected; ///< remove passwordless companies after this many months
|
||||
uint8 autoclean_protected; ///< remove the password from passworded companies after this many months
|
||||
|
@@ -256,3 +256,11 @@ var = network.reload_cfg
|
||||
flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY
|
||||
def = false
|
||||
cat = SC_EXPERT
|
||||
|
||||
[SDTC_VAR]
|
||||
var = network.max_auth_failures
|
||||
type = SLE_UINT8
|
||||
flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY
|
||||
def = 10
|
||||
min = 0
|
||||
max = 255
|
||||
|
Reference in New Issue
Block a user