Browse Source

engine: add stuffcmd filtering, not wired to ClientCmd yet

pull/2/head
Alibek Omarov 3 years ago committed by a1batross
parent
commit
1a1d81de62
  1. 180
      engine/common/cmd.c
  2. 1
      engine/common/common.h
  3. 43
      engine/common/cvar.c
  4. 2
      engine/common/cvar.h
  5. 2
      engine/common/host.c

180
engine/common/cmd.c

@ -30,11 +30,15 @@ typedef struct
} cmdbuf_t; } cmdbuf_t;
qboolean cmd_wait; qboolean cmd_wait;
cmdbuf_t cmd_text; cmdbuf_t cmd_text, filteredcmd_text;
byte cmd_text_buf[MAX_CMD_BUFFER]; byte cmd_text_buf[MAX_CMD_BUFFER];
byte filteredcmd_text_buf[MAX_CMD_BUFFER];
cmdalias_t *cmd_alias; cmdalias_t *cmd_alias;
uint cmd_condition; uint cmd_condition;
int cmd_condlevel; int cmd_condlevel;
static qboolean cmd_currentCommandIsPrivileged;
static void Cmd_ExecuteStringWithPrivilegeCheck( const char *text, qboolean isPrivileged );
/* /*
============================================================================= =============================================================================
@ -52,8 +56,10 @@ Cbuf_Init
void Cbuf_Init( void ) void Cbuf_Init( void )
{ {
cmd_text.data = cmd_text_buf; cmd_text.data = cmd_text_buf;
cmd_text.maxsize = MAX_CMD_BUFFER; filteredcmd_text.data = filteredcmd_text_buf;
cmd_text.cursize = 0;
filteredcmd_text.maxsize = cmd_text.maxsize = MAX_CMD_BUFFER;
filteredcmd_text.cursize = cmd_text.cursize = 0;
} }
/* /*
@ -63,8 +69,9 @@ Cbuf_Clear
*/ */
void Cbuf_Clear( void ) void Cbuf_Clear( void )
{ {
memset( cmd_text.data, 0, sizeof( cmd_text_buf )); memset( cmd_text.data, 0, cmd_text.maxsize );
cmd_text.cursize = 0; memset( filteredcmd_text.data, 0, filteredcmd_text.maxsize );
cmd_text.cursize = filteredcmd_text.cursize = 0;
} }
/* /*
@ -88,6 +95,19 @@ void *Cbuf_GetSpace( cmdbuf_t *buf, int length )
return data; return data;
} }
static void Cbuf_AddTextToBuffer( cmdbuf_t *buf, const char *text )
{
int l = Q_strlen( text );
if(( buf->cursize + l ) >= buf->maxsize )
{
Con_Reportf( S_WARN "%s: overflow\n", __func__ );
return;
}
memcpy( Cbuf_GetSpace( buf, l ), text, l );
}
/* /*
============ ============
Cbuf_AddText Cbuf_AddText
@ -97,16 +117,17 @@ Adds command text at the end of the buffer
*/ */
void Cbuf_AddText( const char *text ) void Cbuf_AddText( const char *text )
{ {
int l = Q_strlen( text ); Cbuf_AddTextToBuffer( &cmd_text, text );
if(( cmd_text.cursize + l ) >= cmd_text.maxsize )
{
Con_Reportf( S_WARN "Cbuf_AddText: overflow\n" );
} }
else
/*
============
Cbuf_AddFilteredText
============
*/
void Cbuf_AddFilteredText( const char *text )
{ {
memcpy( Cbuf_GetSpace( &cmd_text, l ), text, l ); Cbuf_AddTextToBuffer( &filteredcmd_text, text );
}
} }
/* /*
@ -117,43 +138,55 @@ Adds command text immediately after the current command
Adds a \n to the text Adds a \n to the text
============ ============
*/ */
void Cbuf_InsertText( const char *text ) static void Cbuf_InsertTextToBuffer( cmdbuf_t *buf, const char *text )
{ {
int l = Q_strlen( text ); int l = Q_strlen( text );
if(( cmd_text.cursize + l ) >= cmd_text.maxsize ) if(( buf->cursize + l ) >= buf->maxsize )
{ {
Con_Reportf( S_WARN "Cbuf_InsertText: overflow\n" ); Con_Reportf( S_WARN "Cbuf_InsertText: overflow\n" );
} }
else else
{ {
memmove( cmd_text.data + l, cmd_text.data, cmd_text.cursize ); memmove( buf->data + l, buf->data, buf->cursize );
memcpy( cmd_text.data, text, l ); memcpy( buf->data, text, l );
cmd_text.cursize += l; buf->cursize += l;
} }
} }
void Cbuf_InsertText( const char *text )
{
Cbuf_InsertTextToBuffer( &cmd_text, text );
}
/* /*
============ ============
Cbuf_Execute Cbuf_Execute
============ ============
*/ */
void Cbuf_Execute( void ) void Cbuf_ExecuteCommandsFromBuffer( cmdbuf_t *buf, qboolean isPrivileged, int cmdsToExecute )
{ {
char *text; char *text;
char line[MAX_CMD_LINE]; char line[MAX_CMD_LINE];
int i, quotes; int i, quotes;
char *comment; char *comment;
while( cmd_text.cursize ) while( buf->cursize )
{
// limit amount of commands that can be issued
if( cmdsToExecute >= 0 )
{ {
if( !cmdsToExecute-- )
break;
}
// find a \n or ; line break // find a \n or ; line break
text = (char *)cmd_text.data; text = (char *)buf->data;
quotes = false; quotes = false;
comment = NULL; comment = NULL;
for( i = 0; i < cmd_text.cursize; i++ ) for( i = 0; i < buf->cursize; i++ )
{ {
if( !comment ) if( !comment )
{ {
@ -162,7 +195,7 @@ void Cbuf_Execute( void )
if( quotes ) if( quotes )
{ {
// make sure i doesn't get > cursize which causes a negative size in memmove, which is fatal --blub // make sure i doesn't get > cursize which causes a negative size in memmove, which is fatal --blub
if( i < ( cmd_text.cursize - 1 ) && ( text[i+0] == '\\' && (text[i+1] == '"' || text[i+1] == '\\'))) if( i < ( buf->cursize - 1 ) && ( text[i+0] == '\\' && (text[i+1] == '"' || text[i+1] == '\\')))
i++; i++;
} }
else else
@ -191,19 +224,19 @@ void Cbuf_Execute( void )
// delete the text from the command buffer and move remaining commands down // delete the text from the command buffer and move remaining commands down
// this is necessary because commands (exec) can insert data at the // this is necessary because commands (exec) can insert data at the
// beginning of the text buffer // beginning of the text buffer
if( i == cmd_text.cursize ) if( i == buf->cursize )
{ {
cmd_text.cursize = 0; buf->cursize = 0;
} }
else else
{ {
i++; i++;
cmd_text.cursize -= i; buf->cursize -= i;
memmove( cmd_text.data, text + i, cmd_text.cursize ); memmove( buf->data, text + i, buf->cursize );
} }
// execute the command line // execute the command line
Cmd_ExecuteString( line ); Cmd_ExecuteStringWithPrivilegeCheck( line, isPrivileged );
if( cmd_wait ) if( cmd_wait )
{ {
@ -215,6 +248,17 @@ void Cbuf_Execute( void )
} }
} }
/*
============
Cbuf_Execute
============
*/
void Cbuf_Execute( void )
{
Cbuf_ExecuteCommandsFromBuffer( &cmd_text, true, -1 );
Cbuf_ExecuteCommandsFromBuffer( &filteredcmd_text, false, 1 );
}
/* /*
=============== ===============
Cbuf_ExecStuffCmds Cbuf_ExecStuffCmds
@ -282,6 +326,11 @@ void Cbuf_ExecStuffCmds( void )
============================================================================== ==============================================================================
*/ */
qboolean Cmd_CurrentCommandIsPrivileged( void )
{
return cmd_currentCommandIsPrivileged;
}
/* /*
=============== ===============
Cmd_StuffCmds_f Cmd_StuffCmds_f
@ -876,6 +925,32 @@ void Cmd_Else_f( void )
cmd_condition ^= BIT( cmd_condlevel ); cmd_condition ^= BIT( cmd_condlevel );
} }
static qboolean Cmd_ShouldAllowCommand( cmd_t *cmd, qboolean isPrivileged )
{
const char *prefixes[] = { "cl_", "gl_", "r_", "m_", "hud_" };
int i;
// always allow local commands
if( isPrivileged )
return true;
// never allow local only commands from remote
if( FBitSet( cmd->flags, CMD_LOCALONLY ))
return false;
// allow engine commands if user don't mind
if( cl_filterstuffcmd.value <= 0.0f )
return true;
for( i = 0; i < ARRAYSIZE( prefixes ); i++ )
{
if( !Q_stricmp( cmd->name, prefixes[i] ))
return false;
}
return true;
}
/* /*
============ ============
Cmd_ExecuteString Cmd_ExecuteString
@ -883,7 +958,7 @@ Cmd_ExecuteString
A complete command line has been parsed, so try to execute it A complete command line has been parsed, so try to execute it
============ ============
*/ */
void Cmd_ExecuteString( const char *text ) static void Cmd_ExecuteStringWithPrivilegeCheck( const char *text, qboolean isPrivileged )
{ {
cmd_t *cmd = NULL; cmd_t *cmd = NULL;
cmdalias_t *a = NULL; cmdalias_t *a = NULL;
@ -952,44 +1027,56 @@ void Cmd_ExecuteString( const char *text )
if( !host.apply_game_config ) if( !host.apply_game_config )
{ {
// check aliases // check aliases
if( a ) // already found in basecmd if( !a ) // if not found in basecmd
{ {
Cbuf_InsertText( a->value );
return;
}
for( a = cmd_alias; a; a = a->next ) for( a = cmd_alias; a; a = a->next )
{ {
if( !Q_stricmp( cmd_argv[0], a->name )) if( !Q_stricmp( cmd_argv[0], a->name ))
break;
}
}
if( a )
{ {
Cbuf_InsertText( a->value ); Cbuf_InsertTextToBuffer(
isPrivileged ? &cmd_text : &filteredcmd_text,
a->value );
return; return;
} }
} }
}
// special mode for restore game.dll archived cvars // special mode for restore game.dll archived cvars
if( !host.apply_game_config || !Q_strcmp( cmd_argv[0], "exec" )) if( !host.apply_game_config || !Q_strcmp( cmd_argv[0], "exec" ))
{ {
// check functions if( !cmd || !cmd->function ) // if not found in basecmd
if( cmd && cmd->function ) // already found in basecmd
{ {
cmd->function();
return;
}
for( cmd = cmd_functions; cmd; cmd = cmd->next ) for( cmd = cmd_functions; cmd; cmd = cmd->next )
{ {
if( !Q_stricmp( cmd_argv[0], cmd->name ) && cmd->function ) if( !Q_stricmp( cmd_argv[0], cmd->name ) && cmd->function )
break;
}
}
// check functions
if( cmd && cmd->function )
{ {
if( Cmd_ShouldAllowCommand( cmd, isPrivileged ))
{
cmd_currentCommandIsPrivileged = isPrivileged;
cmd->function(); cmd->function();
return; cmd_currentCommandIsPrivileged = true;
} }
else
{
Con_Printf( S_WARN "Could not execute privileged command %s\n", cmd->name );
}
return;
} }
} }
// check cvars // check cvars
if( Cvar_Command( cvar )) return; if( Cvar_CommandWithPrivilegeCheck( cvar, isPrivileged )) return;
if( host.apply_game_config ) if( host.apply_game_config )
return; // don't send nothing to server: we is a server! return; // don't send nothing to server: we is a server!
@ -1011,6 +1098,11 @@ void Cmd_ExecuteString( const char *text )
} }
} }
void Cmd_ExecuteString( const char *text )
{
Cmd_ExecuteStringWithPrivilegeCheck( text, true );
}
/* /*
=================== ===================
Cmd_ForwardToServer Cmd_ForwardToServer

1
engine/common/common.h

@ -184,6 +184,7 @@ extern convar_t host_developer;
extern convar_t *host_limitlocal; extern convar_t *host_limitlocal;
extern convar_t *host_framerate; extern convar_t *host_framerate;
extern convar_t *host_maxfps; extern convar_t *host_maxfps;
extern convar_t cl_filterstuffcmd;
/* /*
============================================================== ==============================================================

43
engine/common/cvar.c

@ -16,6 +16,7 @@ GNU General Public License for more details.
#include <math.h> // fabs... #include <math.h> // fabs...
#include "common.h" #include "common.h"
#include "base_cmd.h" #include "base_cmd.h"
#include "eiface.h" // ARRAYSIZE
convar_t *cvar_vars = NULL; // head of list convar_t *cvar_vars = NULL; // head of list
convar_t *cmd_scripting; convar_t *cmd_scripting;
@ -754,6 +755,38 @@ static void Cvar_SetGL( const char *name, const char *value )
Cvar_FullSet( name, value, FCVAR_GLCONFIG ); Cvar_FullSet( name, value, FCVAR_GLCONFIG );
} }
static qboolean Cvar_ShouldSetCvar( convar_t *v, qboolean isPrivileged )
{
const char *prefixes[] = { "cl_", "gl_", "m_", "r_", "hud_" };
int i;
if( isPrivileged )
return true;
// TODO: figure this out
//if( v->flags & FCVAR_SERVER )
// return false;
if( cl_filterstuffcmd.value <= 0.0f )
return true;
// TODO: figure this out too
//if( v->flags & FCVAR_EXTDLL )
// return false;
// a1ba: xash3d-fwgs extension
if( v->flags & FCVAR_LOCALONLY )
return false;
for( i = 0; i < ARRAYSIZE( prefixes ); i++ )
{
if( Q_stricmp( v->name, prefixes[i] ))
return false;
}
return true;
}
/* /*
============ ============
Cvar_Command Cvar_Command
@ -761,7 +794,7 @@ Cvar_Command
Handles variable inspection and changing from the console Handles variable inspection and changing from the console
============ ============
*/ */
qboolean Cvar_Command( convar_t *v ) qboolean Cvar_CommandWithPrivilegeCheck( convar_t *v, qboolean isPrivileged )
{ {
// special case for setup opengl configuration // special case for setup opengl configuration
if( host.apply_opengl_config ) if( host.apply_opengl_config )
@ -773,7 +806,8 @@ qboolean Cvar_Command( convar_t *v )
// check variables // check variables
if( !v ) // already found in basecmd if( !v ) // already found in basecmd
v = Cvar_FindVar( Cmd_Argv( 0 )); v = Cvar_FindVar( Cmd_Argv( 0 ));
if( !v ) return false; if( !v )
return false;
// perform a variable print or set // perform a variable print or set
if( Cmd_Argc() == 1 ) if( Cmd_Argc() == 1 )
@ -796,6 +830,11 @@ qboolean Cvar_Command( convar_t *v )
Con_Printf( "can't set \"%s\" in multiplayer\n", v->name ); Con_Printf( "can't set \"%s\" in multiplayer\n", v->name );
return false; return false;
} }
else if( !Cvar_ShouldSetCvar( v, isPrivileged ))
{
Con_Printf( "%s is a privileged variable\n", v->name );
return true;
}
else else
{ {
Cvar_DirectSet( v, Cmd_Argv( 1 )); Cvar_DirectSet( v, Cmd_Argv( 1 ));

2
engine/common/cvar.h

@ -75,7 +75,7 @@ void Cvar_WriteVariables( file_t *f, int group );
qboolean Cvar_Exists( const char *var_name ); qboolean Cvar_Exists( const char *var_name );
void Cvar_Reset( const char *var_name ); void Cvar_Reset( const char *var_name );
void Cvar_SetCheatState( void ); void Cvar_SetCheatState( void );
qboolean Cvar_Command( convar_t *v ); qboolean Cvar_CommandWithPrivilegeCheck( convar_t *v, qboolean isPrivileged );
void Cvar_Init( void ); void Cvar_Init( void );
void Cvar_Unlink( int group ); void Cvar_Unlink( int group );

2
engine/common/host.c

@ -52,6 +52,7 @@ struct tests_stats_s tests_stats;
CVAR_DEFINE( host_developer, "developer", "0", 0, "engine is in development-mode" ); CVAR_DEFINE( host_developer, "developer", "0", 0, "engine is in development-mode" );
CVAR_DEFINE_AUTO( sys_ticrate, "100", 0, "framerate in dedicated mode" ); CVAR_DEFINE_AUTO( sys_ticrate, "100", 0, "framerate in dedicated mode" );
CVAR_DEFINE_AUTO( cl_filterstuffcmd, "1", FCVAR_ARCHIVE | FCVAR_LOCALONLY, "filter commands coming from server" );
convar_t *host_serverstate; convar_t *host_serverstate;
convar_t *host_gameloaded; convar_t *host_gameloaded;
@ -1051,6 +1052,7 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
Cmd_AddCommand ( "crash", Host_Crash_f, "a way to force a bus error for development reasons"); Cmd_AddCommand ( "crash", Host_Crash_f, "a way to force a bus error for development reasons");
} }
Cvar_RegisterVariable( &cl_filterstuffcmd );
host_serverstate = Cvar_Get( "host_serverstate", "0", FCVAR_READ_ONLY, "displays current server state" ); host_serverstate = Cvar_Get( "host_serverstate", "0", FCVAR_READ_ONLY, "displays current server state" );
host_maxfps = Cvar_Get( "fps_max", "72", FCVAR_ARCHIVE, "host fps upper limit" ); host_maxfps = Cvar_Get( "fps_max", "72", FCVAR_ARCHIVE, "host fps upper limit" );
host_framerate = Cvar_Get( "host_framerate", "0", 0, "locks frame timing to this value in seconds" ); host_framerate = Cvar_Get( "host_framerate", "0", 0, "locks frame timing to this value in seconds" );

Loading…
Cancel
Save