Integrate Modern HWID into content

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.
This commit is contained in:
Pieter-Jan Briers
2024-11-12 01:51:23 +01:00
parent 36aceb178c
commit 4f3db43696
34 changed files with 9059 additions and 241 deletions

View File

@@ -0,0 +1,62 @@
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
namespace Content.Shared.Database;
/// <summary>
/// Represents a raw HWID value together with its type.
/// </summary>
[Serializable]
public sealed class ImmutableTypedHwid(ImmutableArray<byte> hwid, HwidType type)
{
public readonly ImmutableArray<byte> Hwid = hwid;
public readonly HwidType Type = type;
public override string ToString()
{
var b64 = Convert.ToBase64String(Hwid.AsSpan());
return Type == HwidType.Modern ? $"V2-{b64}" : b64;
}
public static bool TryParse(string value, [NotNullWhen(true)] out ImmutableTypedHwid? hwid)
{
var type = HwidType.Legacy;
if (value.StartsWith("V2-", StringComparison.Ordinal))
{
value = value["V2-".Length..];
type = HwidType.Modern;
}
var array = new byte[GetBase64ByteLength(value)];
if (!Convert.TryFromBase64String(value, array, out _))
{
hwid = null;
return false;
}
hwid = new ImmutableTypedHwid([..array], type);
return true;
}
private static int GetBase64ByteLength(string value)
{
// Why is .NET like this man wtf.
return 3 * (value.Length / 4) - value.TakeLast(2).Count(c => c == '=');
}
}
/// <summary>
/// Represents different types of HWIDs as exposed by the engine.
/// </summary>
public enum HwidType
{
/// <summary>
/// The legacy HWID system. Should only be used for checking old existing database bans.
/// </summary>
Legacy = 0,
/// <summary>
/// The modern HWID system.
/// </summary>
Modern = 1,
}