221 lines
4.9 KiB
Plaintext
221 lines
4.9 KiB
Plaintext
/*
|
|
* Irresistible Gaming 2018
|
|
* Developed by Lorenc
|
|
* Module: security.inc
|
|
* Purpose: security related functions for ig servers
|
|
*/
|
|
|
|
/* ** Includes ** */
|
|
#include < YSI\y_hooks >
|
|
|
|
/* ** Macros ** */
|
|
#define GetServerName(%0) ( g_igServerNames[ %0 ] )
|
|
#define ReturnPlayerIP(%0) ( p_PlayerIP[ ( %0 ) ] )
|
|
#define ReturnPlayerName(%0) ( p_PlayerName[ ( %0 ) ] )
|
|
#define IsPlayerNpcEx(%0) ( IsPlayerNPC( %0 ) || ! strcmp( p_PlayerIP[ %0 ], "127.0.0.1", true ) )
|
|
|
|
/* ** Constants ** */
|
|
stock const
|
|
g_igServerNames [ ] [ ] = { SERVER_NAME };
|
|
|
|
/* ** Variables ** */
|
|
new
|
|
p_PlayerName [ MAX_PLAYERS ] [ MAX_PLAYER_NAME ],
|
|
p_PlayerIP [ MAX_PLAYERS ] [ 16 ],
|
|
p_RconLoginFails [ MAX_PLAYERS char ]
|
|
;
|
|
|
|
/* ** Forwards ** */
|
|
forward OnNpcConnect( npcid );
|
|
forward OnNpcDisconnect( npcid, reason );
|
|
|
|
/* ** Hooks ** */
|
|
hook OnRconLoginAttempt( ip[ ], password[ ], success )
|
|
{
|
|
new
|
|
playerid = INVALID_PLAYER_ID,
|
|
szIP[ 16 ]
|
|
;
|
|
|
|
foreach(new i : Player)
|
|
{
|
|
if( GetPlayerIp( i, szIP, sizeof( szIP ) ) )
|
|
{
|
|
if( !strcmp( szIP, ip, true ) )
|
|
{
|
|
playerid = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( !success )
|
|
{
|
|
if( IsPlayerConnected( playerid ) )
|
|
{
|
|
p_RconLoginFails{ playerid } ++;
|
|
SendClientMessageFormatted( playerid, -1, "{FF0000}[ERROR]{FFFFFF} You have entered an invalid rcon password. {C0C0C0}[%d/2]", p_RconLoginFails{ playerid } );
|
|
|
|
if( p_RconLoginFails{ playerid } >= 2 ) {
|
|
SendClientMessageFormatted( playerid, -1, "{C0C0C0}[SERVER]{FFFFFF} If you are not the server operator or manager, don't bother trying!" );
|
|
Kick( playerid );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( IsPlayerConnected( playerid ) && ! IsPlayerServerMaintainer( playerid ) )
|
|
{
|
|
RangeBanPlayer( playerid );
|
|
return 0;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
hook OnPlayerConnect( playerid )
|
|
{
|
|
static
|
|
szName[ MAX_PLAYER_NAME ], szIP[ 16 ];
|
|
|
|
GetPlayerIp( playerid, szIP, sizeof( szIP ) );
|
|
GetPlayerName( playerid, szName, sizeof( szName ) );
|
|
|
|
if ( IsPlayerNPC( playerid ) ) {
|
|
CallLocalFunction( "OnNpcConnect", "d", playerid );
|
|
return Y_HOOKS_BREAK_RETURN_1;
|
|
}
|
|
|
|
strcpy( p_PlayerIP[ playerid ], szIP );
|
|
strcpy( p_PlayerName[ playerid ], szName );
|
|
|
|
// get out the bots/invalid player ids
|
|
if ( ! ( 0 <= playerid < MAX_PLAYERS ) ) {
|
|
Kick( playerid );
|
|
return Y_HOOKS_BREAK_RETURN_1;
|
|
}
|
|
|
|
// check for invalid name
|
|
if ( strlen( ReturnPlayerName( playerid ) ) <= 2 ) {
|
|
Kick( playerid );
|
|
return Y_HOOKS_BREAK_RETURN_1;
|
|
}
|
|
|
|
// check if player name is "no-one" since it is used for unowned entities
|
|
if ( ! strcmp( ReturnPlayerName( playerid ), "No-one", true ) ) {
|
|
Kick( playerid );
|
|
return Y_HOOKS_BREAK_RETURN_1;
|
|
}
|
|
|
|
// check advertisers
|
|
if ( textContainsIP( ReturnPlayerName( playerid ) ) ) {
|
|
Kick( playerid );
|
|
return Y_HOOKS_BREAK_RETURN_1;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
hook OnPlayerDisconnect( playerid, reason )
|
|
{
|
|
if ( IsPlayerNPC( playerid ) ) {
|
|
CallLocalFunction( "OnNpcDisconnect", "dd", playerid, reason );
|
|
return Y_HOOKS_BREAK_RETURN_1;
|
|
}
|
|
|
|
// Filter out bots
|
|
if ( ! ( 0 <= playerid < MAX_PLAYERS ) ) {
|
|
return Y_HOOKS_BREAK_RETURN_1;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
hook OnPlayerFloodControl( playerid, iCount, iTimeSpan ) {
|
|
static
|
|
szIP[ 16 ];
|
|
|
|
GetPlayerIp( playerid, szIP, sizeof( szIP ) );
|
|
|
|
if ( iCount > 2 && iTimeSpan < 10000 && ! IsPlayerNpcEx( playerid ) ) {
|
|
BanEx( playerid, "BOT-SPAM" );
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
#if !defined DEBUG_MODE
|
|
// prevent player from leaking rcon password
|
|
hook OnPlayerText( playerid, text[ ] )
|
|
{
|
|
static
|
|
rcon_password[ 144 ];
|
|
|
|
GetServerVarAsString( "rcon_password", rcon_password, sizeof( rcon_password ) );
|
|
|
|
if ( strfind( text, rcon_password, true ) != -1 ) {
|
|
return SendClientMessage( playerid, -1, "{C0C0C0}[SERVER]{FFFFFF} Your message was blocked as it exposed the RCON password." ), 0;
|
|
}
|
|
return 1;
|
|
}
|
|
#else
|
|
// aims to clear the banned from the server bug
|
|
hook OnIncomingConnection( playerid, ip_address[ ], port ) {
|
|
SendRconCommand( "reloadbans" );
|
|
return 1;
|
|
}
|
|
#endif
|
|
|
|
/* ** Hooked Functions ** */
|
|
stock Security_SetPlayerName( playerid, const name[ ] )
|
|
{
|
|
if ( 0 <= playerid < MAX_PLAYERS ) {
|
|
format ( p_PlayerName[ playerid ], sizeof ( p_PlayerName[ ] ), "%s", name );
|
|
}
|
|
return SetPlayerName( playerid, name );
|
|
}
|
|
|
|
#if defined _ALS_SetPlayerName
|
|
#undef SetPlayerName
|
|
#else
|
|
#define _ALS_SetPlayerName
|
|
#endif
|
|
|
|
#define SetPlayerName Security_SetPlayerName
|
|
|
|
/* ** Functions ** */
|
|
stock RangeBanPlayer( playerid )
|
|
{
|
|
if ( !IsPlayerConnected( playerid ) )
|
|
return 0;
|
|
|
|
new
|
|
szBan[ 24 ],
|
|
szIP[ 16 ]
|
|
;
|
|
GetPlayerIp( playerid, szIP, sizeof( szIP ) );
|
|
GetRangeIP( szIP, sizeof( szIP ) );
|
|
|
|
format( szBan, sizeof( szBan ), "banip %s", szIP );
|
|
SendRconCommand( szBan );
|
|
|
|
KickPlayerTimed( playerid );
|
|
|
|
return 1;
|
|
}
|
|
|
|
stock GetRangeIP( szIP[ ], iSize = sizeof( szIP ) )
|
|
{
|
|
new
|
|
iCount = 0
|
|
;
|
|
for( new i; szIP[ i ] != '\0'; i ++ )
|
|
{
|
|
if ( szIP[ i ] == '.' && ( iCount ++ ) == 1 )
|
|
{
|
|
strdel( szIP, i, strlen( szIP ) );
|
|
break;
|
|
}
|
|
}
|
|
format( szIP, iSize, "%s.*.*", szIP );
|
|
}
|