Remove C4ControlScript::fInternal

fInternal basically acted as a reverse "evil bit" as in RFC 3514: when
set, the engine would not do any checks on the script contained in the
control packet, nor log the script (visibly in game; the packet log
would of course contain the packet). A malicious game client thus would
be able to inject arbitrary script without people (immediately) noticing
anything was amiss.

As of this patch, only the host is able to execute arbitrary scripts,
and those will be shown in the message board for all players to see.
This privilege can be irrevocably disabled in network games by any
client by using the "/nodebug" message board command.

Closes #936.
stable-5.4
Nicolas Hake 2013-09-04 20:18:06 +02:00
parent 9b82abb8a0
commit 7e260aa9de
5 changed files with 26 additions and 28 deletions

View File

@ -238,7 +238,10 @@ void C4ControlScript::Execute() const
{
const char *szScript = Script.getData();
// user script: from host only
if (!fInternal && (iByClient != C4ClientIDHost) && !Console.Active) return;
if ((iByClient != C4ClientIDHost) && !Console.Active) return;
// only allow scripts when debug mode is not forbidden
if (!Game.Parameters.AllowDebug) return;
// execute
C4Object *pObj = NULL;
C4AulScript *pScript;
@ -260,33 +263,29 @@ void C4ControlScript::Execute() const
}
#endif
// show messages
if (!fInternal)
// print script
if (pObj)
LogF("-> %s::%s", pObj->Def->GetName(), szScript);
else
LogF("-> %s", szScript);
// print result
if (!LocalControl())
{
// print script
if (pObj)
LogF("-> %s::%s", pObj->Def->GetName(), szScript);
C4Network2Client *pClient = NULL;
if (::Network.isEnabled())
pClient = ::Network.Clients.GetClientByID(iByClient);
if (pClient)
LogF(" = %s (by %s)", rVal.GetDataString().getData(), pClient->getName());
else
LogF("-> %s", szScript);
// print result
if (!LocalControl())
{
C4Network2Client *pClient = NULL;
if (::Network.isEnabled())
pClient = ::Network.Clients.GetClientByID(iByClient);
if (pClient)
LogF(" = %s (by %s)", rVal.GetDataString().getData(), pClient->getName());
else
LogF(" = %s (by client %d)", rVal.GetDataString().getData(), iByClient);
}
else
LogF(" = %s", rVal.GetDataString().getData());
LogF(" = %s (by client %d)", rVal.GetDataString().getData(), iByClient);
}
else
LogF(" = %s", rVal.GetDataString().getData());
}
void C4ControlScript::CompileFunc(StdCompiler *pComp)
{
pComp->Value(mkNamingAdapt(iTargetObj, "TargetObj", -1));
pComp->Value(mkNamingAdapt(fInternal, "Internal", false));
pComp->Value(mkNamingAdapt(fUseVarsFromCallerContext, "UseVarsFromCallerContext", false));
pComp->Value(mkNamingAdapt(Script, "Script", ""));
C4ControlPacket::CompileFunc(pComp);
@ -1256,7 +1255,7 @@ void C4ControlEMMoveObject::Execute() const
{
if (!pObjects) return;
// execute script ...
C4ControlScript ScriptCtrl(Script.getData(), C4ControlScript::SCOPE_Global, false);
C4ControlScript ScriptCtrl(Script.getData(), C4ControlScript::SCOPE_Global);
ScriptCtrl.SetByClient(iByClient);
// ... for each object in selection
for (int i=0; i<iObjectNum; ++i)

View File

@ -137,14 +137,13 @@ public:
enum { SCOPE_Console=-2, SCOPE_Global=-1 }; // special scopes to be passed as target objects
C4ControlScript()
: iTargetObj(-1), fInternal(true), fUseVarsFromCallerContext(false)
: iTargetObj(-1), fUseVarsFromCallerContext(false)
{ }
C4ControlScript(const char *szScript, int32_t iTargetObj = SCOPE_Global, bool fInternal = true, bool fUseVarsFromCallerContext = false)
: iTargetObj(iTargetObj), fInternal(fInternal), fUseVarsFromCallerContext(fUseVarsFromCallerContext), Script(szScript, true)
C4ControlScript(const char *szScript, int32_t iTargetObj, bool fUseVarsFromCallerContext = false)
: iTargetObj(iTargetObj), fUseVarsFromCallerContext(fUseVarsFromCallerContext), Script(szScript, true)
{ }
protected:
int32_t iTargetObj;
bool fInternal; // silent execute
bool fUseVarsFromCallerContext;
StdStrBuf Script;
public:

View File

@ -92,7 +92,7 @@ bool C4Console::In(const char *szText)
// editing enabled?
if (!EditCursor.EditingOK()) return false;
// pass through network queue
::Control.DoInput(CID_Script, new C4ControlScript(szText, C4ControlScript::SCOPE_Console, false), CDT_Decide);
::Control.DoInput(CID_Script, new C4ControlScript(szText, C4ControlScript::SCOPE_Console), CDT_Decide);
return true;
}

View File

@ -605,7 +605,7 @@ bool C4MessageInput::ProcessCommand(const char *szCommand)
if (!::Network.isEnabled() && Game.ScenarioFile.IsPacked()) return false;
if (::Network.isEnabled() && !::Network.isHost()) return false;
::Control.DoInput(CID_Script, new C4ControlScript(pCmdPar, C4ControlScript::SCOPE_Console, false), CDT_Decide);
::Control.DoInput(CID_Script, new C4ControlScript(pCmdPar, C4ControlScript::SCOPE_Console), CDT_Decide);
return true;
}
// set runtime properties

View File

@ -232,7 +232,7 @@ void C4AulDebug::ProcessLine(const StdStrBuf &Line)
int32_t objectNum = C4ControlScript::SCOPE_Global;
if (context && context->Obj && context->Obj->GetObject())
objectNum = context->Obj->GetObject()->Number;
::Control.DoInput(CID_Script, new C4ControlScript(szData, objectNum, false, true), CDT_Decide);
::Control.DoInput(CID_Script, new C4ControlScript(szData, objectNum, true), CDT_Decide);
}
else if (SEqualNoCase(szCmd, "PSE"))
if (Game.IsPaused())