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. 186
      engine/common/cmd.c
  2. 3
      engine/common/common.h
  3. 43
      engine/common/cvar.c
  4. 2
      engine/common/cvar.h
  5. 2
      engine/common/host.c

186
engine/common/cmd.c

@ -30,11 +30,15 @@ typedef struct @@ -30,11 +30,15 @@ typedef struct
} cmdbuf_t;
qboolean cmd_wait;
cmdbuf_t cmd_text;
cmdbuf_t cmd_text, filteredcmd_text;
byte cmd_text_buf[MAX_CMD_BUFFER];
byte filteredcmd_text_buf[MAX_CMD_BUFFER];
cmdalias_t *cmd_alias;
uint cmd_condition;
int cmd_condlevel;
static qboolean cmd_currentCommandIsPrivileged;
static void Cmd_ExecuteStringWithPrivilegeCheck( const char *text, qboolean isPrivileged );
/*
=============================================================================
@ -52,8 +56,10 @@ Cbuf_Init @@ -52,8 +56,10 @@ Cbuf_Init
void Cbuf_Init( void )
{
cmd_text.data = cmd_text_buf;
cmd_text.maxsize = MAX_CMD_BUFFER;
cmd_text.cursize = 0;
filteredcmd_text.data = filteredcmd_text_buf;
filteredcmd_text.maxsize = cmd_text.maxsize = MAX_CMD_BUFFER;
filteredcmd_text.cursize = cmd_text.cursize = 0;
}
/*
@ -63,8 +69,9 @@ Cbuf_Clear @@ -63,8 +69,9 @@ Cbuf_Clear
*/
void Cbuf_Clear( void )
{
memset( cmd_text.data, 0, sizeof( cmd_text_buf ));
cmd_text.cursize = 0;
memset( cmd_text.data, 0, cmd_text.maxsize );
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 ) @@ -88,6 +95,19 @@ void *Cbuf_GetSpace( cmdbuf_t *buf, int length )
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
@ -97,16 +117,17 @@ Adds command text at the end of the buffer @@ -97,16 +117,17 @@ Adds command text at the end of the buffer
*/
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
{
memcpy( Cbuf_GetSpace( &cmd_text, l ), text, l );
}
/*
============
Cbuf_AddFilteredText
============
*/
void Cbuf_AddFilteredText( const char *text )
{
Cbuf_AddTextToBuffer( &filteredcmd_text, text );
}
/*
@ -117,43 +138,55 @@ Adds command text immediately after the current command @@ -117,43 +138,55 @@ Adds command text immediately after the current command
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 );
if(( cmd_text.cursize + l ) >= cmd_text.maxsize )
if(( buf->cursize + l ) >= buf->maxsize )
{
Con_Reportf( S_WARN "Cbuf_InsertText: overflow\n" );
}
else
{
memmove( cmd_text.data + l, cmd_text.data, cmd_text.cursize );
memcpy( cmd_text.data, text, l );
cmd_text.cursize += l;
memmove( buf->data + l, buf->data, buf->cursize );
memcpy( buf->data, text, l );
buf->cursize += l;
}
}
void Cbuf_InsertText( const char *text )
{
Cbuf_InsertTextToBuffer( &cmd_text, text );
}
/*
============
Cbuf_Execute
============
*/
void Cbuf_Execute( void )
void Cbuf_ExecuteCommandsFromBuffer( cmdbuf_t *buf, qboolean isPrivileged, int cmdsToExecute )
{
char *text;
char line[MAX_CMD_LINE];
int i, quotes;
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
text = (char *)cmd_text.data;
text = (char *)buf->data;
quotes = false;
comment = NULL;
for( i = 0; i < cmd_text.cursize; i++ )
for( i = 0; i < buf->cursize; i++ )
{
if( !comment )
{
@ -162,7 +195,7 @@ void Cbuf_Execute( void ) @@ -162,7 +195,7 @@ void Cbuf_Execute( void )
if( quotes )
{
// 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++;
}
else
@ -191,19 +224,19 @@ void Cbuf_Execute( void ) @@ -191,19 +224,19 @@ void Cbuf_Execute( void )
// delete the text from the command buffer and move remaining commands down
// this is necessary because commands (exec) can insert data at the
// beginning of the text buffer
if( i == cmd_text.cursize )
if( i == buf->cursize )
{
cmd_text.cursize = 0;
buf->cursize = 0;
}
else
{
i++;
cmd_text.cursize -= i;
memmove( cmd_text.data, text + i, cmd_text.cursize );
buf->cursize -= i;
memmove( buf->data, text + i, buf->cursize );
}
// execute the command line
Cmd_ExecuteString( line );
Cmd_ExecuteStringWithPrivilegeCheck( line, isPrivileged );
if( cmd_wait )
{
@ -215,6 +248,17 @@ void Cbuf_Execute( void ) @@ -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
@ -282,6 +326,11 @@ void Cbuf_ExecStuffCmds( void ) @@ -282,6 +326,11 @@ void Cbuf_ExecStuffCmds( void )
==============================================================================
*/
qboolean Cmd_CurrentCommandIsPrivileged( void )
{
return cmd_currentCommandIsPrivileged;
}
/*
===============
Cmd_StuffCmds_f
@ -876,6 +925,32 @@ void Cmd_Else_f( void ) @@ -876,6 +925,32 @@ void Cmd_Else_f( void )
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
@ -883,7 +958,7 @@ Cmd_ExecuteString @@ -883,7 +958,7 @@ Cmd_ExecuteString
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;
cmdalias_t *a = NULL;
@ -952,44 +1027,56 @@ void Cmd_ExecuteString( const char *text ) @@ -952,44 +1027,56 @@ void Cmd_ExecuteString( const char *text )
if( !host.apply_game_config )
{
// 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 )
{
if( !Q_stricmp( cmd_argv[0], a->name ))
break;
}
}
for( a = cmd_alias; a; a = a->next )
if( a )
{
if( !Q_stricmp( cmd_argv[0], a->name ))
{
Cbuf_InsertText( a->value );
return;
}
Cbuf_InsertTextToBuffer(
isPrivileged ? &cmd_text : &filteredcmd_text,
a->value );
return;
}
}
// special mode for restore game.dll archived cvars
if( !host.apply_game_config || !Q_strcmp( cmd_argv[0], "exec" ))
{
// check functions
if( cmd && cmd->function ) // already found in basecmd
if( !cmd || !cmd->function ) // if not found in basecmd
{
cmd->function();
return;
for( cmd = cmd_functions; cmd; cmd = cmd->next )
{
if( !Q_stricmp( cmd_argv[0], cmd->name ) && cmd->function )
break;
}
}
for( cmd = cmd_functions; cmd; cmd = cmd->next )
// check functions
if( cmd && cmd->function )
{
if( !Q_stricmp( cmd_argv[0], cmd->name ) && cmd->function )
if( Cmd_ShouldAllowCommand( cmd, isPrivileged ))
{
cmd_currentCommandIsPrivileged = isPrivileged;
cmd->function();
return;
cmd_currentCommandIsPrivileged = true;
}
else
{
Con_Printf( S_WARN "Could not execute privileged command %s\n", cmd->name );
}
return;
}
}
// check cvars
if( Cvar_Command( cvar )) return;
if( Cvar_CommandWithPrivilegeCheck( cvar, isPrivileged )) return;
if( host.apply_game_config )
return; // don't send nothing to server: we is a server!
@ -1011,6 +1098,11 @@ void Cmd_ExecuteString( const char *text ) @@ -1011,6 +1098,11 @@ void Cmd_ExecuteString( const char *text )
}
}
void Cmd_ExecuteString( const char *text )
{
Cmd_ExecuteStringWithPrivilegeCheck( text, true );
}
/*
===================
Cmd_ForwardToServer

3
engine/common/common.h

@ -184,6 +184,7 @@ extern convar_t host_developer; @@ -184,6 +184,7 @@ extern convar_t host_developer;
extern convar_t *host_limitlocal;
extern convar_t *host_framerate;
extern convar_t *host_maxfps;
extern convar_t cl_filterstuffcmd;
/*
==============================================================
@ -465,7 +466,7 @@ extern sysinfo_t SI; @@ -465,7 +466,7 @@ extern sysinfo_t SI;
#define CMD_CLIENTDLL BIT( 1 ) // added by client.dll
#define CMD_GAMEUIDLL BIT( 2 ) // added by GameUI.dll
#define CMD_LOCALONLY BIT( 3 ) // restricted from server commands
#define CMD_REFDLL BIT( 4 ) // added by ref.dll
#define CMD_REFDLL BIT( 4 ) // added by ref.dll
typedef void (*xcommand_t)( void );

43
engine/common/cvar.c

@ -16,6 +16,7 @@ GNU General Public License for more details. @@ -16,6 +16,7 @@ GNU General Public License for more details.
#include <math.h> // fabs...
#include "common.h"
#include "base_cmd.h"
#include "eiface.h" // ARRAYSIZE
convar_t *cvar_vars = NULL; // head of list
convar_t *cmd_scripting;
@ -754,6 +755,38 @@ static void Cvar_SetGL( const char *name, const char *value ) @@ -754,6 +755,38 @@ static void Cvar_SetGL( const char *name, const char *value )
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
@ -761,7 +794,7 @@ Cvar_Command @@ -761,7 +794,7 @@ Cvar_Command
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
if( host.apply_opengl_config )
@ -773,7 +806,8 @@ qboolean Cvar_Command( convar_t *v ) @@ -773,7 +806,8 @@ qboolean Cvar_Command( convar_t *v )
// check variables
if( !v ) // already found in basecmd
v = Cvar_FindVar( Cmd_Argv( 0 ));
if( !v ) return false;
if( !v )
return false;
// perform a variable print or set
if( Cmd_Argc() == 1 )
@ -796,6 +830,11 @@ qboolean Cvar_Command( convar_t *v ) @@ -796,6 +830,11 @@ qboolean Cvar_Command( convar_t *v )
Con_Printf( "can't set \"%s\" in multiplayer\n", v->name );
return false;
}
else if( !Cvar_ShouldSetCvar( v, isPrivileged ))
{
Con_Printf( "%s is a privileged variable\n", v->name );
return true;
}
else
{
Cvar_DirectSet( v, Cmd_Argv( 1 ));

2
engine/common/cvar.h

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

2
engine/common/host.c

@ -52,6 +52,7 @@ struct tests_stats_s tests_stats; @@ -52,6 +52,7 @@ struct tests_stats_s tests_stats;
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( cl_filterstuffcmd, "1", FCVAR_ARCHIVE | FCVAR_LOCALONLY, "filter commands coming from server" );
convar_t *host_serverstate;
convar_t *host_gameloaded;
@ -1051,6 +1052,7 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa @@ -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");
}
Cvar_RegisterVariable( &cl_filterstuffcmd );
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_framerate = Cvar_Get( "host_framerate", "0", 0, "locks frame timing to this value in seconds" );

Loading…
Cancel
Save