From 735e9751e8db9a460b177c04f2494dd50ebb54c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albin=20Cor=C3=A9n?= Date: Fri, 22 Nov 2019 15:09:33 +0100 Subject: [PATCH] fix: Fixed invalid connection challenges being sent due to race --- Ruffles/Connections/Connection.cs | 4 +++- Ruffles/Core/RuffleSocket.cs | 38 +++++++++++++++++++++++-------- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/Ruffles/Connections/Connection.cs b/Ruffles/Connections/Connection.cs index 571be67..90e1add 100644 --- a/Ruffles/Connections/Connection.cs +++ b/Ruffles/Connections/Connection.cs @@ -202,7 +202,8 @@ internal set // Pre connection challenge values internal ulong PreConnectionChallengeTimestamp; - internal ulong PreConnectionChallengeCounter; + internal ulong PreConnectionChallengeCounter; + internal bool PreConnectionChallengeSolved; internal ulong PreConnectionChallengeIV; @@ -326,6 +327,7 @@ internal void Reset() PreConnectionChallengeTimestamp = 0; PreConnectionChallengeCounter = 0; PreConnectionChallengeIV = 0; + PreConnectionChallengeSolved = false; OutgoingPackets = 0; OutgoingWirePackets = 0; diff --git a/Ruffles/Core/RuffleSocket.cs b/Ruffles/Core/RuffleSocket.cs index c3df4e5..e62324f 100644 --- a/Ruffles/Core/RuffleSocket.cs +++ b/Ruffles/Core/RuffleSocket.cs @@ -452,13 +452,16 @@ public Connection Connect(EndPoint endpoint) } while ((hash << (sizeof(ulong) * 8 - config.ChallengeDifficulty)) >> (sizeof(ulong) * 8 - config.ChallengeDifficulty) != 0); - if (Logging.CurrentLogLevel <= LogLevel.Debug) Logging.LogInfo("Found hash collision after " + counter + " attempts"); + if (Logging.CurrentLogLevel <= LogLevel.Debug) Logging.LogInfo("Found hash collision after " + counter + " attempts. [Counter=" + (counter - 1) + "] [IV=" + iv + "] [Time=" + unixTimestamp + "] [Hash=" + hash + "]"); // Make counter 1 less counter--; // Save for resends - connection.PreConnectionChallengeCounter = counter; + connection.PreConnectionChallengeCounter = counter; + + // Mark it as solved (for resending) + connection.PreConnectionChallengeSolved = true; // Write counter for (byte i = 0; i < sizeof(ulong); i++) memory.Buffer[1 + sizeof(ulong) + i] = ((byte)(counter >> (i * 8))); @@ -645,7 +648,7 @@ private void CheckConnectionResends() { if (connections[i].State == ConnectionState.RequestingConnection) { - if ((DateTime.Now - connections[i].HandshakeLastSendTime).TotalMilliseconds > config.ConnectionRequestMinResendDelay && connections[i].HandshakeResendAttempts < config.MaxConnectionRequestResends) + if ((!config.TimeBasedConnectionChallenge || connections[i].PreConnectionChallengeSolved) && (DateTime.Now - connections[i].HandshakeLastSendTime).TotalMilliseconds > config.ConnectionRequestMinResendDelay && connections[i].HandshakeResendAttempts < config.MaxConnectionRequestResends) { connections[i].HandshakeResendAttempts++; connections[i].HandshakeLastSendTime = DateTime.Now; @@ -672,9 +675,15 @@ private void CheckConnectionResends() // Write IV for (byte x = 0; x < sizeof(ulong); x++) memory.Buffer[1 + (sizeof(ulong) * 2) + x] = ((byte)(connections[i].PreConnectionChallengeIV >> (x * 8))); - } - + // Print debug + if (Logging.CurrentLogLevel <= LogLevel.Debug) Logging.LogInfo("Resending ConnectionRequest with challenge [Counter=" + connections[i].PreConnectionChallengeCounter + "] [IV=" + connections[i].PreConnectionChallengeIV + "] [Time=" + connections[i].PreConnectionChallengeTimestamp + "] [Hash=" + HashProvider.GetStableHash64(connections[i].PreConnectionChallengeTimestamp, connections[i].PreConnectionChallengeCounter, connections[i].PreConnectionChallengeIV) + "]"); + } + else + { + // Print debug + if (Logging.CurrentLogLevel <= LogLevel.Debug) Logging.LogInfo("Resending ConnectionRequest"); + } connections[i].SendRaw(new ArraySegment(memory.Buffer, 0, (int)memory.VirtualCount), true, (ushort)memory.VirtualCount); @@ -703,7 +712,10 @@ private void CheckConnectionResends() // Write the connection difficulty memory.Buffer[1 + sizeof(ulong)] = connections[i].ChallengeDifficulty; - + + // Print debug + if (Logging.CurrentLogLevel <= LogLevel.Debug) Logging.LogInfo("Resending ChallengeRequest"); + // Send the challenge connections[i].SendRaw(new ArraySegment(memory.Buffer, 0, (int)memory.VirtualCount), true, (ushort)memory.VirtualCount); @@ -732,7 +744,10 @@ private void CheckConnectionResends() // Write the challenge response for (byte x = 0; x < sizeof(ulong); x++) memory.Buffer[1 + x] = ((byte)(connections[i].ChallengeAnswer >> (x * 8))); - + + // Print debug + if (Logging.CurrentLogLevel <= LogLevel.Debug) Logging.LogInfo("Resending ChallengeResponse"); + // Send the challenge response connections[i].SendRaw(new ArraySegment(memory.Buffer, 0, (int)memory.VirtualCount), true, (ushort)memory.VirtualCount); @@ -763,7 +778,10 @@ private void CheckConnectionResends() for (byte x = 0; x < (byte)config.ChannelTypes.Length; x++) { memory.Buffer[2 + x] = (byte)config.ChannelTypes[x]; - } + } + + // Print debug + if (Logging.CurrentLogLevel <= LogLevel.Debug) Logging.LogInfo("Resending Hail"); connections[i].SendRaw(new ArraySegment(memory.Buffer, 0, (int)memory.VirtualCount), true, (ushort)memory.VirtualCount); @@ -1099,7 +1117,7 @@ internal void HandlePacket(ArraySegment payload, EndPoint endpoint, bool w if (!isCollided) { // They failed the challenge - if (Logging.CurrentLogLevel <= LogLevel.Info) Logging.LogWarning("Client " + endpoint + " failed the connection request. They submitted an invalid answer"); + if (Logging.CurrentLogLevel <= LogLevel.Info) Logging.LogWarning("Client " + endpoint + " failed the connection request. They submitted an invalid answer. [ClaimedHash=" + claimedHash + "] [Counter=" + counter + "] [IV=" + userIv + "] [Time=" + challengeUnixTime + "]"); return; } @@ -1229,7 +1247,7 @@ internal void HandlePacket(ArraySegment payload, EndPoint endpoint, bool w // Release memory memoryManager.DeAlloc(memory); - if (Logging.CurrentLogLevel <= LogLevel.Debug) Logging.LogInfo("Server " + endpoint + " challenge of difficulty " + connection.ChallengeDifficulty + " was solved. Answer was sent"); + if (Logging.CurrentLogLevel <= LogLevel.Debug) Logging.LogInfo("Server " + endpoint + " challenge of difficulty " + connection.ChallengeDifficulty + " was solved. Answer was sent. [CollidedValue=" + collidedValue + "]"); } } break;