fix(network): reject repeats of the do-once handshake packets
Seeding and picking a server each happen once per connection. Neither had a guard, so a client pipelining into the recv buffer could re-run the handshake before the queued disconnect drained and reach both handlers again. A second play-server is the one that mattered: this connection may already have spent its auth id on a game login, and the id it would be handed back is the spent one, which nothing will redeem. Rejecting the packet is the honest answer -- the client is out of protocol order, not unlucky. Account login and game login already guarded on SentFirstPacket. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
fd4d7e82a6
commit
d337cf4a1e
1 changed files with 17 additions and 1 deletions
|
|
@ -504,6 +504,14 @@ public static class IncomingAccountPackets
|
|||
|
||||
public static void PlayServer(NetState state, SpanReader reader)
|
||||
{
|
||||
// A server is picked once per connection. Picking again would hand back an id this
|
||||
// connection may already have spent on a game login, so the client could never redeem it.
|
||||
if (state.AuthId != 0)
|
||||
{
|
||||
state.Disconnect("Duplicate play server packet sent.");
|
||||
return;
|
||||
}
|
||||
|
||||
int index = reader.ReadInt16();
|
||||
var info = state.ServerInfo;
|
||||
var a = state.Account;
|
||||
|
|
@ -516,7 +524,7 @@ public static class IncomingAccountPackets
|
|||
{
|
||||
var si = info[index];
|
||||
|
||||
state.AuthId = GenerateAuthID(state);
|
||||
state.AuthId = state.GenerateAuthID();
|
||||
|
||||
state.SentFirstPacket = false;
|
||||
state.SendPlayServerAck(si, state.AuthId);
|
||||
|
|
@ -525,6 +533,14 @@ public static class IncomingAccountPackets
|
|||
|
||||
public static void LoginServerSeed(NetState state, SpanReader reader)
|
||||
{
|
||||
// Seeding happens once per connection. A second one means the client is restarting a
|
||||
// handshake it already completed, which no real client does.
|
||||
if (state.Seeded)
|
||||
{
|
||||
state.Disconnect("Duplicate login server seed packet sent.");
|
||||
return;
|
||||
}
|
||||
|
||||
state.Seed = reader.ReadInt32();
|
||||
state.Seeded = true;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue