Skip to content

Commit

Permalink
fix: Fixed invalid connection challenges being sent due to race
Browse files Browse the repository at this point in the history
  • Loading branch information
TwoTenPvP committed Nov 22, 2019
1 parent a5a9574 commit 735e975
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 11 deletions.
4 changes: 3 additions & 1 deletion Ruffles/Connections/Connection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;


Expand Down Expand Up @@ -326,6 +327,7 @@ internal void Reset()
PreConnectionChallengeTimestamp = 0;
PreConnectionChallengeCounter = 0;
PreConnectionChallengeIV = 0;
PreConnectionChallengeSolved = false;

OutgoingPackets = 0;
OutgoingWirePackets = 0;
Expand Down
38 changes: 28 additions & 10 deletions Ruffles/Core/RuffleSocket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)));
Expand Down Expand Up @@ -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;
Expand All @@ -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<byte>(memory.Buffer, 0, (int)memory.VirtualCount), true, (ushort)memory.VirtualCount);

Expand Down Expand Up @@ -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<byte>(memory.Buffer, 0, (int)memory.VirtualCount), true, (ushort)memory.VirtualCount);

Expand Down Expand Up @@ -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<byte>(memory.Buffer, 0, (int)memory.VirtualCount), true, (ushort)memory.VirtualCount);

Expand Down Expand Up @@ -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<byte>(memory.Buffer, 0, (int)memory.VirtualCount), true, (ushort)memory.VirtualCount);

Expand Down Expand Up @@ -1099,7 +1117,7 @@ internal void HandlePacket(ArraySegment<byte> 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;
}

Expand Down Expand Up @@ -1229,7 +1247,7 @@ internal void HandlePacket(ArraySegment<byte> 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;
Expand Down

0 comments on commit 735e975

Please sign in to comment.