1
0

ProtoProxy now properly waits for both sides to establish encryption

No more "End of stream" kicks in the client. Data sent while one connection is encrypted and the other is not is buffered and sent when the other link establishes encryption.
This commit is contained in:
madmaxoft 2013-07-28 18:15:19 +02:00
parent 8c61c54dae
commit 00196e975a
2 changed files with 54 additions and 15 deletions

View File

@ -49,13 +49,25 @@
{ \ { \
AString ToServer; \ AString ToServer; \
m_ClientBuffer.ReadAgain(ToServer); \ m_ClientBuffer.ReadAgain(ToServer); \
if (m_ServerState == csUnencrypted) \ switch (m_ServerState) \
{ \ { \
SERVERSEND(ToServer.data(), ToServer.size()); \ case csUnencrypted: \
} \ { \
else \ SERVERSEND(ToServer.data(), ToServer.size()); \
{ \ break; \
SERVERENCRYPTSEND(ToServer.data(), ToServer.size()); \ } \
case csEncryptedUnderstood: \
case csEncryptedUnknown: \
{ \
SERVERENCRYPTSEND(ToServer.data(), ToServer.size()); \
break; \
} \
case csWaitingForEncryption: \
{ \
Log("Waiting for server encryption, queued %u bytes", ToServer.size()); \
m_ServerEncryptionBuffer.append(ToServer.data(), ToServer.size()); \
break; \
} \
} \ } \
DebugSleep(50); \ DebugSleep(50); \
} }
@ -64,13 +76,25 @@
{ \ { \
AString ToClient; \ AString ToClient; \
m_ServerBuffer.ReadAgain(ToClient); \ m_ServerBuffer.ReadAgain(ToClient); \
if (m_ClientState == csUnencrypted) \ switch (m_ClientState) \
{ \ { \
CLIENTSEND(ToClient.data(), ToClient.size()); \ case csUnencrypted: \
} \ { \
else \ CLIENTSEND(ToClient.data(), ToClient.size()); \
{ \ break; \
CLIENTENCRYPTSEND(ToClient.data(), ToClient.size()); \ } \
case csEncryptedUnderstood: \
case csEncryptedUnknown: \
{ \
CLIENTENCRYPTSEND(ToClient.data(), ToClient.size()); \
break; \
} \
case csWaitingForEncryption: \
{ \
Log("Waiting for client encryption, queued %u bytes", ToClient.size()); \
m_ClientEncryptionBuffer.append(ToClient.data(), ToClient.size()); \
break; \
} \
} \ } \
DebugSleep(50); \ DebugSleep(50); \
} }
@ -379,6 +403,7 @@ bool cConnection::RelayFromServer(void)
switch (m_ServerState) switch (m_ServerState)
{ {
case csUnencrypted: case csUnencrypted:
case csWaitingForEncryption:
{ {
return DecodeServersPackets(Buffer, res); return DecodeServersPackets(Buffer, res);
} }
@ -419,6 +444,7 @@ bool cConnection::RelayFromClient(void)
switch (m_ClientState) switch (m_ClientState)
{ {
case csUnencrypted: case csUnencrypted:
case csWaitingForEncryption:
{ {
return DecodeClientsPackets(Buffer, res); return DecodeClientsPackets(Buffer, res);
} }
@ -1543,6 +1569,9 @@ bool cConnection::HandleServerEncryptionKeyResponse(void)
} }
Log("Server communication is now encrypted"); Log("Server communication is now encrypted");
m_ServerState = csEncryptedUnderstood; m_ServerState = csEncryptedUnderstood;
DataLog(m_ServerEncryptionBuffer.data(), m_ServerEncryptionBuffer.size(), "Sending the queued data to server (%u bytes):", m_ServerEncryptionBuffer.size());
SERVERENCRYPTSEND(m_ServerEncryptionBuffer.data(), m_ServerEncryptionBuffer.size());
m_ServerEncryptionBuffer.clear();
return true; return true;
} }
@ -2459,6 +2488,7 @@ void cConnection::SendEncryptionKeyResponse(const AString & a_ServerPublicKey, c
ToServer.WriteBEShort(EncryptedLength); ToServer.WriteBEShort(EncryptedLength);
ToServer.WriteBuf(EncryptedNonce, EncryptedLength); ToServer.WriteBuf(EncryptedNonce, EncryptedLength);
SERVERSEND(ToServer); SERVERSEND(ToServer);
m_ServerState = csWaitingForEncryption;
} }
@ -2507,6 +2537,11 @@ void cConnection::StartClientEncryption(const AString & a_EncKey, const AString
Log("Client connection is now encrypted"); Log("Client connection is now encrypted");
m_ClientState = csEncryptedUnderstood; m_ClientState = csEncryptedUnderstood;
// Send the queued data:
DataLog(m_ClientEncryptionBuffer.data(), m_ClientEncryptionBuffer.size(), "Sending the queued data to client (%u bytes):", m_ClientEncryptionBuffer.size());
CLIENTENCRYPTSEND(m_ClientEncryptionBuffer.data(), m_ClientEncryptionBuffer.size());
m_ClientEncryptionBuffer.clear();
// Handle all postponed server data // Handle all postponed server data
DecodeServersPackets(NULL, 0); DecodeServersPackets(NULL, 0);
} }

View File

@ -39,9 +39,10 @@ class cConnection
enum eConnectionState enum eConnectionState
{ {
csUnencrypted, // The connection is not encrypted. Packets must be decoded in order to be able to start decryption. csUnencrypted, // The connection is not encrypted. Packets must be decoded in order to be able to start decryption.
csEncryptedUnderstood, // The communication is encrypted and so far all packets have been understood, so they can be still decoded csEncryptedUnderstood, // The communication is encrypted and so far all packets have been understood, so they can be still decoded
csEncryptedUnknown, // The communication is encrypted, but an unknown packet has been received, so packets cannot be decoded anymore csEncryptedUnknown, // The communication is encrypted, but an unknown packet has been received, so packets cannot be decoded anymore
csWaitingForEncryption, // The communication is waiting for the other line to establish encryption
}; };
eConnectionState m_ClientState; eConnectionState m_ClientState;
@ -72,6 +73,9 @@ protected:
Decryptor m_ClientDecryptor; Decryptor m_ClientDecryptor;
Encryptor m_ClientEncryptor; Encryptor m_ClientEncryptor;
AString m_ClientEncryptionBuffer; // Buffer for the data to be sent to the client once encryption is established
AString m_ServerEncryptionBuffer; // Buffer for the data to be sent to the server once encryption is established
/// Set to true when PACKET_PING is received from the client; will cause special parsing for server kick /// Set to true when PACKET_PING is received from the client; will cause special parsing for server kick
bool m_HasClientPinged; bool m_HasClientPinged;