2022-02-19 02:31:16 +01:00
//=====================================================================================//
//
// Purpose: Implementation of the CBanSystem class.
//
// $NoKeywords: $
//=====================================================================================//
2021-12-25 22:36:38 +01:00
# include "core/stdafx.h"
2022-04-02 02:48:54 +02:00
# include "engine/net.h"
2022-05-20 11:52:19 +02:00
# include "engine/client/client.h"
2022-09-01 01:07:16 +02:00
# include "filesystem/filesystem.h"
2022-08-09 17:34:10 +02:00
# include "networksystem/bansystem.h"
2021-12-25 22:36:38 +01:00
//-----------------------------------------------------------------------------
// Purpose: loads and parses the banlist
//-----------------------------------------------------------------------------
2022-02-19 02:31:16 +01:00
void CBanSystem : : Load ( void )
2021-12-25 22:36:38 +01:00
{
2022-08-29 17:03:14 +02:00
if ( IsBanListValid ( ) )
{
m_vBanList . clear ( ) ;
}
2022-09-01 01:07:16 +02:00
FileHandle_t pFile = FileSystem ( ) - > Open ( " banlist.json " , " rt " ) ;
if ( ! pFile )
{
return ;
}
uint32_t nLen = FileSystem ( ) - > Size ( pFile ) ;
char * pBuf = MemAllocSingleton ( ) - > Alloc < char > ( nLen ) ;
int nRead = FileSystem ( ) - > Read ( pBuf , nLen , pFile ) ;
FileSystem ( ) - > Close ( pFile ) ;
pBuf [ nRead ] = ' \0 ' ; // Null terminate the string buffer containing our banned list.
try
2021-12-25 22:36:38 +01:00
{
2022-09-01 01:07:16 +02:00
nlohmann : : json jsIn = nlohmann : : json : : parse ( pBuf ) ;
2021-12-25 22:36:38 +01:00
2022-09-01 01:07:16 +02:00
size_t nTotalBans = 0 ;
2022-06-14 20:56:55 +02:00
if ( ! jsIn . is_null ( ) )
2021-12-25 22:36:38 +01:00
{
2022-04-02 02:48:54 +02:00
if ( ! jsIn [ " totalBans " ] . is_null ( ) )
2021-12-25 22:36:38 +01:00
{
2022-09-01 01:07:16 +02:00
nTotalBans = jsIn [ " totalBans " ] . get < size_t > ( ) ;
2021-12-25 22:36:38 +01:00
}
}
2022-09-01 01:07:16 +02:00
for ( size_t i = 0 ; i < nTotalBans ; i + + )
2021-12-25 22:36:38 +01:00
{
2022-08-09 17:57:43 +02:00
nlohmann : : json jsEntry = jsIn [ std : : to_string ( i ) ] ;
2022-09-01 01:07:16 +02:00
if ( ! jsEntry . is_null ( ) )
2021-12-25 22:36:38 +01:00
{
2022-09-01 01:07:16 +02:00
string svIpAddress = jsEntry [ " ipAddress " ] . get < string > ( ) ;
uint64_t nNucleusID = jsEntry [ " nucleusId " ] . get < uint64_t > ( ) ;
2021-12-25 22:36:38 +01:00
2022-09-01 01:07:16 +02:00
m_vBanList . push_back ( std : : make_pair ( svIpAddress , nNucleusID ) ) ;
}
2021-12-25 22:36:38 +01:00
}
}
2022-09-01 01:07:16 +02:00
catch ( const std : : exception & ex )
{
Warning ( eDLL_T : : SERVER , " %s: Exception while parsing banned list: \n %s \n " , __FUNCTION__ , ex . what ( ) ) ;
}
MemAllocSingleton ( ) - > Free ( pBuf ) ;
2021-12-25 22:36:38 +01:00
}
//-----------------------------------------------------------------------------
// Purpose: saves the banlist
//-----------------------------------------------------------------------------
2022-02-19 02:31:16 +01:00
void CBanSystem : : Save ( void ) const
2021-12-25 22:36:38 +01:00
{
2022-09-01 01:07:16 +02:00
FileHandle_t pFile = FileSystem ( ) - > Open ( " banlist.json " , " wt " , " PLATFORM " ) ;
if ( ! pFile )
2021-12-25 22:36:38 +01:00
{
2022-09-01 01:07:16 +02:00
Error ( eDLL_T : : SERVER , false , " %s - Unable to write to '%s' (read-only?) \n " , __FUNCTION__ , " banlist.json " ) ;
return ;
2021-12-25 22:36:38 +01:00
}
2022-09-01 01:07:16 +02:00
try
{
nlohmann : : json jsOut ;
for ( size_t i = 0 ; i < m_vBanList . size ( ) ; i + + )
{
jsOut [ std : : to_string ( i ) ] [ " ipAddress " ] = m_vBanList [ i ] . first ;
jsOut [ std : : to_string ( i ) ] [ " nucleusId " ] = m_vBanList [ i ] . second ;
}
jsOut [ " totalBans " ] = m_vBanList . size ( ) ;
string svJsOut = jsOut . dump ( 4 ) ;
FileSystem ( ) - > Write ( svJsOut . data ( ) , svJsOut . size ( ) , pFile ) ;
}
catch ( const std : : exception & ex )
{
Warning ( eDLL_T : : SERVER , " %s: Exception while parsing banned list: \n %s \n " , __FUNCTION__ , ex . what ( ) ) ;
}
2021-12-25 22:36:38 +01:00
2022-09-01 01:07:16 +02:00
FileSystem ( ) - > Close ( pFile ) ;
2021-12-25 22:36:38 +01:00
}
//-----------------------------------------------------------------------------
// Purpose: adds a banned player entry to the banlist
2022-08-09 17:57:43 +02:00
// Input : &svIpAddress -
2022-08-29 15:59:12 +02:00
// nNucleusID -
2021-12-25 22:36:38 +01:00
//-----------------------------------------------------------------------------
2022-08-29 15:59:12 +02:00
bool CBanSystem : : AddEntry ( const string & svIpAddress , const uint64_t nNucleusID )
2021-12-25 22:36:38 +01:00
{
2022-08-30 12:07:09 +02:00
Assert ( ! svIpAddress . empty ( ) ) ;
if ( IsBanListValid ( ) )
2021-12-25 22:36:38 +01:00
{
2022-08-29 15:59:12 +02:00
auto it = std : : find ( m_vBanList . begin ( ) , m_vBanList . end ( ) , std : : make_pair ( svIpAddress , nNucleusID ) ) ;
2022-06-14 20:56:55 +02:00
if ( it = = m_vBanList . end ( ) )
2022-01-09 14:35:43 +01:00
{
2022-08-29 15:59:12 +02:00
m_vBanList . push_back ( std : : make_pair ( svIpAddress , nNucleusID ) ) ;
2022-08-27 23:45:58 +02:00
return true ;
2022-01-09 14:35:43 +01:00
}
2021-12-25 22:36:38 +01:00
}
2022-08-30 12:07:09 +02:00
else
{
m_vBanList . push_back ( std : : make_pair ( svIpAddress , nNucleusID ) ) ;
return true ;
}
2022-08-27 23:45:58 +02:00
return false ;
2021-12-25 22:36:38 +01:00
}
//-----------------------------------------------------------------------------
// Purpose: deletes an entry in the banlist
2022-08-09 17:57:43 +02:00
// Input : &svIpAddress -
2022-08-29 15:59:12 +02:00
// nNucleusID -
2021-12-25 22:36:38 +01:00
//-----------------------------------------------------------------------------
2022-08-29 15:59:12 +02:00
bool CBanSystem : : DeleteEntry ( const string & svIpAddress , const uint64_t nNucleusID )
2021-12-25 22:36:38 +01:00
{
2022-08-30 12:07:09 +02:00
Assert ( ! svIpAddress . empty ( ) ) ;
if ( IsBanListValid ( ) )
2021-12-25 22:36:38 +01:00
{
2022-08-30 12:07:09 +02:00
auto it = std : : find_if ( m_vBanList . begin ( ) , m_vBanList . end ( ) ,
[ & ] ( const pair < const string , const uint64_t > & element )
{ return ( svIpAddress . compare ( element . first ) = = NULL | | element . second = = nNucleusID ) ; } ) ;
if ( it ! = m_vBanList . end ( ) )
2021-12-25 22:36:38 +01:00
{
2022-08-30 12:07:09 +02:00
DeleteConnectionRefuse ( it - > second ) ;
m_vBanList . erase ( it ) ;
return true ;
2021-12-25 22:36:38 +01:00
}
}
2022-08-27 23:45:58 +02:00
2022-08-30 12:07:09 +02:00
return false ;
2021-12-25 22:36:38 +01:00
}
//-----------------------------------------------------------------------------
// Purpose: adds a connect refuse entry to the refuselist
2022-08-09 17:57:43 +02:00
// Input : &svError -
2022-08-29 15:59:12 +02:00
// nNucleusID -
2021-12-25 22:36:38 +01:00
//-----------------------------------------------------------------------------
2022-08-30 12:07:09 +02:00
bool CBanSystem : : AddConnectionRefuse ( const string & svError , const uint64_t nNucleusID )
2021-12-25 22:36:38 +01:00
{
2022-08-30 12:07:09 +02:00
if ( IsRefuseListValid ( ) )
2021-12-25 22:36:38 +01:00
{
2022-08-30 12:07:09 +02:00
auto it = std : : find_if ( m_vRefuseList . begin ( ) , m_vRefuseList . end ( ) ,
[ & ] ( const pair < const string , const uint64_t > & element ) { return element . second = = nNucleusID ; } ) ;
if ( it = = m_vRefuseList . end ( ) )
{
m_vRefuseList . push_back ( std : : make_pair ( svError , nNucleusID ) ) ;
return true ;
}
2021-12-25 22:36:38 +01:00
}
else
{
2022-08-30 12:07:09 +02:00
m_vRefuseList . push_back ( std : : make_pair ( svError , nNucleusID ) ) ;
return true ;
2021-12-25 22:36:38 +01:00
}
2022-08-30 12:07:09 +02:00
return false ;
2021-12-25 22:36:38 +01:00
}
//-----------------------------------------------------------------------------
// Purpose: deletes an entry in the refuselist
2022-08-29 15:59:12 +02:00
// Input : nNucleusID -
2021-12-25 22:36:38 +01:00
//-----------------------------------------------------------------------------
2022-08-30 12:07:09 +02:00
bool CBanSystem : : DeleteConnectionRefuse ( const uint64_t nNucleusID )
2021-12-25 22:36:38 +01:00
{
2022-08-30 12:07:09 +02:00
if ( IsRefuseListValid ( ) )
2021-12-25 22:36:38 +01:00
{
2022-08-30 12:07:09 +02:00
auto it = std : : find_if ( m_vRefuseList . begin ( ) , m_vRefuseList . end ( ) ,
[ & ] ( const pair < const string , const uint64_t > & element ) { return element . second = = nNucleusID ; } ) ;
if ( it ! = m_vRefuseList . end ( ) )
2021-12-25 22:36:38 +01:00
{
2022-08-30 12:07:09 +02:00
m_vRefuseList . erase ( it ) ;
return true ;
2021-12-25 22:36:38 +01:00
}
}
2022-08-30 12:07:09 +02:00
return false ;
2021-12-25 22:36:38 +01:00
}
2022-02-19 02:31:16 +01:00
//-----------------------------------------------------------------------------
// Purpose: Check refuse list and kill netchan connection.
//-----------------------------------------------------------------------------
void CBanSystem : : BanListCheck ( void )
{
if ( IsRefuseListValid ( ) )
{
2022-08-27 23:45:58 +02:00
bool bSave = false ;
2022-06-14 20:56:55 +02:00
for ( size_t i = 0 ; i < m_vRefuseList . size ( ) ; i + + )
2022-02-19 02:31:16 +01:00
{
for ( int c = 0 ; c < MAX_PLAYERS ; c + + ) // Loop through all possible client instances.
{
2022-08-27 23:45:58 +02:00
CClient * pClient = g_pClient - > GetClient ( c ) ;
2022-07-07 20:35:49 +02:00
if ( ! pClient )
continue ;
2022-02-19 02:31:16 +01:00
2022-07-07 20:35:49 +02:00
CNetChan * pNetChan = pClient - > GetNetChan ( ) ;
if ( ! pNetChan )
2022-02-19 02:31:16 +01:00
continue ;
2022-08-29 15:59:12 +02:00
if ( pClient - > GetNucleusID ( ) ! = m_vRefuseList [ i ] . second )
2022-02-19 02:31:16 +01:00
continue ;
2022-06-14 20:56:55 +02:00
string svIpAddress = pNetChan - > GetAddress ( ) ;
2022-02-19 02:31:16 +01:00
2022-08-30 12:07:09 +02:00
Warning ( eDLL_T : : SERVER , " Removing client '%s' from slot '%hu' ('%llu' is banned from this server!) \n " , svIpAddress . c_str ( ) , pClient - > GetHandle ( ) , pClient - > GetNucleusID ( ) ) ;
if ( AddEntry ( svIpAddress , pClient - > GetNucleusID ( ) ) & & ! bSave )
2022-08-27 23:45:58 +02:00
bSave = true ;
2022-08-30 12:07:09 +02:00
NET_DisconnectClient ( pClient , c , m_vRefuseList [ i ] . first . c_str ( ) , 0 , true ) ;
2022-02-19 02:31:16 +01:00
}
}
2022-08-27 23:45:58 +02:00
if ( bSave )
Save ( ) ; // Save banlist to file.
2022-02-19 02:31:16 +01:00
}
}
2022-06-14 20:56:55 +02:00
//-----------------------------------------------------------------------------
// Purpose: checks if specified ip address or necleus id is banned
2022-08-09 17:57:43 +02:00
// Input : &svIpAddress -
2022-08-29 15:59:12 +02:00
// nNucleusID -
2022-06-14 20:56:55 +02:00
// Output : true if banned, false if not banned
//-----------------------------------------------------------------------------
2022-08-29 15:59:12 +02:00
bool CBanSystem : : IsBanned ( const string & svIpAddress , const uint64_t nNucleusID ) const
2022-06-14 20:56:55 +02:00
{
for ( size_t i = 0 ; i < m_vBanList . size ( ) ; i + + )
{
string ipAddress = m_vBanList [ i ] . first ;
2022-08-29 15:59:12 +02:00
uint64_t nucleusID = m_vBanList [ i ] . second ;
2022-06-14 20:56:55 +02:00
if ( ipAddress . empty ( ) | |
2022-08-29 15:59:12 +02:00
! nucleusID ) // Cannot be null.
2022-06-14 20:56:55 +02:00
{
continue ;
}
if ( ipAddress . compare ( svIpAddress ) = = NULL | |
2022-08-29 15:59:12 +02:00
nNucleusID = = nucleusID )
2022-06-14 20:56:55 +02:00
{
return true ;
}
}
return false ;
}
2021-12-25 22:36:38 +01:00
//-----------------------------------------------------------------------------
// Purpose: checks if refuselist is valid
//-----------------------------------------------------------------------------
2022-02-19 02:31:16 +01:00
bool CBanSystem : : IsRefuseListValid ( void ) const
2021-12-25 22:36:38 +01:00
{
2022-06-14 20:56:55 +02:00
return ! m_vRefuseList . empty ( ) ;
2021-12-25 22:36:38 +01:00
}
//-----------------------------------------------------------------------------
// Purpose: checks if banlist is valid
//-----------------------------------------------------------------------------
2022-02-19 02:31:16 +01:00
bool CBanSystem : : IsBanListValid ( void ) const
2021-12-25 22:36:38 +01:00
{
2022-06-14 20:56:55 +02:00
return ! m_vBanList . empty ( ) ;
2021-12-25 22:36:38 +01:00
}
///////////////////////////////////////////////////////////////////////////////
2022-02-28 01:05:55 +01:00
CBanSystem * g_pBanSystem = new CBanSystem ( ) ;