From 2ff60f8399b0443459ce620ca3be709e2aa8bdb3 Mon Sep 17 00:00:00 2001 From: zombieb Date: Mon, 22 Sep 2025 00:24:04 -0400 Subject: [PATCH] OnLogout, Steam platform auth in account creation. Not configurable to ensure server uses ticket to validate. --- Core/Content/CustomRecNet/CustomRecNet.cs | 2 + Core/Init.cs | 4 +- Core/SteamPlatform.cs | 46 +++++++++++++++++++++++ Patches/BestHTTP.cs | 24 +++++++++--- Patches/Internals/OnLogout.cs | 30 +++++++++++++++ Patches/Internals/PlatformManager.cs | 29 ++++++++++++++ Patches/Internals/PostAuthentication.cs | 12 ++---- 7 files changed, 132 insertions(+), 15 deletions(-) create mode 100644 Core/SteamPlatform.cs create mode 100644 Patches/Internals/OnLogout.cs create mode 100644 Patches/Internals/PlatformManager.cs diff --git a/Core/Content/CustomRecNet/CustomRecNet.cs b/Core/Content/CustomRecNet/CustomRecNet.cs index 9065b03..93fdcd3 100644 --- a/Core/Content/CustomRecNet/CustomRecNet.cs +++ b/Core/Content/CustomRecNet/CustomRecNet.cs @@ -16,6 +16,8 @@ public class RecNetInteractions public static List postAuthenticationActions = []; public static List postLocalAccountActions = []; public static List onNotificationsOpen = []; + public static List onLogout = []; + public static List onPlatformInitialize = []; public static Il2CppSystem.Uri CreateServiceUri(Service service, string pathAndQuery) { diff --git a/Core/Init.cs b/Core/Init.cs index 1f3da21..fd21a30 100644 --- a/Core/Init.cs +++ b/Core/Init.cs @@ -43,6 +43,7 @@ public class Initialization UniversalPatchPlugin.Log.LogInfo("PATCH LIST END ========================="); } + // to be removed in a future update try { CacheChangePatchConfigs(); @@ -62,8 +63,9 @@ public class Initialization { UniversalPatchPlugin.Log.LogInfo("Attaching game objects"); - if (ServerPatchesConfig.CustomEmotes.Value) UniversalPatchPlugin.Instance.AddComponent(); + UniversalPatchPlugin.Instance.AddComponent(); UniversalPatchPlugin.Instance.AddComponent(); + if (ServerPatchesConfig.CustomEmotes.Value) UniversalPatchPlugin.Instance.AddComponent(); if (ServerPatchesConfig.CustomKnownDlls.Value) UniversalPatchPlugin.Instance.AddComponent(); if (ServerPatchesConfig.CustomGameConfigurations.Value) UniversalPatchPlugin.Instance.AddComponent(); } diff --git a/Core/SteamPlatform.cs b/Core/SteamPlatform.cs new file mode 100644 index 0000000..ee5db56 --- /dev/null +++ b/Core/SteamPlatform.cs @@ -0,0 +1,46 @@ +using Il2CppInterop.Runtime; +using Steamworks; +using System; +using undead_universal_patch_il2cpp.Core.Content.CustomRecNet; +using UnityEngine; + +namespace undead_universal_patch_il2cpp.Core; + +public class SteamPlatform : MonoBehaviour +{ + public static string AuthTicket { get; set; } = null; + + void GetAuthTicket() { + SteamPlatformManager manager = PlatformManager.Instance.GetComponentInChildren(); + manager.GetAuthSessionTicket().Then( + DelegateSupport.ConvertDelegate>((SteamPlatformManager.AuthSessionTicket ticket) => + { + if (!string.IsNullOrEmpty(ticket.Error)) UniversalPatchPlugin.Log.LogError($"Could not get Steam auth ticket!: {ticket.Error}"); + else + { + AuthTicket = BitConverter.ToString(ticket.Ticket).Replace("-", "").ToUpperInvariant().TrimEnd('0'); + Util.ConditionalDebug($"Got new Steam auth ticket"); + } + })); + } + + void Start() + { + RecNetInteractions.onLogout.Add(GetAuthTicket); + RecNetInteractions.onPlatformInitialize.Add(GetAuthTicket); + + /* + Every time the user logs out of matchmaking + or when PlatformManager initializes, fetch a new ticket. + The user might be logging out to the account selection screen + where they might create a new one; a Steam auth ticket is added to + the auth params in the create request and it must be valid. + + It *is* possible (though very unlikely) that the user creates a new account + before the first ticket is fetched, since the method that gets a ticket is + an IPromise. + + If this way of doing things isn't the best, fix it and I'll merge + */ + } +} \ No newline at end of file diff --git a/Patches/BestHTTP.cs b/Patches/BestHTTP.cs index b39db29..60b90a8 100644 --- a/Patches/BestHTTP.cs +++ b/Patches/BestHTTP.cs @@ -1,9 +1,12 @@ using System; using System.Reflection; +using System.Threading.Tasks; using BestHTTP; +using BestHTTP.Forms; using HarmonyLib; using undead_universal_patch_il2cpp.Core; using undead_universal_patch_il2cpp.Core.Config; +using UnityEngine; namespace undead_universal_patch_il2cpp.Patches { @@ -22,6 +25,8 @@ namespace undead_universal_patch_il2cpp.Patches static readonly MethodInfo getHeaderMethod = requestType?.GetMethod("GetFirstHeaderValue"); static readonly MethodInfo addHeaderMethod = requestType?.GetMethod("AddHeader"); + static readonly MethodInfo getFormFields = requestType?.GetMethod("GetFormFields"); + static readonly PropertyInfo formImplProp = requestType?.GetProperty("FormImpl"); static readonly PropertyInfo methodTypeProp = requestType?.GetProperty("MethodType"); static readonly PropertyInfo uriProp = requestType?.GetProperty("Uri"); static readonly PropertyInfo customCertProp = requestType?.GetProperty("CustomCertificateVerifyer"); @@ -30,13 +35,13 @@ namespace undead_universal_patch_il2cpp.Patches getHeaderMethod, addHeaderMethod, methodTypeProp, + getFormFields, + formImplProp, uriProp, customCertProp ]).Success; - static MethodBase TargetMethod() => patchResult.Method; - [HarmonyPrefix] static void Prefix(ref object request) { if (PatchConfig.CertificatePatch.Value) customCertProp.GetSetMethod().Invoke(request, [null]); @@ -59,6 +64,16 @@ namespace undead_universal_patch_il2cpp.Patches if (newUri.Host.Contains("ns.rec.net")) newUri = new Il2CppSystem.Uri(NameserverConfig.NewUrl.Value); + bool isAccCreate = newUri.PathAndQuery.Contains("account/create"); + if (isAccCreate && SteamPlatform.AuthTicket != null) + { + HTTPFormBase form = (HTTPFormBase)formImplProp.GetValue(request, null); + + form.AddField("x-steam-ticket", SteamPlatform.AuthTicket); + Util.ConditionalDebug("Added Steam ticket to create request"); + } + else if (isAccCreate) UniversalPatchPlugin.Log.LogError("The Steam auth ticket has not yet been fetched, account creation might fail!"); + // Finish request changes string afterUrl = newUri.ToString(); @@ -71,9 +86,8 @@ namespace undead_universal_patch_il2cpp.Patches $" URL After : {(beforeUrl == afterUrl ? "(unmodified)" : afterUrl)}\n" + $" Method : {method}\n" + $" Content-Type : {contentType ?? "(not set)"}"); - else UniversalPatchPlugin.Log.LogInfo("BestHTTPProxy Request Log\n" + - $" Before : {beforeUrl}\n" + - $" After : {afterUrl}"); + else UniversalPatchPlugin.Log.LogInfo("BestHTTPProxy Request\n" + + $" {method} {afterUrl}"); } } } diff --git a/Patches/Internals/OnLogout.cs b/Patches/Internals/OnLogout.cs new file mode 100644 index 0000000..6d61ffc --- /dev/null +++ b/Patches/Internals/OnLogout.cs @@ -0,0 +1,30 @@ +using HarmonyLib; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using undead_universal_patch_il2cpp.Core; +using undead_universal_patch_il2cpp.Core.Content.CustomRecNet; + +namespace undead_universal_patch_il2cpp.Patches.Internals; + +[HarmonyPatch] +public static class LogoutEvent +{ + static PatchTypesResult typesResult = Util.PreparePatchTypes( + "RecNet logout event patch", + "RecNet.Login", + "OnLogout" + ); + + static MethodBase TargetMethod() => typesResult.Method; + static bool Prepare() => typesResult.Success; + + static void Postfix() + { + Util.ConditionalDebug("Running onLogout actions"); + foreach (var action in RecNetInteractions.onLogout) action(); + } +} \ No newline at end of file diff --git a/Patches/Internals/PlatformManager.cs b/Patches/Internals/PlatformManager.cs new file mode 100644 index 0000000..4115a02 --- /dev/null +++ b/Patches/Internals/PlatformManager.cs @@ -0,0 +1,29 @@ +using HarmonyLib; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using undead_universal_patch_il2cpp.Core; +using undead_universal_patch_il2cpp.Core.Content.CustomRecNet; + +namespace undead_universal_patch_il2cpp.Patches.Internals; + +[HarmonyPatch] +public class SteamPlatformManagerEvent +{ + static PatchTypesResult typesResult = Util.PreparePatchTypes( + "On SteamPlatformManager.Initialize", + "SteamPlatformManager", + "Initialize" + ); + + static MethodBase TargetMethod() => typesResult.Method; + static bool Prepare() => typesResult.Success; + + static void Postfix() + { + UniversalPatchPlugin.Log.LogInfo("Running post-steam platform initialize actions"); + foreach (var action in RecNetInteractions.onPlatformInitialize) action(); + } +} \ No newline at end of file diff --git a/Patches/Internals/PostAuthentication.cs b/Patches/Internals/PostAuthentication.cs index 574a1b1..b050c2e 100644 --- a/Patches/Internals/PostAuthentication.cs +++ b/Patches/Internals/PostAuthentication.cs @@ -22,19 +22,13 @@ public class AuthenticationEventPatch static MethodBase TargetMethod() => patchResult.Method; - private static bool RanPostActions { get; set; } = false; static void Postfix(ref string accessToken) { UniversalPatchPlugin.Log.LogInfo("Intercepted AccessToken"); RecNetInteractions.AccessToken = accessToken; - if (!RanPostActions) - { - bool value = (bool)hasAccessTokenProperty.GetValue(patchResult.Type); - if (value) UniversalPatchPlugin.Log.LogInfo("Running post-authentication actions"); - foreach (var action in RecNetInteractions.postAuthenticationActions) - action(); - } - else RanPostActions = true; + UniversalPatchPlugin.Log.LogInfo("Running post-authentication actions"); + foreach (var action in RecNetInteractions.postAuthenticationActions) + action(); } } \ No newline at end of file