Skip to content

Commit

Permalink
Address ClientUUID issue as per GHSA-hvm9-wc8j-mgrc
Browse files Browse the repository at this point in the history
With credits to original contributors and TShock team, see advisory for more details.
  • Loading branch information
SignatureBeef committed Dec 19, 2024
1 parent a74e49f commit 24d30d3
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 139 deletions.
136 changes: 0 additions & 136 deletions OTAPI.Scripts/Mods/PatchClientUUID.Server.cs

This file was deleted.

116 changes: 113 additions & 3 deletions OTAPI.Scripts/Patches/Terraria.RemoteClient.Server.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,65 @@ You should have received a copy of the GNU General Public License
#pragma warning disable CS0108 // Member hides inherited member; missing new keyword
#pragma warning disable CS0626 // Method, operator, or accessor is marked external and has no attributes on it

using ModFramework;
using Mono.Cecil.Cil;
using MonoMod;
using System;
using System.Collections.Generic;

/// <summary>
/// @doc Adds additional properties to Terraria.RemoteClient.
/// </summary>
[MonoModIgnore]
partial class Patch
{
[Modification(ModType.PostPatch, "Patching in Client UUID")]
public static void PatchClientUUID(MonoModder modder)
{
const int PacketID = 68;
int messageType = 0;
var GetData = modder.GetILCursor(() => new Terraria.MessageBuffer().GetData(0, 0, out messageType));
var Callback = modder.GetMethodDefinition(() => OTAPI.Hooks.MessageBuffer.InvokeClientUUIDReceived(default, default, default, default, ref messageType));

GetData.GotoNext(i => i.OpCode == OpCodes.Switch);

var instructions = (Instruction[])GetData.Next.Operand;

var packet = instructions[PacketID - 1];

GetData.Goto(packet);

/*
* Replace the ReadString call with the callback. Reference il:
// reader.ReadString();
IL_655e: ldarg.0 == GetData.Next
IL_655f: ldfld class [mscorlib]System.IO.BinaryReader Terraria.MessageBuffer::reader
IL_6564: callvirt instance string [mscorlib]System.IO.BinaryReader::ReadString()
IL_6569: pop
IL_656a: ret
*/

GetData.Index++;
GetData.Emit(OpCodes.Ldarg_0);

GetData.Index++;

foreach (var parameter in GetData.Method.Parameters)
{
GetData.Emit(OpCodes.Ldarg, parameter);
}

System.Diagnostics.Debug.Assert(GetData.Next.OpCode == OpCodes.Callvirt);
GetData.Next.OpCode = OpCodes.Call;
GetData.Next.Operand = Callback;

GetData.Index++;
System.Diagnostics.Debug.Assert(GetData.Next.OpCode == OpCodes.Pop);
GetData.Next.OpCode = OpCodes.Nop;
}
}

/// <summary>
/// @doc Adds a Terraria.RemoteClient.Data variable for data storage.
/// </summary>
Expand All @@ -29,6 +86,7 @@ namespace Terraria
partial class patch_RemoteClient : Terraria.RemoteClient
{
public Dictionary<string, object> Data { get; set; }
public string ClientUUID { get; set; }

[MonoMod.MonoModConstructor]
patch_RemoteClient()
Expand All @@ -39,8 +97,60 @@ partial class patch_RemoteClient : Terraria.RemoteClient
public extern void orig_Reset();
public void Reset()
{
orig_Reset();
Data.Clear();
// clear before possible socket exceptions
Data.Clear();
ClientUUID = null;
orig_Reset();
}
}
}

namespace OTAPI
{
public static partial class Hooks
{
public static partial class MessageBuffer
{
public class ClientUUIDReceivedEventArgs : EventArgs
{
public HookEvent Event { get; set; }
public HookResult? Result { get; set; }

public Terraria.MessageBuffer Instance { get; set; }
public System.IO.BinaryReader Reader { get; set; }
public int Start { get; set; }
public int Length { get; set; }
public int MessageType { get; set; }
public string ClientUUID { get; set; }
}
public static event EventHandler<ClientUUIDReceivedEventArgs> ClientUUIDReceived;

/// <summary>
/// Called when Terraria receives a ClientUUID(#68) packet from a connection
/// </summary>
public static void InvokeClientUUIDReceived(Terraria.MessageBuffer instance, System.IO.BinaryReader reader, int start, int length, ref int messageType)
{
var args = new ClientUUIDReceivedEventArgs()
{
Event = HookEvent.Before,
Instance = instance,
Reader = reader,
Start = start,
Length = length,
MessageType = messageType
};

ClientUUIDReceived?.Invoke(null, args);
if (args.Result != HookResult.Cancel)
{
args.ClientUUID = reader.ReadString();

((Terraria.patch_RemoteClient)Terraria.Netplay.Clients[args.Instance.whoAmI]).ClientUUID = args.ClientUUID;

args.Event = HookEvent.After;
ClientUUIDReceived?.Invoke(null, args);
}
}
}
}
}
}

0 comments on commit 24d30d3

Please # to comment.