This should be the primary changes for the future-proof "Modern HWID" system implemented into Robust and the auth server. HWIDs in the database have been given an additional column representing their version, legacy or modern. This is implemented via an EF Core owned entity. By manually setting the column name of the main value column, we can keep DB compatibility and the migration is just adding some type columns. This new HWID type has to be plumbed through everywhere, resulting in some breaking changes for the DB layer and such. New bans and player records are placed with the new modern HWID. Old bans are still checked against legacy HWIDs. Modern HWIDs are presented with a "V2-" prefix to admins, to allow distinguishing them. This is also integrated into the parsing logic for placing new bans. There's also some code cleanup to reduce copy pasting around the place from my changes. Requires latest engine to support ImmutableArray<byte> in NetSerializer.
116 lines
3.7 KiB
C#
116 lines
3.7 KiB
C#
using System.Collections.Immutable;
|
|
using System.Net;
|
|
using Content.Server.IP;
|
|
using Content.Shared.Database;
|
|
using Robust.Shared.Network;
|
|
|
|
namespace Content.Server.Database;
|
|
|
|
/// <summary>
|
|
/// Implements logic to match a <see cref="ServerBanDef"/> against a player query.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// 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!
|
|
/// </para>
|
|
/// </remarks>
|
|
public static class BanMatcher
|
|
{
|
|
/// <summary>
|
|
/// Check whether a ban matches the specified player info.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// This function does not check whether the ban itself is expired or manually unbanned.
|
|
/// </para>
|
|
/// </remarks>
|
|
/// <param name="ban">The ban information.</param>
|
|
/// <param name="player">Information about the player to match against.</param>
|
|
/// <returns>True if the ban matches the provided player info.</returns>
|
|
public static bool BanMatches(ServerBanDef 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;
|
|
|
|
if (!player.ExemptFlags.HasFlag(ServerBanExemptFlags.IP)
|
|
&& player.Address != null
|
|
&& ban.Address is not null
|
|
&& player.Address.IsInSubnet(ban.Address.Value)
|
|
&& (!ban.ExemptFlags.HasFlag(ServerBanExemptFlags.BlacklistedRange) || player.IsNewPlayer))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (player.UserId is { } id && ban.UserId == id.UserId)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
switch (ban.HWId?.Type)
|
|
{
|
|
case HwidType.Legacy:
|
|
if (player.HWId is { Length: > 0 } hwIdVar
|
|
&& hwIdVar.AsSpan().SequenceEqual(ban.HWId.Hwid.AsSpan()))
|
|
{
|
|
return true;
|
|
}
|
|
break;
|
|
case HwidType.Modern:
|
|
if (player.ModernHWIds is { Length: > 0 } modernHwIdVar)
|
|
{
|
|
foreach (var hwid in modernHwIdVar)
|
|
{
|
|
if (hwid.AsSpan().SequenceEqual(ban.HWId.Hwid.AsSpan()))
|
|
return true;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// A simple struct containing player info used to match bans against.
|
|
/// </summary>
|
|
public struct PlayerInfo
|
|
{
|
|
/// <summary>
|
|
/// The user ID of the player.
|
|
/// </summary>
|
|
public NetUserId? UserId;
|
|
|
|
/// <summary>
|
|
/// The IP address of the player.
|
|
/// </summary>
|
|
public IPAddress? Address;
|
|
|
|
/// <summary>
|
|
/// The LEGACY hardware ID of the player. Corresponds with <see cref="NetUserData.HWId"/>.
|
|
/// </summary>
|
|
public ImmutableArray<byte>? HWId;
|
|
|
|
/// <summary>
|
|
/// The modern hardware IDs of the player. Corresponds with <see cref="NetUserData.ModernHWIds"/>.
|
|
/// </summary>
|
|
public ImmutableArray<ImmutableArray<byte>>? ModernHWIds;
|
|
|
|
/// <summary>
|
|
/// Exemption flags the player has been granted.
|
|
/// </summary>
|
|
public ServerBanExemptFlags ExemptFlags;
|
|
|
|
/// <summary>
|
|
/// True if this player is new and is thus eligible for more bans.
|
|
/// </summary>
|
|
public bool IsNewPlayer;
|
|
}
|
|
}
|