using System.Collections.Immutable; using System.Linq; using System.Net; using Content.Server.IP; using Content.Shared.Database; using Robust.Shared.Network; namespace Content.Server.Database; /// /// Implements logic to match a against a player query. /// /// /// /// This implementation is used by in-game ban matching code, and partially by the SQLite database layer. /// Some logic is duplicated into both the SQLite and PostgreSQL database layers to provide more optimal SQL queries. /// Both should be kept in sync, please! /// /// public static class BanMatcher { /// /// Check whether a ban matches the specified player info. /// /// /// /// This function does not check whether the ban itself is expired or manually unbanned. /// /// /// The ban information. /// Information about the player to match against. /// True if the ban matches the provided player info. public static bool BanMatches(BanDef ban, in PlayerInfo player) { var exemptFlags = player.ExemptFlags; // Any flag to bypass BlacklistedRange bans. if (exemptFlags != ServerBanExemptFlags.None) exemptFlags |= ServerBanExemptFlags.BlacklistedRange; if ((ban.ExemptFlags & exemptFlags) != 0) return false; var playerAddr = player.Address; if (!player.ExemptFlags.HasFlag(ServerBanExemptFlags.IP) && playerAddr != null && ban.Addresses.Any(addr => playerAddr.IsInSubnet(addr)) && (!ban.ExemptFlags.HasFlag(ServerBanExemptFlags.BlacklistedRange) || player.IsNewPlayer)) { return true; } if (player.UserId is { } id && ban.UserIds.Contains(id)) { return true; } foreach (var banHwid in ban.HWIds) { switch (banHwid.Type) { case HwidType.Legacy: if (player.HWId is { Length: > 0 } hwIdVar && hwIdVar.AsSpan().SequenceEqual(banHwid.Hwid.AsSpan())) { return true; } break; case HwidType.Modern: if (player.ModernHWIds is { Length: > 0 } modernHwIdVar) { foreach (var hwid in modernHwIdVar) { if (hwid.AsSpan().SequenceEqual(banHwid.Hwid.AsSpan())) return true; } } break; } } return false; } /// /// A simple struct containing player info used to match bans against. /// public struct PlayerInfo { /// /// The user ID of the player. /// public NetUserId? UserId; /// /// The IP address of the player. /// public IPAddress? Address; /// /// The LEGACY hardware ID of the player. Corresponds with . /// public ImmutableArray? HWId; /// /// The modern hardware IDs of the player. Corresponds with . /// public ImmutableArray>? ModernHWIds; /// /// Exemption flags the player has been granted. /// public ServerBanExemptFlags ExemptFlags; /// /// True if this player is new and is thus eligible for more bans. /// public bool IsNewPlayer; } }