Harden the mod against hostile servers and players
- PacketReader for all network data: lengths are checked against the real data (Mono allocated the claimed size first - a fake 2 GB length crashed the game) - FsmSync: remote players can no longer switch arbitrary FSMs - never PLAYER / Systems / MSCO objects, CLICK only on FSMs that wait for a click, bolt/assembly events only along a transition the FSM really has for that event - Time/weather (msco.world) and '* ' system-style chat only from the host in P2P (the dedicated server filters them itself); other msco.* ids are reserved Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+34
@@ -292,6 +292,11 @@ namespace MSCO
|
||||
if (Debug) MscoLog.Warning("[MSCO] << not found: " + msg.Path + " [" + msg.FsmName + "]");
|
||||
return;
|
||||
}
|
||||
if (!Allowed(fsm, msg))
|
||||
{
|
||||
if (Debug) MscoLog.Warning("[MSCO] << refused: " + msg.EventName + " " + msg.Path + " [" + msg.FsmName + " -> " + msg.State + "]");
|
||||
return;
|
||||
}
|
||||
if (msg.EventName == VehicleAdmin.InstallEvent) { VehicleAdmin.InstallRemote(fsm); return; } // Admin hat ein Teil eingebaut
|
||||
FsmState state = fsm.Fsm.GetState(msg.State);
|
||||
if (state == null || switchState == null) return;
|
||||
@@ -304,6 +309,35 @@ namespace MSCO
|
||||
finally { applying--; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Darf ein Mitspieler diese FSM in diesen Zustand schalten? Sonst könnte ein manipulierter Client beliebige
|
||||
/// Zustände bei allen anderen auslösen (z.B. Tod oder Speichern). Nie: der eigene Spieler (PLAYER), Systeme
|
||||
/// (Tod, Speichern ...), MSCO selbst. Klicks nur auf FSMs, die auf einen Klick warten; Schrauben/Montage nur
|
||||
/// über einen Übergang, den die FSM für genau dieses Event auch hat.
|
||||
/// </summary>
|
||||
static bool Allowed(PlayMakerFSM fsm, FsmEventMsg msg)
|
||||
{
|
||||
try
|
||||
{
|
||||
string root = fsm.transform.root.name;
|
||||
if (root == "PLAYER" || root == "Systems" || root.StartsWith("MSCO_")) return false;
|
||||
if (msg.EventName == VehicleAdmin.InstallEvent) return fsm.FsmName == "Assembly";
|
||||
if (msg.EventName == "CLICK")
|
||||
{
|
||||
foreach (FsmState s in fsm.FsmStates) if (ChecksInput(s)) return fsm.Fsm.GetState(msg.State) != null;
|
||||
return false;
|
||||
}
|
||||
if (Array.IndexOf(SyncedEvents, msg.EventName) < 0) return false;
|
||||
foreach (FsmState s in fsm.FsmStates)
|
||||
foreach (FsmTransition t in s.Transitions)
|
||||
if (t.EventName == msg.EventName && t.ToState == msg.State) return true;
|
||||
foreach (FsmTransition t in fsm.Fsm.GlobalTransitions)
|
||||
if (t.EventName == msg.EventName && t.ToState == msg.State) return true;
|
||||
return false;
|
||||
}
|
||||
catch { return false; }
|
||||
}
|
||||
|
||||
/// <summary>FSM in einen Zustand schalten, ohne dass das als eigene Aktion erkannt und gesendet wird.</summary>
|
||||
public static void SwitchStateSilently(PlayMakerFSM fsm, FsmState state)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user