Core/Auth: Refactor client auth key storage to support more future client variants and preserve more information about client version

Port From (https://github.com/TrinityCore/TrinityCore/commit/8e1595265925e0840d07e943b8c9ff1e906d4719)
This commit is contained in:
Hondacrx
2024-10-09 14:28:10 -04:00
parent 71cc76d6b6
commit 37d48ec371
16 changed files with 213 additions and 63 deletions
@@ -24,6 +24,11 @@ namespace Framework.Database
return WithChainingCallback((queryCallback, result) => callback(obj, result));
}
public QueryCallback WithCallback<T, U>(Action<T, U, SQLResult> callback, T obj, U obj2)
{
return WithChainingCallback((queryCallback, result) => callback(obj, obj2, result));
}
public QueryCallback WithChainingCallback(Action<QueryCallback, SQLResult> callback)
{
_callbacks.Enqueue(new QueryCallbackData(callback));
@@ -0,0 +1,79 @@
// Copyright (c) CypherCore <http://github.com/CypherCore> All rights reserved.
// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
namespace Framework.ClientBuild
{
struct ClientBuildPlatformType
{
public static int Windows = "Win".fourcc();
public static int macOS = "Mac".fourcc();
}
struct ClientBuildArch
{
public static int x86 = "x86".fourcc();
public static int x64 = "x64".fourcc();
public static int Arm32 = "A32".fourcc();
public static int Arm64 = "A64".fourcc();
public static int WA32 = "WA32".fourcc();
}
struct ClientBuildType
{
public static int Retail = "WoW".fourcc();
public static int RetailChina = "WoWC".fourcc();
public static int Beta = "WoWB".fourcc();
public static int BetaRelease = "WoWE".fourcc();
public static int Ptr = "WoWT".fourcc();
public static int PtrRelease = "WoWR".fourcc();
}
public class ClientBuildHelper
{
public static bool IsValid(string platform)
{
switch (platform)
{
case "Win":
case "Wn64":
case "WinA":
case "Mac":
case "Mc64":
case "MacA":
return true;
default:
break;
}
return false;
}
}
public class ClientBuildVariantId
{
public int Platform;
public int Arch;
public int Type;
}
public class ClientBuildAuthKey
{
public static int Size = 16;
public ClientBuildVariantId Variant;
public byte[] Key = new byte[Size];
}
public class ClientBuildInfo
{
public uint Build;
public uint MajorVersion;
public uint MinorVersion;
public uint BugfixVersion;
public char[] HotfixVersion = new char[4];
public List<ClientBuildAuthKey> AuthKeys = new();
}
}
+1 -1
View File
@@ -6,7 +6,7 @@ using System;
namespace Framework.Realm
{
public struct RealmId : IEquatable<RealmId>
{
{
public uint Index { get; set; }
public byte Region { get; set; }
public byte Site { get; set; }
+40 -27
View File
@@ -1,6 +1,7 @@
// Copyright (c) CypherCore <http://github.com/CypherCore> All rights reserved.
// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information.
using Framework.ClientBuild;
using Framework.Constants;
using Framework.Database;
using Framework.IO;
@@ -36,13 +37,15 @@ public class RealmManager : Singleton<RealmManager>
void LoadBuildInfo()
{
_builds.Clear();
// 0 1 2 3 4 5 6 7
SQLResult result = DB.Login.Query("SELECT majorVersion, minorVersion, bugfixVersion, hotfixVersion, build, win64AuthSeed, mac64AuthSeed, macArmAuthSeed FROM build_info ORDER BY build ASC");
if (!result.IsEmpty())
{
do
{
RealmBuildInfo build = new();
ClientBuildInfo build = new();
build.MajorVersion = result.Read<uint>(0);
build.MinorVersion = result.Read<uint>(1);
build.BugfixVersion = result.Read<uint>(2);
@@ -51,17 +54,33 @@ public class RealmManager : Singleton<RealmManager>
build.HotfixVersion = hotfixVersion.ToCharArray();
build.Build = result.Read<uint>(4);
string win64AuthSeedHexStr = result.Read<string>(5);
if (!win64AuthSeedHexStr.IsEmpty() && win64AuthSeedHexStr.Length == build.Win64AuthSeed.Length * 2)
build.Win64AuthSeed = win64AuthSeedHexStr.ToByteArray();
if (win64AuthSeedHexStr.Length == ClientBuildAuthKey.Size * 2)
{
ClientBuildAuthKey buildKey = new();
buildKey.Variant = new() { Platform = ClientBuildPlatformType.Windows, Arch = ClientBuildArch.x64, Type = ClientBuildType.Retail };
buildKey.Key = win64AuthSeedHexStr.ToByteArray();
build.AuthKeys.Add(buildKey);
}
string mac64AuthSeedHexStr = result.Read<string>(6);
if (!mac64AuthSeedHexStr.IsEmpty() && mac64AuthSeedHexStr.Length == build.Mac64AuthSeed.Length * 2)
build.Mac64AuthSeed = mac64AuthSeedHexStr.ToByteArray();
if (mac64AuthSeedHexStr.Length == ClientBuildAuthKey.Size * 2)
{
ClientBuildAuthKey buildKey = new();
buildKey.Variant = new() { Platform = ClientBuildPlatformType.macOS, Arch = ClientBuildArch.x64, Type = ClientBuildType.Retail };
buildKey.Key = mac64AuthSeedHexStr.ToByteArray();
build.AuthKeys.Add(buildKey);
}
string macArmAuthSeedHexStr = result.Read<string>(7);
if (macArmAuthSeedHexStr.IsEmpty() && mac64AuthSeedHexStr.Length == build.MacArmAuthSeed.Length * 2)
build.MacArmAuthSeed = macArmAuthSeedHexStr.ToByteArray();
if (macArmAuthSeedHexStr.Length == ClientBuildAuthKey.Size * 2)
{
ClientBuildAuthKey buildKey = new();
buildKey.Variant = new() { Platform = ClientBuildPlatformType.macOS, Arch = ClientBuildArch.Arm64, Type = ClientBuildType.Retail };
buildKey.Key = macArmAuthSeedHexStr.ToByteArray();
build.AuthKeys.Add(buildKey);
}
_builds.Add(build);
@@ -199,7 +218,7 @@ public class RealmManager : Singleton<RealmManager>
}
}
public RealmBuildInfo GetBuildInfo(uint build)
public ClientBuildInfo GetBuildInfo(uint build)
{
foreach (var clientBuild in _builds)
if (clientBuild.Build == build)
@@ -210,7 +229,7 @@ public class RealmManager : Singleton<RealmManager>
public uint GetMinorMajorBugfixVersionForBuild(uint build)
{
RealmBuildInfo buildInfo = _builds.FirstOrDefault(p => p.Build < build);
ClientBuildInfo buildInfo = _builds.FirstOrDefault(p => p.Build < build);
return buildInfo != null ? (buildInfo.MajorVersion * 10000 + buildInfo.MinorVersion * 100 + buildInfo.BugfixVersion) : 0;
}
@@ -226,7 +245,7 @@ public class RealmManager : Singleton<RealmManager>
realmEntry.CfgCategoriesID = realm.Timezone;
ClientVersion version = new();
RealmBuildInfo buildInfo = GetBuildInfo(realm.Build);
ClientBuildInfo buildInfo = GetBuildInfo(realm.Build);
if (buildInfo != null)
{
version.Major = (int)buildInfo.MajorVersion;
@@ -302,7 +321,7 @@ public class RealmManager : Singleton<RealmManager>
return BitConverter.GetBytes(jsonData.Length).Combine(ZLib.Compress(jsonData));
}
public BattlenetRpcErrorCode JoinRealm(uint realmAddress, uint build, IPAddress clientAddress, byte[] clientSecret, Locale locale, string os, TimeSpan timezoneOffset, string accountName, AccountTypes accountSecurityLevel, Bgs.Protocol.GameUtilities.V1.ClientResponse response)
public BattlenetRpcErrorCode JoinRealm(uint realmAddress, uint build, ClientBuildVariantId buildVariant, IPAddress clientAddress, byte[] clientSecret, Locale locale, string os, TimeSpan timezoneOffset, string accountName, AccountTypes accountSecurityLevel, Bgs.Protocol.GameUtilities.V1.ClientResponse response)
{
Realm realm = GetRealm(new RealmId(realmAddress));
if (realm != null)
@@ -336,10 +355,16 @@ public class RealmManager : Singleton<RealmManager>
stmt.AddValue(6, accountName);
DB.Login.DirectExecute(stmt);
RealmJoinTicket joinTicket = new();
joinTicket.GameAccount = accountName;
joinTicket.Platform = buildVariant.Platform;
joinTicket.ClientArch = buildVariant.Arch;
joinTicket.Type = buildVariant.Type;
Bgs.Protocol.Attribute attribute = new();
attribute.Name = "Param_RealmJoinTicket";
attribute.Value = new Bgs.Protocol.Variant();
attribute.Value.BlobValue = Google.Protobuf.ByteString.CopyFrom(accountName, Encoding.UTF8);
attribute.Value.BlobValue = Google.Protobuf.ByteString.CopyFromUtf8(JsonSerializer.Serialize(joinTicket));
response.Attribute.Add(attribute);
attribute = new Bgs.Protocol.Attribute();
@@ -369,7 +394,7 @@ public class RealmManager : Singleton<RealmManager>
RealmPopulationState ConvertLegacyPopulationState(LegacyRealmFlags legacyRealmFlags, float population)
{
if (legacyRealmFlags .HasAnyFlag(LegacyRealmFlags.Offline))
if (legacyRealmFlags.HasAnyFlag(LegacyRealmFlags.Offline))
return RealmPopulationState.Offline;
if (legacyRealmFlags.HasAnyFlag(LegacyRealmFlags.Recommended))
return RealmPopulationState.Recommended;
@@ -387,22 +412,10 @@ public class RealmManager : Singleton<RealmManager>
public ICollection<Realm> GetRealms() { return _realms.Values; }
List<string> GetSubRegions() { return _subRegions; }
List<RealmBuildInfo> _builds = new();
List<ClientBuildInfo> _builds = new();
ConcurrentDictionary<RealmId, Realm> _realms = new();
Dictionary<RealmId, string> _removedRealms = new();
List<string> _subRegions = new();
Timer _updateTimer;
RealmId? _currentRealmId;
}
public class RealmBuildInfo
{
public uint Build;
public uint MajorVersion;
public uint MinorVersion;
public uint BugfixVersion;
public char[] HotfixVersion = new char[4];
public byte[] Win64AuthSeed = new byte[16];
public byte[] Mac64AuthSeed = new byte[16];
public byte[] MacArmAuthSeed = new byte[16];
}
}
+15
View File
@@ -438,6 +438,21 @@ namespace System
}
return hash;
}
public static int fourcc(this string str)
{
//if (length > sizeof(uint))
// throw "Text can only be max 4 characters long";
int intValue = 0;
foreach (char c in str.ToCharArray())
{
intValue <<= 8;
intValue |= c;
}
return intValue;
}
#endregion
#region BinaryReader
@@ -1,9 +1,9 @@
// Copyright (c) CypherCore <http://github.com/CypherCore> All rights reserved.
// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information.
using Framework.Web.Rest.Realmlist;
using System.Collections.Generic;
using System.Text.Json.Serialization;
using Framework.Web.Rest.Realmlist;
namespace Framework.Web
{
@@ -0,0 +1,22 @@
// Copyright (c) CypherCore <http://github.com/CypherCore> All rights reserved.
// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information.
using System.Text.Json.Serialization;
namespace Framework.Web
{
public class RealmJoinTicket
{
[JsonPropertyName("gameAccount")]
public string GameAccount { get; set; }
[JsonPropertyName("platform")]
public int Platform { get; set; }
[JsonPropertyName("type")]
public int Type { get; set; }
[JsonPropertyName("clientArch")]
public int ClientArch { get; set; }
}
}
@@ -2,9 +2,8 @@
// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information.
using System.Text.Json.Serialization;
using Framework.Web.Rest.Realmlist;
namespace Framework.Web.Rest.Realmlist
namespace Framework.Web
{
internal class RealmListRAFInfo
{
@@ -1,9 +1,9 @@
// Copyright (c) CypherCore <http://github.com/CypherCore> All rights reserved.
// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information.
using Framework.Web.Rest.Realmlist;
using System.Collections.Generic;
using System.Text.Json.Serialization;
using Framework.Web.Rest.Realmlist;
namespace Framework.Web
{