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
Cvar_FullSet( "cl_background", "0", FCVAR_READ_ONLY );
cls.state = ca_disconnected;
memset( &cls.serveradr, 0, sizeof( cls.serveradr ) );
cls.set_lastdemo = false;
S_StopBackgroundTrack();
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 )
{
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 )
{
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.state = ca_connecting;
Q_strncpy( cls.servername, "localhost", sizeof( cls.servername ));
cls.serveradr.type = NA_LOOPBACK;
// we don't need a challenge on the localhost
CL_SendConnectPacket();
return;
@ -1150,6 +1152,7 @@ void CL_CheckForResend( void )
return;
}
cls.serveradr = adr;
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_retry++;
@ -1501,6 +1504,7 @@ void CL_Disconnect( void )
IN_LockInputDevices( false ); // unlock input devices
cls.state = ca_disconnected;
memset( &cls.serveradr, 0, sizeof( cls.serveradr ) );
cls.set_lastdemo = false;
cls.connect_retry = 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
@ -1887,6 +1904,9 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
// server connection
if( !Q_strcmp( c, "client_connect" ))
{
if( !CL_IsFromConnectingServer( from ))
return;
if( cls.state == ca_connected )
{
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
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" ))
{
byte recv_buf[NET_MAX_FRAGMENT];
dword crcValue = MSG_ReadLong( msg );
int realsize = MSG_GetMaxBytes( msg ) - MSG_GetNumBytesRead( msg );
dword crcValue;
int realsize;
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.connect_retry >= CL_TEST_RETRIES )
@ -1999,6 +2017,9 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
}
else if( !Q_strcmp( c, "challenge" ))
{
if( !CL_IsFromConnectingServer( from ))
return;
// challenge from the server we are connecting to
cls.challenge = Q_atoi( Cmd_Argv( 1 ));
CL_SendConnectPacket();
@ -2006,11 +2027,17 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
}
else if( !Q_strcmp( c, "echo" ))
{
if( !CL_IsFromConnectingServer( from ))
return;
// echo request from server
Netchan_OutOfBandPrint( NS_CLIENT, from, "%s", Cmd_Argv( 1 ));
}
else if( !Q_strcmp( c, "disconnect" ))
{
if( !CL_IsFromConnectingServer( from ))
return;
// a disconnect message from the server, which will happen if the server
// dropped the connection but it is still getting packets from us
CL_Disconnect_f();
@ -2021,6 +2048,48 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
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" ))
{
// serverlist got from masterserver
@ -2713,28 +2782,6 @@ void CL_Escape_f( void )
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
@ -2744,6 +2791,7 @@ void CL_InitLocal( void )
{
cls.state = ca_disconnected;
cls.signon = 0;
memset( &cls.serveradr, 0, sizeof( cls.serveradr ) );
cl.resourcesneeded.pNext = cl.resourcesneeded.pPrev = &cl.resourcesneeded;
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
qboolean internetservers_wait; // 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
netadr_t legacyserver;
netadr_t legacyservers[MAX_LEGACY_SERVERS];
int legacyservercount;
int extensions;
netadr_t serveradr;
} client_static_t;
#ifdef __cplusplus
@ -1075,7 +1079,8 @@ void UI_CharEvent( int key );
qboolean UI_MouseInRect( void );
qboolean UI_IsVisible( 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 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 );

View File

@ -851,7 +851,6 @@ qboolean CL_IsInConsole( void );
qboolean CL_IsThirdPerson( void );
qboolean CL_IsIntermission( void );
qboolean CL_Initialized( void );
void CL_WarnLostSplitPacket( void );
char *CL_Userinfo( void );
void CL_LegacyUpdateInfo( void );
void CL_CharEvent( int key );
@ -952,6 +951,7 @@ void GL_FreeImage( const char *name );
void VID_InitDefaultResolution( void );
void VID_Init( void );
void UI_SetActiveMenu( qboolean fActive );
void UI_ShowConnectionWarning( void );
void Cmd_Null_f( void );
// 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
if( p->received < p->count )
{
CL_WarnLostSplitPacket();
UI_ShowConnectionWarning();
Con_Reportf( S_WARN "NetSplit_GetLong: lost packet %d\n", p->id );
}