engine: client: implement errormsg, secure client by checking server IP address we're connected to

This commit is contained in:
Alibek Omarov 2019-07-13 20:54:16 +03:00
parent 4e4a9827b1
commit 9662ab106f
7 changed files with 150 additions and 38 deletions

View File

@ -1154,6 +1154,7 @@ void CL_StopPlayback( void )
// let game known about demo state // let game known about demo state
Cvar_FullSet( "cl_background", "0", FCVAR_READ_ONLY ); Cvar_FullSet( "cl_background", "0", FCVAR_READ_ONLY );
cls.state = ca_disconnected; cls.state = ca_disconnected;
memset( &cls.serveradr, 0, sizeof( cls.serveradr ) );
cls.set_lastdemo = false; cls.set_lastdemo = false;
S_StopBackgroundTrack(); S_StopBackgroundTrack();
cls.connect_time = 0; cls.connect_time = 0;

View File

@ -503,6 +503,13 @@ void UI_AddTouchButtonToList( const char *name, const char *texture, const char
} }
} }
/*
=================
UI_ResetPing
notify gameui dll about latency reset
=================
*/
void UI_ResetPing( void ) void UI_ResetPing( void )
{ {
if( gameui.dllFuncs2.pfnResetPing ) if( gameui.dllFuncs2.pfnResetPing )
@ -511,11 +518,62 @@ void UI_ResetPing( void )
} }
} }
/*
=================
UI_ShowConnectionWarning
show connection warning dialog implemented by gameui dll
=================
*/
void UI_ShowConnectionWarning( void ) void UI_ShowConnectionWarning( void )
{ {
if( gameui.dllFuncs2.pfnShowConnectionWarning ) if( cls.state != ca_connected )
return;
if( Host_IsLocalClient() )
return;
if( ++cl.lostpackets == 8 )
{ {
gameui.dllFuncs2.pfnShowConnectionWarning(); CL_Disconnect();
if( gameui.dllFuncs2.pfnShowConnectionWarning )
{
gameui.dllFuncs2.pfnShowConnectionWarning();
}
Con_DPrintf( S_WARN "Too many lost packets! Showing Network options menu\n" );
}
}
/*
=================
UI_ShowConnectionWarning
show update dialog
=================
*/
void UI_ShowUpdateDialog( qboolean preferStore )
{
if( gameui.dllFuncs2.pfnShowUpdateDialog )
{
gameui.dllFuncs2.pfnShowUpdateDialog( preferStore );
}
Con_Printf( S_WARN "This version is not supported anymore. To continue, install latest engine version\n" );
}
/*
=================
UI_ShowConnectionWarning
show message box
=================
*/
void UI_ShowMessageBox( const char *text )
{
if( gameui.dllFuncs2.pfnShowMessageBox )
{
gameui.dllFuncs2.pfnShowMessageBox( text );
} }
} }

View File

@ -1098,6 +1098,8 @@ void CL_CheckForResend( void )
cls.signon = 0; cls.signon = 0;
cls.state = ca_connecting; cls.state = ca_connecting;
Q_strncpy( cls.servername, "localhost", sizeof( cls.servername )); Q_strncpy( cls.servername, "localhost", sizeof( cls.servername ));
cls.serveradr.type = NA_LOOPBACK;
// we don't need a challenge on the localhost // we don't need a challenge on the localhost
CL_SendConnectPacket(); CL_SendConnectPacket();
return; return;
@ -1150,6 +1152,7 @@ void CL_CheckForResend( void )
return; return;
} }
cls.serveradr = adr;
cls.max_fragment_size = Q_max( FRAGMENT_MAX_SIZE, cls.max_fragment_size >> Q_min( 1, cls.connect_retry )); cls.max_fragment_size = Q_max( FRAGMENT_MAX_SIZE, cls.max_fragment_size >> Q_min( 1, cls.connect_retry ));
cls.connect_time = host.realtime; // for retransmit requests cls.connect_time = host.realtime; // for retransmit requests
cls.connect_retry++; cls.connect_retry++;
@ -1501,6 +1504,7 @@ void CL_Disconnect( void )
IN_LockInputDevices( false ); // unlock input devices IN_LockInputDevices( false ); // unlock input devices
cls.state = ca_disconnected; cls.state = ca_disconnected;
memset( &cls.serveradr, 0, sizeof( cls.serveradr ) );
cls.set_lastdemo = false; cls.set_lastdemo = false;
cls.connect_retry = 0; cls.connect_retry = 0;
cls.signon = 0; cls.signon = 0;
@ -1858,6 +1862,19 @@ void CL_SetupOverviewParams( void )
} }
} }
/*
=================
CL_IsFromConnectingServer
Used for connectionless packets, when netchan may not be ready.
=================
*/
static qboolean CL_IsFromConnectingServer( netadr_t from )
{
return NET_IsLocalAddress( from ) ||
NET_CompareAdr( cls.serveradr, from );
}
/* /*
================= =================
CL_ConnectionlessPacket CL_ConnectionlessPacket
@ -1887,6 +1904,9 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
// server connection // server connection
if( !Q_strcmp( c, "client_connect" )) if( !Q_strcmp( c, "client_connect" ))
{ {
if( !CL_IsFromConnectingServer( from ))
return;
if( cls.state == ca_connected ) if( cls.state == ca_connected )
{ {
Con_DPrintf( S_ERROR "dup connect received. ignored\n"); Con_DPrintf( S_ERROR "dup connect received. ignored\n");
@ -1927,21 +1947,19 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
// print command from somewhere // print command from somewhere
Con_Printf( "%s", MSG_ReadString( msg )); Con_Printf( "%s", MSG_ReadString( msg ));
} }
else if( !Q_strcmp( c, "errormsg" ))
{
args = MSG_ReadString( msg );
if( !Q_strcmp( args, "Server uses protocol version 48.\n" ))
{
cls.legacyserver = from;
}
}
else if( !Q_strcmp( c, "testpacket" )) else if( !Q_strcmp( c, "testpacket" ))
{ {
byte recv_buf[NET_MAX_FRAGMENT]; byte recv_buf[NET_MAX_FRAGMENT];
dword crcValue = MSG_ReadLong( msg ); dword crcValue;
int realsize = MSG_GetMaxBytes( msg ) - MSG_GetNumBytesRead( msg ); int realsize;
dword crcValue2 = 0; dword crcValue2 = 0;
if( !CL_IsFromConnectingServer( from ))
return;
crcValue = MSG_ReadLong( msg );
realsize = MSG_GetMaxBytes( msg ) - MSG_GetNumBytesRead( msg );
if( cls.max_fragment_size != MSG_GetMaxBytes( msg )) if( cls.max_fragment_size != MSG_GetMaxBytes( msg ))
{ {
if( cls.connect_retry >= CL_TEST_RETRIES ) if( cls.connect_retry >= CL_TEST_RETRIES )
@ -1999,6 +2017,9 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
} }
else if( !Q_strcmp( c, "challenge" )) else if( !Q_strcmp( c, "challenge" ))
{ {
if( !CL_IsFromConnectingServer( from ))
return;
// challenge from the server we are connecting to // challenge from the server we are connecting to
cls.challenge = Q_atoi( Cmd_Argv( 1 )); cls.challenge = Q_atoi( Cmd_Argv( 1 ));
CL_SendConnectPacket(); CL_SendConnectPacket();
@ -2006,11 +2027,17 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
} }
else if( !Q_strcmp( c, "echo" )) else if( !Q_strcmp( c, "echo" ))
{ {
if( !CL_IsFromConnectingServer( from ))
return;
// echo request from server // echo request from server
Netchan_OutOfBandPrint( NS_CLIENT, from, "%s", Cmd_Argv( 1 )); Netchan_OutOfBandPrint( NS_CLIENT, from, "%s", Cmd_Argv( 1 ));
} }
else if( !Q_strcmp( c, "disconnect" )) else if( !Q_strcmp( c, "disconnect" ))
{ {
if( !CL_IsFromConnectingServer( from ))
return;
// a disconnect message from the server, which will happen if the server // a disconnect message from the server, which will happen if the server
// dropped the connection but it is still getting packets from us // dropped the connection but it is still getting packets from us
CL_Disconnect_f(); CL_Disconnect_f();
@ -2021,6 +2048,48 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
memset( &cls.legacyserver, 0, sizeof( cls.legacyserver )); memset( &cls.legacyserver, 0, sizeof( cls.legacyserver ));
} }
} }
else if( !Q_strcmp( c, "errormsg" ))
{
if( !CL_IsFromConnectingServer( from ))
return;
args = MSG_ReadString( msg );
if( !Q_strcmp( args, "Server uses protocol version 48.\n" ))
{
cls.legacyserver = from;
}
else
{
if( UI_IsVisible() )
UI_ShowMessageBox( va("^3Server message^7\n%s", args ) );
Msg( "%s", args );
}
}
else if( !Q_strcmp( c, "updatemsg" ))
{
// got an update message from master server
// show update dialog from menu
netadr_t adr;
qboolean preferStore = true;
if( !Q_strcmp( Cmd_Argv( 1 ), "nostore" ) )
preferStore = false;
// trust only hardcoded master server
if( NET_StringToAdr( MASTERSERVER_ADR, &adr ) )
{
if( NET_CompareAdr( from, adr ))
{
UI_ShowUpdateDialog( preferStore );
}
}
else
{
// in case we don't have master anymore
UI_ShowUpdateDialog( preferStore );
}
}
else if( !Q_strcmp( c, "f" )) else if( !Q_strcmp( c, "f" ))
{ {
// serverlist got from masterserver // serverlist got from masterserver
@ -2713,28 +2782,6 @@ void CL_Escape_f( void )
else UI_SetActiveMenu( true ); else UI_SetActiveMenu( true );
} }
/*
=================
CL_WarnLostSplitPacket
=================
*/
void CL_WarnLostSplitPacket( void )
{
if( cls.state != ca_connected )
return;
if( Host_IsLocalClient() )
return;
if( ++cl.lostpackets == 8 )
{
CL_Disconnect();
UI_ShowConnectionWarning();
Con_DPrintf( S_WARN "Too many lost packets! Showing Network options menu\n" );
}
}
/* /*
================= =================
CL_InitLocal CL_InitLocal
@ -2744,6 +2791,7 @@ void CL_InitLocal( void )
{ {
cls.state = ca_disconnected; cls.state = ca_disconnected;
cls.signon = 0; cls.signon = 0;
memset( &cls.serveradr, 0, sizeof( cls.serveradr ) );
cl.resourcesneeded.pNext = cl.resourcesneeded.pPrev = &cl.resourcesneeded; cl.resourcesneeded.pNext = cl.resourcesneeded.pPrev = &cl.resourcesneeded;
cl.resourcesonhand.pNext = cl.resourcesonhand.pPrev = &cl.resourcesonhand; cl.resourcesonhand.pNext = cl.resourcesonhand.pPrev = &cl.resourcesonhand;

View File

@ -618,11 +618,15 @@ typedef struct
file_t *demoheader; // contain demo startup info in case we record a demo on this level file_t *demoheader; // contain demo startup info in case we record a demo on this level
qboolean internetservers_wait; // internetservers is waiting for dns request qboolean internetservers_wait; // internetservers is waiting for dns request
qboolean internetservers_pending; // internetservers is waiting for dns request qboolean internetservers_pending; // internetservers is waiting for dns request
// legacy mode support
qboolean legacymode; // one-way 48 protocol compatibility qboolean legacymode; // one-way 48 protocol compatibility
netadr_t legacyserver; netadr_t legacyserver;
netadr_t legacyservers[MAX_LEGACY_SERVERS]; netadr_t legacyservers[MAX_LEGACY_SERVERS];
int legacyservercount; int legacyservercount;
int extensions; int extensions;
netadr_t serveradr;
} client_static_t; } client_static_t;
#ifdef __cplusplus #ifdef __cplusplus
@ -1075,7 +1079,8 @@ void UI_CharEvent( int key );
qboolean UI_MouseInRect( void ); qboolean UI_MouseInRect( void );
qboolean UI_IsVisible( void ); qboolean UI_IsVisible( void );
void UI_ResetPing( void ); void UI_ResetPing( void );
void UI_ShowConnectionWarning( void ); void UI_ShowUpdateDialog( qboolean preferStore );
void UI_ShowMessageBox( const char *text );
void UI_AddTouchButtonToList( const char *name, const char *texture, const char *command, unsigned char *color, int flags ); void UI_AddTouchButtonToList( const char *name, const char *texture, const char *command, unsigned char *color, int flags );
void pfnPIC_Set( HIMAGE hPic, int r, int g, int b, int a ); void pfnPIC_Set( HIMAGE hPic, int r, int g, int b, int a );
void pfnPIC_Draw( int x, int y, int width, int height, const wrect_t *prc ); void pfnPIC_Draw( int x, int y, int width, int height, const wrect_t *prc );

View File

@ -851,7 +851,6 @@ qboolean CL_IsInConsole( void );
qboolean CL_IsThirdPerson( void ); qboolean CL_IsThirdPerson( void );
qboolean CL_IsIntermission( void ); qboolean CL_IsIntermission( void );
qboolean CL_Initialized( void ); qboolean CL_Initialized( void );
void CL_WarnLostSplitPacket( void );
char *CL_Userinfo( void ); char *CL_Userinfo( void );
void CL_LegacyUpdateInfo( void ); void CL_LegacyUpdateInfo( void );
void CL_CharEvent( int key ); void CL_CharEvent( int key );
@ -952,6 +951,7 @@ void GL_FreeImage( const char *name );
void VID_InitDefaultResolution( void ); void VID_InitDefaultResolution( void );
void VID_Init( void ); void VID_Init( void );
void UI_SetActiveMenu( qboolean fActive ); void UI_SetActiveMenu( qboolean fActive );
void UI_ShowConnectionWarning( void );
void Cmd_Null_f( void ); void Cmd_Null_f( void );
// soundlib shared exports // soundlib shared exports

View File

@ -327,7 +327,7 @@ void CL_ClearStaticEntities( void )
} }
void CL_WarnLostSplitPacket( void ) void UI_ShowConnectionWarning( void )
{ {
} }

View File

@ -140,7 +140,7 @@ qboolean NetSplit_GetLong( netsplit_t *ns, netadr_t *from, byte *data, size_t *l
// warn if previous packet not received // warn if previous packet not received
if( p->received < p->count ) if( p->received < p->count )
{ {
CL_WarnLostSplitPacket(); UI_ShowConnectionWarning();
Con_Reportf( S_WARN "NetSplit_GetLong: lost packet %d\n", p->id ); Con_Reportf( S_WARN "NetSplit_GetLong: lost packet %d\n", p->id );
} }