]> git.deb.at Git - rhonda/impostor.git/commitdiff
Gate PackedGameDataTo behind AC check v1.10.6
authorminiduikboot <mini@duikbo.at>
Sat, 23 May 2026 10:52:26 +0000 (12:52 +0200)
committerminiduikboot <mini@duikbo.at>
Sun, 24 May 2026 18:36:02 +0000 (20:36 +0200)
docs/Server-configuration.md
src/Impostor.Api/CheatCategory.cs
src/Impostor.Api/Config/AntiCheatConfig.cs
src/Impostor.Api/Net/Messages/MessageFlags.cs
src/Impostor.Server/Net/Client.cs

index a39b3c570abc85e921af8f502c177f12f9e331fd..61891296698a4eb7a25fcf4accba0ab3eed112a2 100644 (file)
@@ -25,20 +25,21 @@ Impostor has an Http Server that is used by recent versions of Among Us to conne
 
 Impostor has an Anticheat that makes it possible to kick cheaters from games automatically. Note that the anticheat is tuned on the vanilla version of the game, so client-side modifications could trigger the Anticheat if you're playing with them.
 
-| Key                           | Default   | Value                                                                                                                                                                                                               |
-|-------------------------------|-----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| **Enabled**                   | `true`    | Whether the anticheat should be enabled.                                                                                                                                                                            |
-| **BanIpFromGame**             | `true`    | When anticheat is enabled and a player is caught hacking, they will be kicked from the server. If this value is set to `true`, the player will be banned instead and will not be able to rejoin that specific game. |
-| **AllowCheatingHosts**        | `"Never"` | Configure whether hosts are allowed to cheat. "Never" forbids it, "Always" allows it. "IfRequested" allows hosts to cheat if they connect with the DisableServerAuthorityFlag set.                                  |
-| **EnableGameFlowChecks**      | `true`    | Enable checks that check if certain actions are done in the appropriate order or at the appropriate moment in the game. This includes changing cosmetics while in game or murdering too fast.                       |
-| **EnableInvalidObjectChecks** | `true`    | Enables checks that check if network objects are spawned properly. Disabling this option also implies disabling EnableRoleChecks.                                                                                   |
-| **EnableMustBeHostChecks**    | `true`    | Enables checks that check if players are the host before they can do actions that require them to be host of the game. This includes starting the game and spawning objects.                                        |
-| **EnableColorLimitChecks**    | `true`    | Enables checks that checks if players request colors that are already in use.                                                                                                                                       |
-| **EnableNameLimitChecks**     | `true`    | Enables checks that checks if player names have a length that is possible to set using the user interface.                                                                                                          |
-| **EnableOwnershipChecks**     | `true`    | Enables checks that check if players are allowed to perform a certain action on themself or another player.                                                                                                         |
-| **EnableRoleChecks**          | `true`    | Enables checks that check if players have the correct role when performing certain role abilities like venting or murdering.                                                                                        |
-| **EnableTargetChecks**        | `true`    | Enables checks that check if certain packets to everyone that should only have been sent to certain players or vice versa. This includes sending votes or network objects.                                          |
-| **ForbidProtocolExtensions**  | `true`    | If disabled allows players to send network packets that go beyond the network packets sent by the vanilla game. This is necessary for most mods that need all players to install it.                                |
+| Key                           | Default       | Value                                                                                                                                                                                                               |
+|-------------------------------|---------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| **Enabled**                   | `true`        | Whether the anticheat should be enabled.                                                                                                                                                                            |
+| **BanIpFromGame**             | `true`        | When anticheat is enabled and a player is caught hacking, they will be kicked from the server. If this value is set to `true`, the player will be banned instead and will not be able to rejoin that specific game. |
+| **AllowCheatingHosts**        | `"Never"`     | Configure whether hosts are allowed to cheat. "Never" forbids it, "Always" allows it. "IfRequested" allows hosts to cheat if they connect with the DisableServerAuthorityFlag set.                                  |
+| **AllowHostOnlyExtensions**   | "IfRequested" | Configure whether [Host-Only extensions](https://github.com/Innersloth-LLC/AmongUsModdingInformation#host-only-mods) are allowed in all games ("Always"), +25 games only ("IfRequested") or by nobody ("Never")     |
+| **EnableGameFlowChecks**      | `true`        | Enable checks that check if certain actions are done in the appropriate order or at the appropriate moment in the game. This includes changing cosmetics while in game or murdering too fast.                       |
+| **EnableInvalidObjectChecks** | `true`        | Enables checks that check if network objects are spawned properly. Disabling this option also implies disabling EnableRoleChecks.                                                                                   |
+| **EnableMustBeHostChecks**    | `true`        | Enables checks that check if players are the host before they can do actions that require them to be host of the game. This includes starting the game and spawning objects.                                        |
+| **EnableColorLimitChecks**    | `true`        | Enables checks that checks if players request colors that are already in use.                                                                                                                                       |
+| **EnableNameLimitChecks**     | `true`        | Enables checks that checks if player names have a length that is possible to set using the user interface.                                                                                                          |
+| **EnableOwnershipChecks**     | `true`        | Enables checks that check if players are allowed to perform a certain action on themself or another player.                                                                                                         |
+| **EnableRoleChecks**          | `true`        | Enables checks that check if players have the correct role when performing certain role abilities like venting or murdering.                                                                                        |
+| **EnableTargetChecks**        | `true`        | Enables checks that check if certain packets to everyone that should only have been sent to certain players or vice versa. This includes sending votes or network objects.                                          |
+| **ForbidProtocolExtensions**  | `true`        | If disabled allows players to send network packets that go beyond the network packets sent by the vanilla game. This is necessary for most mods that need all players to install it.                                |
 
 ### Compatibility
 
index 9972268ce54d581193a982c9d7a21bdf0641e0b2..26f6c5a67cb618d8747e9ba21b14ced3dbb70b21 100644 (file)
@@ -5,6 +5,9 @@ public enum CheatCategory
     /// <summary>A packet used a part of the network protocol that is unknown to Impostor, like a custom RPC.</summary>
     ProtocolExtension,
 
+    /// <summary>A host-only mod extension is used outside of host-authoritive mode.</summary>
+    HostOnlyExtension,
+
     /// <summary>A packet was sent at an inappropriate moment.</summary>
     GameFlow,
 
index f888fd79721b05fc9eb2fd6cfc67d6abedde6ead..a649904052c5337684c83c3613bcf7a6f7558454 100644 (file)
@@ -10,6 +10,8 @@ namespace Impostor.Api.Config
 
         public CheatingHostMode AllowCheatingHosts { get; set; } = CheatingHostMode.Never;
 
+        public CheatingHostMode AllowHostOnlyExtensions { get; set; } = CheatingHostMode.IfRequested;
+
         public bool EnableGameFlowChecks { get; set; } = true;
 
         public bool EnableMustBeHostChecks { get; set; } = true;
index a902e77a7e6150c901b58ff8dc09883ced3e055a..4faba36663744b0edbacb3c065ce09bb06532e02 100644 (file)
@@ -1,4 +1,4 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
 using System.Linq;
 using System.Reflection;
 
@@ -41,6 +41,11 @@ namespace Impostor.Api.Net.Messages
                 .ToDictionary(x => (byte)x.GetValue(null)!, y => y.Name);
         }
 
+        /// <summary>
+        /// Convert a MessageFlag to the corresponding string.
+        /// </summary>
+        /// <param name="flag">The MessageFlag to convert.</param>
+        /// <returns>A string corresponding with the value of flag.</returns>
         public static string FlagToString(byte flag)
         {
             return FlagCache.TryGetValue(flag, out var res) ? res : $"Unknown Flag {flag}";
index 5f4572fe497860b616ca87d88f412e4e9855998e..08597c22c39e241fa346c3e71a24d1aaa083a491 100644 (file)
@@ -74,6 +74,12 @@ namespace Impostor.Server.Net
                 CheatCategory.Ownership => _antiCheatConfig.EnableOwnershipChecks,
                 CheatCategory.Role => _antiCheatConfig.EnableRoleChecks,
                 CheatCategory.Target => _antiCheatConfig.EnableTargetChecks,
+                CheatCategory.HostOnlyExtension => _antiCheatConfig.AllowHostOnlyExtensions switch {
+                    CheatingHostMode.Always => false,
+                    CheatingHostMode.IfRequested => !GameVersion.HasDisableServerAuthorityFlag,
+                    CheatingHostMode.Never => true,
+                    _ => true,
+                },
                 CheatCategory.Other => true,
                 _ => LogUnknownCategory(category),
             };
@@ -194,7 +200,7 @@ namespace Impostor.Server.Net
 
                 case MessageFlags.StartGame:
                 {
-                    if (!IsPacketAllowed(reader, true))
+                    if (!IsPacketAllowed(reader, true, flag))
                     {
                         return;
                     }
@@ -209,7 +215,7 @@ namespace Impostor.Server.Net
 
                 case MessageFlags.RemovePlayer:
                 {
-                    if (!IsPacketAllowed(reader, true))
+                    if (!IsPacketAllowed(reader, true, flag))
                     {
                         return;
                     }
@@ -226,7 +232,7 @@ namespace Impostor.Server.Net
                 case MessageFlags.GameData:
                 case MessageFlags.GameDataTo:
                 {
-                    if (!IsPacketAllowed(reader, false))
+                    if (!IsPacketAllowed(reader, false, flag))
                     {
                         return;
                     }
@@ -261,7 +267,17 @@ namespace Impostor.Server.Net
 
                 case MessageFlags.PackedGameDataTo:
                 {
-                    if (!IsPackedGameDataToAllowed(reader))
+                    // We're limiting this to hosts right now. If you have a use case for this for
+                    // players to use this feature, we're open to changing this.
+                    if (!IsPacketAllowed(reader, true, flag))
+                    {
+                        return;
+                    }
+
+                    if (await ReportCheatAsync(
+                        new CheatContext(MessageFlags.FlagToString(flag)),
+                        CheatCategory.HostOnlyExtension,
+                        "Client sent a PackedGameDataTo message"))
                     {
                         return;
                     }
@@ -302,7 +318,7 @@ namespace Impostor.Server.Net
 
                 case MessageFlags.EndGame:
                 {
-                    if (!IsPacketAllowed(reader, true))
+                    if (!IsPacketAllowed(reader, true, flag))
                     {
                         return;
                     }
@@ -317,7 +333,7 @@ namespace Impostor.Server.Net
 
                 case MessageFlags.AlterGame:
                 {
-                    if (!IsPacketAllowed(reader, true))
+                    if (!IsPacketAllowed(reader, true, flag))
                     {
                         return;
                     }
@@ -338,7 +354,7 @@ namespace Impostor.Server.Net
 
                 case MessageFlags.KickPlayer:
                 {
-                    if (!IsPacketAllowed(reader, true))
+                    if (!IsPacketAllowed(reader, true, flag))
                     {
                         return;
                     }
@@ -419,7 +435,7 @@ namespace Impostor.Server.Net
             await _gameManager.OnClientDisconnectAsync(this);
         }
 
-        private bool IsPacketAllowed(IMessageReader message, bool hostOnly)
+        private bool IsPacketAllowed(IMessageReader message, bool hostOnly, byte flag)
         {
             if (Player == null)
             {
@@ -442,36 +458,17 @@ namespace Impostor.Server.Net
                     return true;
                 }
 
-                _logger.LogWarning("[{0}] Client sent packet only allowed by the host ({1}).", Id, game.HostId);
+                _logger.LogWarning(
+                    "[{0}] Client sent packet {1} only allowed by the host ({2}).",
+                    Id,
+                    MessageFlags.FlagToString(flag),
+                    game.HostId);
                 return false;
             }
 
             return true;
         }
 
-        private bool IsPackedGameDataToAllowed(IMessageReader message)
-        {
-            if (Player == null)
-            {
-                return false;
-            }
-
-            var game = Player.Game;
-
-            if (message.ReadPackedInt32() != game.Code)
-            {
-                return false;
-            }
-
-            if (game.HostId == Id)
-            {
-                return true;
-            }
-
-            _logger.LogWarning("[{0}] Client sent PackedGameDataTo only allowed by the host ({1}).", Id, game.HostId);
-            return false;
-        }
-
         /// <summary>
         ///     Triggered when the connected client requests the PlatformSpecificData.
         /// </summary>