ProtoProxy: The login part of the protocol is implemented.
This commit is contained in:
parent
fe82ada084
commit
21192e5ead
@ -52,7 +52,7 @@
|
|||||||
|
|
||||||
#define CLIENTSEND(...) SendData(m_ClientSocket, __VA_ARGS__, "Client")
|
#define CLIENTSEND(...) SendData(m_ClientSocket, __VA_ARGS__, "Client")
|
||||||
#define SERVERSEND(...) SendData(m_ServerSocket, __VA_ARGS__, "Server")
|
#define SERVERSEND(...) SendData(m_ServerSocket, __VA_ARGS__, "Server")
|
||||||
#define CLIENTENCRYPTSEND(...) SendEncryptedData(m_ClientSocket, m_ClientEncryptor, __VA_ARGS__, "Client")
|
#define CLIENTENCRYPTSEND(...) SendData(m_ClientSocket, __VA_ARGS__, "Client") // The client conn is always unencrypted
|
||||||
#define SERVERENCRYPTSEND(...) SendEncryptedData(m_ServerSocket, m_ServerEncryptor, __VA_ARGS__, "Server")
|
#define SERVERENCRYPTSEND(...) SendEncryptedData(m_ServerSocket, m_ServerEncryptor, __VA_ARGS__, "Server")
|
||||||
|
|
||||||
#define COPY_TO_SERVER() \
|
#define COPY_TO_SERVER() \
|
||||||
@ -99,12 +99,13 @@
|
|||||||
CLIENTENCRYPTSEND(ToClient.data(), ToClient.size()); \
|
CLIENTENCRYPTSEND(ToClient.data(), ToClient.size()); \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
case csWaitingForEncryption: \
|
/* case csWaitingForEncryption: \
|
||||||
{ \
|
{ \
|
||||||
Log("Waiting for client encryption, queued %u bytes", ToClient.size()); \
|
Log("Waiting for client encryption, queued %u bytes", ToClient.size()); \
|
||||||
m_ClientEncryptionBuffer.append(ToClient.data(), ToClient.size()); \
|
m_ClientEncryptionBuffer.append(ToClient.data(), ToClient.size()); \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
|
*/ \
|
||||||
} \
|
} \
|
||||||
DebugSleep(50); \
|
DebugSleep(50); \
|
||||||
}
|
}
|
||||||
@ -276,7 +277,9 @@ cConnection::cConnection(SOCKET a_ClientSocket, cServer & a_Server) :
|
|||||||
m_ClientBuffer(1024 KiB),
|
m_ClientBuffer(1024 KiB),
|
||||||
m_ServerBuffer(1024 KiB),
|
m_ServerBuffer(1024 KiB),
|
||||||
m_HasClientPinged(false),
|
m_HasClientPinged(false),
|
||||||
m_ProtocolState(-1)
|
m_ServerProtocolState(-1),
|
||||||
|
m_ClientProtocolState(-1),
|
||||||
|
m_IsServerEncrypted(false)
|
||||||
{
|
{
|
||||||
// Create the Logs subfolder, if not already created:
|
// Create the Logs subfolder, if not already created:
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
@ -459,7 +462,6 @@ bool cConnection::RelayFromServer(void)
|
|||||||
{
|
{
|
||||||
m_ServerDecryptor.ProcessData((byte *)Buffer, (byte *)Buffer, res);
|
m_ServerDecryptor.ProcessData((byte *)Buffer, (byte *)Buffer, res);
|
||||||
DataLog(Buffer, res, "Decrypted %d bytes from the SERVER", res);
|
DataLog(Buffer, res, "Decrypted %d bytes from the SERVER", res);
|
||||||
m_ClientEncryptor.ProcessData((byte *)Buffer, (byte *)Buffer, res);
|
|
||||||
return CLIENTSEND(Buffer, res);
|
return CLIENTSEND(Buffer, res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -492,13 +494,10 @@ bool cConnection::RelayFromClient(void)
|
|||||||
}
|
}
|
||||||
case csEncryptedUnderstood:
|
case csEncryptedUnderstood:
|
||||||
{
|
{
|
||||||
m_ClientDecryptor.ProcessData((byte *)Buffer, (byte *)Buffer, res);
|
|
||||||
DataLog(Buffer, res, "Decrypted %d bytes from the CLIENT", res);
|
|
||||||
return DecodeClientsPackets(Buffer, res);
|
return DecodeClientsPackets(Buffer, res);
|
||||||
}
|
}
|
||||||
case csEncryptedUnknown:
|
case csEncryptedUnknown:
|
||||||
{
|
{
|
||||||
m_ClientDecryptor.ProcessData((byte *)Buffer, (byte *)Buffer, res);
|
|
||||||
DataLog(Buffer, res, "Decrypted %d bytes from the CLIENT", res);
|
DataLog(Buffer, res, "Decrypted %d bytes from the CLIENT", res);
|
||||||
m_ServerEncryptor.ProcessData((byte *)Buffer, (byte *)Buffer, res);
|
m_ServerEncryptor.ProcessData((byte *)Buffer, (byte *)Buffer, res);
|
||||||
return SERVERSEND(Buffer, res);
|
return SERVERSEND(Buffer, res);
|
||||||
@ -608,7 +607,7 @@ bool cConnection::DecodeClientsPackets(const char * a_Data, int a_Size)
|
|||||||
UInt32 PacketType;
|
UInt32 PacketType;
|
||||||
VERIFY(m_ClientBuffer.ReadVarInt(PacketType));
|
VERIFY(m_ClientBuffer.ReadVarInt(PacketType));
|
||||||
Log("Decoding client's packets, there are now %d bytes in the queue; next packet is 0x%0x, %u bytes long", m_ClientBuffer.GetReadableSpace(), PacketType, PacketLen);
|
Log("Decoding client's packets, there are now %d bytes in the queue; next packet is 0x%0x, %u bytes long", m_ClientBuffer.GetReadableSpace(), PacketType, PacketLen);
|
||||||
switch (m_ProtocolState)
|
switch (m_ClientProtocolState)
|
||||||
{
|
{
|
||||||
case -1:
|
case -1:
|
||||||
{
|
{
|
||||||
@ -625,15 +624,26 @@ bool cConnection::DecodeClientsPackets(const char * a_Data, int a_Size)
|
|||||||
// Status query
|
// Status query
|
||||||
switch (PacketType)
|
switch (PacketType)
|
||||||
{
|
{
|
||||||
case 0: HANDLE_CLIENT_READ(HandleClientStatusRequest); break;
|
case 0x00: HANDLE_CLIENT_READ(HandleClientStatusRequest); break;
|
||||||
case 1: HANDLE_CLIENT_READ(HandleClientStatusPing); break;
|
case 0x01: HANDLE_CLIENT_READ(HandleClientStatusPing); break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
{
|
{
|
||||||
// Login / game
|
// Login
|
||||||
|
switch (PacketType)
|
||||||
|
{
|
||||||
|
case 0x00: HANDLE_CLIENT_READ(HandleClientLoginStart); break;
|
||||||
|
case 0x01: HANDLE_CLIENT_READ(HandleClientLoginEncryptionKeyResponse); break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
// Game:
|
||||||
switch (PacketType)
|
switch (PacketType)
|
||||||
{
|
{
|
||||||
case PACKET_BLOCK_DIG: HANDLE_CLIENT_READ(HandleClientBlockDig); break;
|
case PACKET_BLOCK_DIG: HANDLE_CLIENT_READ(HandleClientBlockDig); break;
|
||||||
@ -642,7 +652,6 @@ bool cConnection::DecodeClientsPackets(const char * a_Data, int a_Size)
|
|||||||
case PACKET_CLIENT_STATUSES: HANDLE_CLIENT_READ(HandleClientClientStatuses); break;
|
case PACKET_CLIENT_STATUSES: HANDLE_CLIENT_READ(HandleClientClientStatuses); break;
|
||||||
case PACKET_CREATIVE_INVENTORY_ACTION: HANDLE_CLIENT_READ(HandleClientCreativeInventoryAction); break;
|
case PACKET_CREATIVE_INVENTORY_ACTION: HANDLE_CLIENT_READ(HandleClientCreativeInventoryAction); break;
|
||||||
case PACKET_DISCONNECT: HANDLE_CLIENT_READ(HandleClientDisconnect); break;
|
case PACKET_DISCONNECT: HANDLE_CLIENT_READ(HandleClientDisconnect); break;
|
||||||
case PACKET_ENCRYPTION_KEY_RESPONSE: HANDLE_CLIENT_READ(HandleClientEncryptionKeyResponse); break;
|
|
||||||
case PACKET_ENTITY_ACTION: HANDLE_CLIENT_READ(HandleClientEntityAction); break;
|
case PACKET_ENTITY_ACTION: HANDLE_CLIENT_READ(HandleClientEntityAction); break;
|
||||||
case PACKET_S_KEEPALIVE: HANDLE_CLIENT_READ(HandleClientKeepAlive); break;
|
case PACKET_S_KEEPALIVE: HANDLE_CLIENT_READ(HandleClientKeepAlive); break;
|
||||||
case PACKET_LOCALE_AND_VIEW: HANDLE_CLIENT_READ(HandleClientLocaleAndView); break;
|
case PACKET_LOCALE_AND_VIEW: HANDLE_CLIENT_READ(HandleClientLocaleAndView); break;
|
||||||
@ -733,7 +742,7 @@ bool cConnection::DecodeServersPackets(const char * a_Data, int a_Size)
|
|||||||
VERIFY(m_ServerBuffer.ReadVarInt(PacketType));
|
VERIFY(m_ServerBuffer.ReadVarInt(PacketType));
|
||||||
Log("Decoding server's packets, there are now %d bytes in the queue; next packet is 0x%0x, %u bytes long", m_ServerBuffer.GetReadableSpace(), PacketType, PacketLen);
|
Log("Decoding server's packets, there are now %d bytes in the queue; next packet is 0x%0x, %u bytes long", m_ServerBuffer.GetReadableSpace(), PacketType, PacketLen);
|
||||||
LogFlush();
|
LogFlush();
|
||||||
switch (m_ProtocolState)
|
switch (m_ServerProtocolState)
|
||||||
{
|
{
|
||||||
case -1:
|
case -1:
|
||||||
{
|
{
|
||||||
@ -754,18 +763,30 @@ bool cConnection::DecodeServersPackets(const char * a_Data, int a_Size)
|
|||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
{
|
{
|
||||||
// Login / game:
|
// Login:
|
||||||
switch (PacketType)
|
switch (PacketType)
|
||||||
{
|
{
|
||||||
case PACKET_ATTACH_ENTITY: HANDLE_SERVER_READ(HandleServerAttachEntity); break;
|
case 0x00: HANDLE_SERVER_READ(HandleServerLoginDisconnect); break;
|
||||||
case PACKET_BLOCK_ACTION: HANDLE_SERVER_READ(HandleServerBlockAction); break;
|
case 0x01: HANDLE_SERVER_READ(HandleServerLoginEncryptionKeyRequest); break;
|
||||||
case PACKET_BLOCK_CHANGE: HANDLE_SERVER_READ(HandleServerBlockChange); break;
|
case 0x02: HANDLE_SERVER_READ(HandleServerLoginSuccess); break;
|
||||||
case PACKET_CHANGE_GAME_STATE: HANDLE_SERVER_READ(HandleServerChangeGameState); break;
|
}
|
||||||
case PACKET_C_CHAT_MESSAGE: HANDLE_SERVER_READ(HandleServerChatMessage); break;
|
break;
|
||||||
case PACKET_COLLECT_PICKUP: HANDLE_SERVER_READ(HandleServerCollectPickup); break;
|
}
|
||||||
case PACKET_DESTROY_ENTITIES: HANDLE_SERVER_READ(HandleServerDestroyEntities); break;
|
|
||||||
case PACKET_ENCRYPTION_KEY_REQUEST: HANDLE_SERVER_READ(HandleServerEncryptionKeyRequest); break;
|
case 3:
|
||||||
case PACKET_ENCRYPTION_KEY_RESPONSE: HANDLE_SERVER_READ(HandleServerEncryptionKeyResponse); break;
|
{
|
||||||
|
// Game:
|
||||||
|
switch (PacketType)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
case 0x1b: HANDLE_SERVER_READ(HandleServerAttachEntity); break;
|
||||||
|
case 0x24: HANDLE_SERVER_READ(HandleServerBlockAction); break;
|
||||||
|
case 0x23: HANDLE_SERVER_READ(HandleServerBlockChange); break;
|
||||||
|
case 0x2b: HANDLE_SERVER_READ(HandleServerChangeGameState); break;
|
||||||
|
case 0x02: HANDLE_SERVER_READ(HandleServerChatMessage); break;
|
||||||
|
case 0x0d: HANDLE_SERVER_READ(HandleServerCollectPickup); break;
|
||||||
|
case 0x13: HANDLE_SERVER_READ(HandleServerDestroyEntities); break;
|
||||||
|
*/
|
||||||
case PACKET_ENTITY: HANDLE_SERVER_READ(HandleServerEntity); break;
|
case PACKET_ENTITY: HANDLE_SERVER_READ(HandleServerEntity); break;
|
||||||
case PACKET_ENTITY_EQUIPMENT: HANDLE_SERVER_READ(HandleServerEntityEquipment); break;
|
case PACKET_ENTITY_EQUIPMENT: HANDLE_SERVER_READ(HandleServerEntityEquipment); break;
|
||||||
case PACKET_ENTITY_HEAD_LOOK: HANDLE_SERVER_READ(HandleServerEntityHeadLook); break;
|
case PACKET_ENTITY_HEAD_LOOK: HANDLE_SERVER_READ(HandleServerEntityHeadLook); break;
|
||||||
@ -852,6 +873,76 @@ bool cConnection::DecodeServersPackets(const char * a_Data, int a_Size)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// packet handling, client-side, initial handshake:
|
||||||
|
|
||||||
|
bool cConnection::HandleClientHandshake(void)
|
||||||
|
{
|
||||||
|
// Read the packet from the client:
|
||||||
|
HANDLE_CLIENT_PACKET_READ(ReadVarInt, UInt32, ProtocolVersion);
|
||||||
|
HANDLE_CLIENT_PACKET_READ(ReadVarUTF8String, AString, ServerHost);
|
||||||
|
HANDLE_CLIENT_PACKET_READ(ReadBEShort, short, ServerPort);
|
||||||
|
HANDLE_CLIENT_PACKET_READ(ReadVarInt, UInt32, NextState);
|
||||||
|
m_ClientBuffer.CommitRead();
|
||||||
|
|
||||||
|
Log("Received an initial handshake packet from the client:");
|
||||||
|
Log(" ProtocolVersion = %u", ProtocolVersion);
|
||||||
|
Log(" ServerHost = \"%s\"", ServerHost.c_str());
|
||||||
|
Log(" ServerPort = %d", ServerPort);
|
||||||
|
Log(" NextState = %u", NextState);
|
||||||
|
|
||||||
|
// Send the same packet to the server, but with our port:
|
||||||
|
cByteBuffer Packet(512);
|
||||||
|
Packet.WriteVarInt(0); // Packet type - initial handshake
|
||||||
|
Packet.WriteVarInt(ProtocolVersion);
|
||||||
|
Packet.WriteVarUTF8String(ServerHost);
|
||||||
|
Packet.WriteBEShort(m_Server.GetConnectPort());
|
||||||
|
Packet.WriteVarInt(NextState);
|
||||||
|
AString Pkt;
|
||||||
|
Packet.ReadAll(Pkt);
|
||||||
|
cByteBuffer ToServer(512);
|
||||||
|
ToServer.WriteVarUTF8String(Pkt);
|
||||||
|
SERVERSEND(ToServer);
|
||||||
|
|
||||||
|
m_ClientProtocolState = (int)NextState;
|
||||||
|
m_ServerProtocolState = (int)NextState;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// packet handling, client-side, login:
|
||||||
|
|
||||||
|
bool cConnection::HandleClientLoginEncryptionKeyResponse(void)
|
||||||
|
{
|
||||||
|
Log("Client: Unexpected packet: encryption key response");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cConnection::HandleClientLoginStart(void)
|
||||||
|
{
|
||||||
|
HANDLE_CLIENT_PACKET_READ(ReadVarUTF8String, AString, UserName);
|
||||||
|
Log("Received a login start packet from the client:");
|
||||||
|
Log(" Username = \"%s\"", UserName.c_str());
|
||||||
|
COPY_TO_SERVER();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// packet handling, client-side, game:
|
||||||
|
|
||||||
bool cConnection::HandleClientAnimation(void)
|
bool cConnection::HandleClientAnimation(void)
|
||||||
{
|
{
|
||||||
HANDLE_CLIENT_PACKET_READ(ReadBEInt, int, EntityID);
|
HANDLE_CLIENT_PACKET_READ(ReadBEInt, int, EntityID);
|
||||||
@ -972,33 +1063,6 @@ bool cConnection::HandleClientDisconnect(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cConnection::HandleClientEncryptionKeyResponse(void)
|
|
||||||
{
|
|
||||||
HANDLE_CLIENT_PACKET_READ(ReadBEShort, short, EncKeyLength);
|
|
||||||
AString EncKey;
|
|
||||||
if (!m_ClientBuffer.ReadString(EncKey, EncKeyLength))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
HANDLE_CLIENT_PACKET_READ(ReadBEShort, short, EncNonceLength);
|
|
||||||
AString EncNonce;
|
|
||||||
if (!m_ClientBuffer.ReadString(EncNonce, EncNonceLength))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if ((EncKeyLength > MAX_ENC_LEN) || (EncNonceLength > MAX_ENC_LEN))
|
|
||||||
{
|
|
||||||
Log("Client: Too long encryption params");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
StartClientEncryption(EncKey, EncNonce);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cConnection::HandleClientEntityAction(void)
|
bool cConnection::HandleClientEntityAction(void)
|
||||||
{
|
{
|
||||||
HANDLE_CLIENT_PACKET_READ(ReadBEInt, int, PlayerID);
|
HANDLE_CLIENT_PACKET_READ(ReadBEInt, int, PlayerID);
|
||||||
@ -1016,43 +1080,6 @@ bool cConnection::HandleClientEntityAction(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cConnection::HandleClientHandshake(void)
|
|
||||||
{
|
|
||||||
// Read the packet from the client:
|
|
||||||
HANDLE_CLIENT_PACKET_READ(ReadVarInt, UInt32, ProtocolVersion);
|
|
||||||
HANDLE_CLIENT_PACKET_READ(ReadVarUTF8String, AString, ServerHost);
|
|
||||||
HANDLE_CLIENT_PACKET_READ(ReadBEShort, short, ServerPort);
|
|
||||||
HANDLE_CLIENT_PACKET_READ(ReadVarInt, UInt32, NextState);
|
|
||||||
m_ClientBuffer.CommitRead();
|
|
||||||
|
|
||||||
Log("Received an initial handshake packet from the client:");
|
|
||||||
Log(" ProtocolVersion = %u", ProtocolVersion);
|
|
||||||
Log(" ServerHost = \"%s\"", ServerHost.c_str());
|
|
||||||
Log(" ServerPort = %d", ServerPort);
|
|
||||||
Log(" NextState = %u", NextState);
|
|
||||||
|
|
||||||
// Send the same packet to the server, but with our port:
|
|
||||||
cByteBuffer Packet(512);
|
|
||||||
Packet.WriteVarInt(0); // Packet type - initial handshake
|
|
||||||
Packet.WriteVarInt(ProtocolVersion);
|
|
||||||
Packet.WriteVarUTF8String(ServerHost);
|
|
||||||
Packet.WriteBEShort(m_Server.GetConnectPort());
|
|
||||||
Packet.WriteVarInt(NextState);
|
|
||||||
AString Pkt;
|
|
||||||
Packet.ReadAll(Pkt);
|
|
||||||
cByteBuffer ToServer(512);
|
|
||||||
ToServer.WriteVarUTF8String(Pkt);
|
|
||||||
SERVERSEND(ToServer);
|
|
||||||
|
|
||||||
m_ProtocolState = (int)NextState;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cConnection::HandleClientKeepAlive(void)
|
bool cConnection::HandleClientKeepAlive(void)
|
||||||
{
|
{
|
||||||
HANDLE_CLIENT_PACKET_READ(ReadBEInt, int, ID);
|
HANDLE_CLIENT_PACKET_READ(ReadBEInt, int, ID);
|
||||||
@ -1325,6 +1352,84 @@ bool cConnection::HandleClientWindowClose(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// packet handling, server-side, login:
|
||||||
|
|
||||||
|
bool cConnection::HandleServerLoginDisconnect(void)
|
||||||
|
{
|
||||||
|
HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, Reason);
|
||||||
|
Log("Received a login-disconnect packet from the server:");
|
||||||
|
Log(" Reason = \"%s\"", Reason.c_str());
|
||||||
|
COPY_TO_SERVER();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cConnection::HandleServerLoginEncryptionKeyRequest(void)
|
||||||
|
{
|
||||||
|
// Read the packet from the server:
|
||||||
|
HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, ServerID);
|
||||||
|
HANDLE_SERVER_PACKET_READ(ReadBEShort, short, PublicKeyLength);
|
||||||
|
AString PublicKey;
|
||||||
|
if (!m_ServerBuffer.ReadString(PublicKey, PublicKeyLength))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
HANDLE_SERVER_PACKET_READ(ReadBEShort, short, NonceLength);
|
||||||
|
AString Nonce;
|
||||||
|
if (!m_ServerBuffer.ReadString(Nonce, NonceLength))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Log("Got PACKET_ENCRYPTION_KEY_REQUEST from the SERVER:");
|
||||||
|
Log(" ServerID = %s", ServerID.c_str());
|
||||||
|
|
||||||
|
// Reply to the server:
|
||||||
|
SendEncryptionKeyResponse(PublicKey, Nonce);
|
||||||
|
|
||||||
|
// Do not send to client - we want the client connection open
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cConnection::HandleServerLoginSuccess(void)
|
||||||
|
{
|
||||||
|
HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, UUID);
|
||||||
|
HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, Username);
|
||||||
|
Log("Received a login success packet from the server:");
|
||||||
|
Log(" UUID = \"%s\"", UUID.c_str());
|
||||||
|
Log(" Username = \"%s\"", Username.c_str());
|
||||||
|
|
||||||
|
Log("Server is now in protocol state Game.");
|
||||||
|
m_ServerProtocolState = 3;
|
||||||
|
|
||||||
|
if (m_IsServerEncrypted)
|
||||||
|
{
|
||||||
|
Log("Server communication is now encrypted");
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
COPY_TO_CLIENT();
|
||||||
|
Log("Client is now in protocol state Game.");
|
||||||
|
m_ClientProtocolState = 3;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// packet handling, server-side, game:
|
||||||
|
|
||||||
bool cConnection::HandleServerAttachEntity(void)
|
bool cConnection::HandleServerAttachEntity(void)
|
||||||
{
|
{
|
||||||
HANDLE_SERVER_PACKET_READ(ReadBEInt, int, EntityID);
|
HANDLE_SERVER_PACKET_READ(ReadBEInt, int, EntityID);
|
||||||
@ -1453,48 +1558,6 @@ bool cConnection::HandleServerDestroyEntities(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cConnection::HandleServerEncryptionKeyRequest(void)
|
|
||||||
{
|
|
||||||
// Read the packet from the server:
|
|
||||||
HANDLE_SERVER_PACKET_READ(ReadBEUTF16String16, AString, ServerID);
|
|
||||||
HANDLE_SERVER_PACKET_READ(ReadBEShort, short, PublicKeyLength);
|
|
||||||
AString PublicKey;
|
|
||||||
if (!m_ServerBuffer.ReadString(PublicKey, PublicKeyLength))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
HANDLE_SERVER_PACKET_READ(ReadBEShort, short, NonceLength);
|
|
||||||
AString Nonce;
|
|
||||||
if (!m_ServerBuffer.ReadString(Nonce, NonceLength))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Log("Got PACKET_ENCRYPTION_KEY_REQUEST from the SERVER:");
|
|
||||||
Log(" ServerID = %s", ServerID.c_str());
|
|
||||||
|
|
||||||
// Reply to the server:
|
|
||||||
SendEncryptionKeyResponse(PublicKey, Nonce);
|
|
||||||
|
|
||||||
// Send a 0xFD Encryption Key Request http://wiki.vg/Protocol#0xFD to the client, using our own key:
|
|
||||||
Log("Sending PACKET_ENCRYPTION_KEY_REQUEST to the CLIENT");
|
|
||||||
AString key;
|
|
||||||
StringSink sink(key); // GCC won't allow inline instantiation in the following line, damned temporary refs
|
|
||||||
m_Server.GetPublicKey().Save(sink);
|
|
||||||
cByteBuffer ToClient(512);
|
|
||||||
ToClient.WriteByte (PACKET_ENCRYPTION_KEY_REQUEST);
|
|
||||||
ToClient.WriteBEUTF16String16(ServerID);
|
|
||||||
ToClient.WriteBEShort ((short)key.size());
|
|
||||||
ToClient.WriteBuf (key.data(), key.size());
|
|
||||||
ToClient.WriteBEShort (4);
|
|
||||||
ToClient.WriteBEInt (m_Nonce); // Using 'this' as the cryptographic nonce, so that we don't have to generate one each time :)
|
|
||||||
CLIENTSEND(ToClient);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cConnection::HandleServerEntity(void)
|
bool cConnection::HandleServerEntity(void)
|
||||||
{
|
{
|
||||||
HANDLE_SERVER_PACKET_READ(ReadBEInt, int, EntityID);
|
HANDLE_SERVER_PACKET_READ(ReadBEInt, int, EntityID);
|
||||||
@ -1779,26 +1842,6 @@ bool cConnection::HandleServerKeepAlive(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cConnection::HandleServerEncryptionKeyResponse(void)
|
|
||||||
{
|
|
||||||
HANDLE_SERVER_PACKET_READ(ReadBEInt, int, Lengths);
|
|
||||||
if (Lengths != 0)
|
|
||||||
{
|
|
||||||
Log("Lengths are not zero!");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
Log("Server communication is now encrypted");
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cConnection::HandleServerKick(void)
|
bool cConnection::HandleServerKick(void)
|
||||||
{
|
{
|
||||||
HANDLE_SERVER_PACKET_READ(ReadBEUTF16String16, AString, Reason);
|
HANDLE_SERVER_PACKET_READ(ReadBEUTF16String16, AString, Reason);
|
||||||
@ -2826,68 +2869,14 @@ void cConnection::SendEncryptionKeyResponse(const AString & a_ServerPublicKey, c
|
|||||||
// Send the packet to the server:
|
// Send the packet to the server:
|
||||||
Log("Sending PACKET_ENCRYPTION_KEY_RESPONSE to the SERVER");
|
Log("Sending PACKET_ENCRYPTION_KEY_RESPONSE to the SERVER");
|
||||||
cByteBuffer ToServer(1024);
|
cByteBuffer ToServer(1024);
|
||||||
ToServer.WriteByte(PACKET_ENCRYPTION_KEY_RESPONSE);
|
ToServer.WriteByte(0x01); // To server: Encryption key response
|
||||||
ToServer.WriteBEShort(EncryptedLength);
|
ToServer.WriteBEShort(EncryptedLength);
|
||||||
ToServer.WriteBuf(EncryptedSecret, EncryptedLength);
|
ToServer.WriteBuf(EncryptedSecret, EncryptedLength);
|
||||||
ToServer.WriteBEShort(EncryptedLength);
|
ToServer.WriteBEShort(EncryptedLength);
|
||||||
ToServer.WriteBuf(EncryptedNonce, EncryptedLength);
|
ToServer.WriteBuf(EncryptedNonce, EncryptedLength);
|
||||||
SERVERSEND(ToServer);
|
SERVERSEND(ToServer);
|
||||||
m_ServerState = csWaitingForEncryption;
|
m_ServerState = csEncryptedUnderstood;
|
||||||
}
|
m_IsServerEncrypted = true;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cConnection::StartClientEncryption(const AString & a_EncKey, const AString & a_EncNonce)
|
|
||||||
{
|
|
||||||
// Decrypt EncNonce using privkey
|
|
||||||
RSAES<PKCS1v15>::Decryptor rsaDecryptor(m_Server.GetPrivateKey());
|
|
||||||
time_t CurTime = time(NULL);
|
|
||||||
RandomPool rng;
|
|
||||||
rng.Put((const byte *)&CurTime, sizeof(CurTime));
|
|
||||||
byte DecryptedNonce[MAX_ENC_LEN];
|
|
||||||
DecodingResult res = rsaDecryptor.Decrypt(rng, (const byte *)a_EncNonce.data(), a_EncNonce.size(), DecryptedNonce);
|
|
||||||
if (!res.isValidCoding || (res.messageLength != 4))
|
|
||||||
{
|
|
||||||
Log("Client: Bad nonce length");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (ntohl(*((int *)DecryptedNonce)) != m_Nonce)
|
|
||||||
{
|
|
||||||
Log("Bad nonce value");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decrypt the symmetric encryption key using privkey:
|
|
||||||
byte SharedSecret[MAX_ENC_LEN];
|
|
||||||
res = rsaDecryptor.Decrypt(rng, (const byte *)a_EncKey.data(), a_EncKey.size(), SharedSecret);
|
|
||||||
if (!res.isValidCoding || (res.messageLength != 16))
|
|
||||||
{
|
|
||||||
Log("Bad key length");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send encryption key response:
|
|
||||||
cByteBuffer ToClient(6);
|
|
||||||
ToClient.WriteByte((char)0xfc);
|
|
||||||
ToClient.WriteBEShort(0);
|
|
||||||
ToClient.WriteBEShort(0);
|
|
||||||
CLIENTSEND(ToClient);
|
|
||||||
|
|
||||||
// Start the encryption:
|
|
||||||
m_ClientEncryptor.SetKey(SharedSecret, 16, MakeParameters(Name::IV(), ConstByteArrayParameter(SharedSecret, 16))(Name::FeedbackSize(), 1));
|
|
||||||
m_ClientDecryptor.SetKey(SharedSecret, 16, MakeParameters(Name::IV(), ConstByteArrayParameter(SharedSecret, 16))(Name::FeedbackSize(), 1));
|
|
||||||
Log("Client connection is now encrypted");
|
|
||||||
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
|
|
||||||
DecodeServersPackets(NULL, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -71,17 +71,27 @@ protected:
|
|||||||
Decryptor m_ServerDecryptor;
|
Decryptor m_ServerDecryptor;
|
||||||
Encryptor m_ServerEncryptor;
|
Encryptor m_ServerEncryptor;
|
||||||
|
|
||||||
Decryptor m_ClientDecryptor;
|
|
||||||
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
|
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;
|
||||||
|
|
||||||
/// State the protocol is in (as defined by the initial handshake), -1 if no initial handshake received yet
|
/*
|
||||||
int m_ProtocolState;
|
The protocol states can be one of:
|
||||||
|
-1: no initial handshake received yet
|
||||||
|
1: status
|
||||||
|
2: login
|
||||||
|
3: game
|
||||||
|
*/
|
||||||
|
/// State the to-server protocol is in (as defined by the initial handshake / login), -1 if no initial handshake received yet
|
||||||
|
int m_ServerProtocolState;
|
||||||
|
|
||||||
|
/// State the to-client protocol is in (as defined by the initial handshake / login), -1 if no initial handshake received yet
|
||||||
|
int m_ClientProtocolState;
|
||||||
|
|
||||||
|
/// True if the server connection has provided encryption keys
|
||||||
|
bool m_IsServerEncrypted;
|
||||||
|
|
||||||
|
|
||||||
bool ConnectToServer(void);
|
bool ConnectToServer(void);
|
||||||
|
|
||||||
@ -112,7 +122,18 @@ protected:
|
|||||||
/// Decodes packets coming from the server, sends appropriate counterparts to the client; returns false if the connection is to be dropped
|
/// Decodes packets coming from the server, sends appropriate counterparts to the client; returns false if the connection is to be dropped
|
||||||
bool DecodeServersPackets(const char * a_Data, int a_Size);
|
bool DecodeServersPackets(const char * a_Data, int a_Size);
|
||||||
|
|
||||||
// Packet handling, client-side:
|
// Packet handling, client-side, initial:
|
||||||
|
bool HandleClientHandshake(void);
|
||||||
|
|
||||||
|
// Packet handling, client-side, status:
|
||||||
|
bool HandleClientStatusPing(void);
|
||||||
|
bool HandleClientStatusRequest(void);
|
||||||
|
|
||||||
|
// Packet handling, client-side, login:
|
||||||
|
bool HandleClientLoginEncryptionKeyResponse(void);
|
||||||
|
bool HandleClientLoginStart(void);
|
||||||
|
|
||||||
|
// Packet handling, client-side, game:
|
||||||
bool HandleClientAnimation(void);
|
bool HandleClientAnimation(void);
|
||||||
bool HandleClientBlockDig(void);
|
bool HandleClientBlockDig(void);
|
||||||
bool HandleClientBlockPlace(void);
|
bool HandleClientBlockPlace(void);
|
||||||
@ -120,9 +141,7 @@ protected:
|
|||||||
bool HandleClientClientStatuses(void);
|
bool HandleClientClientStatuses(void);
|
||||||
bool HandleClientCreativeInventoryAction(void);
|
bool HandleClientCreativeInventoryAction(void);
|
||||||
bool HandleClientDisconnect(void);
|
bool HandleClientDisconnect(void);
|
||||||
bool HandleClientEncryptionKeyResponse(void);
|
|
||||||
bool HandleClientEntityAction(void);
|
bool HandleClientEntityAction(void);
|
||||||
bool HandleClientHandshake(void);
|
|
||||||
bool HandleClientKeepAlive(void);
|
bool HandleClientKeepAlive(void);
|
||||||
bool HandleClientLocaleAndView(void);
|
bool HandleClientLocaleAndView(void);
|
||||||
bool HandleClientPing(void);
|
bool HandleClientPing(void);
|
||||||
@ -133,15 +152,18 @@ protected:
|
|||||||
bool HandleClientPlayerPositionLook(void);
|
bool HandleClientPlayerPositionLook(void);
|
||||||
bool HandleClientPluginMessage(void);
|
bool HandleClientPluginMessage(void);
|
||||||
bool HandleClientSlotSelect(void);
|
bool HandleClientSlotSelect(void);
|
||||||
bool HandleClientStatusPing(void);
|
|
||||||
bool HandleClientStatusRequest(void);
|
|
||||||
bool HandleClientTabCompletion(void);
|
bool HandleClientTabCompletion(void);
|
||||||
bool HandleClientUpdateSign(void);
|
bool HandleClientUpdateSign(void);
|
||||||
bool HandleClientUseEntity(void);
|
bool HandleClientUseEntity(void);
|
||||||
bool HandleClientWindowClick(void);
|
bool HandleClientWindowClick(void);
|
||||||
bool HandleClientWindowClose(void);
|
bool HandleClientWindowClose(void);
|
||||||
|
|
||||||
// Packet handling, server-side:
|
// Packet handling, server-side, login:
|
||||||
|
bool HandleServerLoginDisconnect(void);
|
||||||
|
bool HandleServerLoginEncryptionKeyRequest(void);
|
||||||
|
bool HandleServerLoginSuccess(void);
|
||||||
|
|
||||||
|
// Packet handling, server-side, game:
|
||||||
bool HandleServerAttachEntity(void);
|
bool HandleServerAttachEntity(void);
|
||||||
bool HandleServerBlockAction(void);
|
bool HandleServerBlockAction(void);
|
||||||
bool HandleServerBlockChange(void);
|
bool HandleServerBlockChange(void);
|
||||||
@ -150,8 +172,6 @@ protected:
|
|||||||
bool HandleServerCollectPickup(void);
|
bool HandleServerCollectPickup(void);
|
||||||
bool HandleServerCompass(void);
|
bool HandleServerCompass(void);
|
||||||
bool HandleServerDestroyEntities(void);
|
bool HandleServerDestroyEntities(void);
|
||||||
bool HandleServerEncryptionKeyRequest(void);
|
|
||||||
bool HandleServerEncryptionKeyResponse(void);
|
|
||||||
bool HandleServerEntity(void);
|
bool HandleServerEntity(void);
|
||||||
bool HandleServerEntityEquipment(void);
|
bool HandleServerEntityEquipment(void);
|
||||||
bool HandleServerEntityHeadLook(void);
|
bool HandleServerEntityHeadLook(void);
|
||||||
|
Loading…
Reference in New Issue
Block a user