diff --git a/source/Protocol.h b/source/Protocol.h index 1b313ce09..c87516640 100644 --- a/source/Protocol.h +++ b/source/Protocol.h @@ -56,7 +56,6 @@ public: virtual void SendEntRelMove (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) = 0; virtual void SendEntRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) = 0; virtual void SendGameMode (eGameMode a_GameMode) = 0; - virtual void SendHandshake (const AString & a_ServerName) = 0; virtual void SendHealth (void) = 0; virtual void SendInventoryProgress(char a_WindowID, short a_Progressbar, short a_Value) = 0; virtual void SendInventorySlot (int a_WindowID, short a_SlotNum, const cItem & a_Item) = 0; diff --git a/source/Protocol125.cpp b/source/Protocol125.cpp index d9faefb77..a50551c35 100644 --- a/source/Protocol125.cpp +++ b/source/Protocol125.cpp @@ -15,6 +15,8 @@ #include "cPlayer.h" #include "cChatColor.h" #include "cWindow.h" +#include "cRoot.h" +#include "cServer.h" @@ -958,7 +960,26 @@ int cProtocol125::ParseEntityAction(void) int cProtocol125::ParseHandshake(void) { HANDLE_PACKET_READ(ReadBEUTF16String16, AString, Username); - m_Client->HandleHandshake(Username); + + AStringVector UserData = StringSplit(Username, ";"); // "FakeTruth;localhost:25565" + if (UserData.empty()) + { + m_Client->Kick("Did not receive username"); + return PARSE_OK; + } + m_Username = UserData[0]; + + LOGD("HANDSHAKE %s", Username.c_str()); + + if (cRoot::Get()->GetDefaultWorld()->GetNumPlayers() >= cRoot::Get()->GetDefaultWorld()->GetMaxPlayers()) + { + m_Client->Kick("The server is currently full :(-- Try again later"); + return PARSE_OK; + } + + SendHandshake(cRoot::Get()->GetServer()->GetServerID()); + LOGD("User \"%s\" was sent a handshake response", m_Username.c_str()); + return PARSE_OK; } @@ -987,6 +1008,29 @@ int cProtocol125::ParseLogin(void) HANDLE_PACKET_READ(ReadChar, char, Difficulty); HANDLE_PACKET_READ(ReadByte, Byte, WorldHeight); HANDLE_PACKET_READ(ReadByte, Byte, MaxPlayers); + + if (ProtocolVersion < 29) + { + m_Client->Kick("Your client is outdated!"); + return PARSE_OK; + } + else if (ProtocolVersion > 29) + { + m_Client->Kick("Your client version is higher than the server!"); + return PARSE_OK; + } + + if (m_Username.compare(Username) != 0) + { + LOGWARNING("Login Username (\"%s\") does not match Handshake username (\"%s\") for client @ \"%s\", kicking", + Username.c_str(), + m_Username.c_str(), + m_Client->GetSocket().GetIPString().c_str() + ); + m_Client->Kick("Hacked client"); // Don't tell them why we don't want them + return PARSE_OK; + } + m_Client->HandleLogin(ProtocolVersion, Username); return PARSE_OK; } diff --git a/source/Protocol125.h b/source/Protocol125.h index c1b10bd52..db2b88833 100644 --- a/source/Protocol125.h +++ b/source/Protocol125.h @@ -42,7 +42,6 @@ public: virtual void SendEntRelMove (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override; virtual void SendEntRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override; virtual void SendGameMode (eGameMode a_GameMode) override; - virtual void SendHandshake (const AString & a_ConnectionHash) override; virtual void SendHealth (void) override; virtual void SendInventoryProgress(char a_WindowID, short a_Progressbar, short a_Value) override; virtual void SendInventorySlot (int a_WindowID, short a_SlotNum, const cItem & a_Item) override; @@ -79,8 +78,13 @@ protected: cByteBuffer m_ReceivedData; //< Buffer for the received data + AString m_Username; //< Stored in ParseHandshake(), compared to Login username + virtual void SendData(const char * a_Data, int a_Size) override; + /// Sends the Handshake packet + void SendHandshake(const AString & a_ConnectionHash); + /// Parse the packet of the specified type from m_ReceivedData (switch into ParseXYZ() ) virtual int ParsePacket(unsigned char a_PacketType); diff --git a/source/ProtocolRecognizer.h b/source/ProtocolRecognizer.h index 5afdf9506..f4704565e 100644 --- a/source/ProtocolRecognizer.h +++ b/source/ProtocolRecognizer.h @@ -39,7 +39,6 @@ public: virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override; virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) override; virtual void SendGameMode (eGameMode a_GameMode) override; - virtual void SendHandshake (const AString & a_ServerName) override; virtual void SendHealth (void) override; virtual void SendInventoryProgress(char a_WindowID, short a_Progressbar, short a_Value) override; virtual void SendInventorySlot (int a_WindowID, short a_SlotNum, const cItem & a_Item) override; diff --git a/source/cClientHandle.cpp b/source/cClientHandle.cpp index 0fd1597c4..6d217e6af 100644 --- a/source/cClientHandle.cpp +++ b/source/cClientHandle.cpp @@ -426,66 +426,21 @@ void cClientHandle::HandlePing(void) -void cClientHandle::HandleHandshake(const AString & a_Username) -{ - AStringVector UserData = StringSplit(a_Username, ";"); // "FakeTruth;localhost:25565" - if (UserData.empty()) - { - Kick("Did not receive username"); - return; - } - m_Username = UserData[0]; - - LOGD("HANDSHAKE %s", m_Username.c_str()); - - if (cRoot::Get()->GetDefaultWorld()->GetNumPlayers() >= cRoot::Get()->GetDefaultWorld()->GetMaxPlayers()) - { - Kick("The server is currently full :(-- Try again later"); - return; - } - cRoot::Get()->GetServer()->BroadcastChat(m_Username + " is connecting.", this); - - SendHandshake(cRoot::Get()->GetServer()->GetServerID()); - LOGD("User \"%s\" was sent a handshake", m_Username.c_str()); -} - - - - - -void cClientHandle::HandleLogin(int a_ProtocolVersion, const AString & a_Username) +bool cClientHandle::HandleLogin(int a_ProtocolVersion, const AString & a_Username) { LOGD("LOGIN %s", a_Username.c_str()); - if (a_ProtocolVersion < m_ProtocolVersion) - { - Kick("Your client is outdated!"); - return; - } - else if (a_ProtocolVersion > m_ProtocolVersion) - { - Kick("Your client version is higher than the server!"); - return; - } - if (m_Username.compare(a_Username) != 0) - { - LOGWARNING("Login Username (\"%s\") does not match Handshake username (\"%s\") for client @ \"%s\")", - a_Username.c_str(), - m_Username.c_str(), - m_Socket.GetIPString().c_str() - ); - Kick("Hacked client"); // Don't tell them why we don't want them - return; - } + m_Username = a_Username; if (cRoot::Get()->GetPluginManager()->CallHookLogin(this, a_ProtocolVersion, a_Username)) { Destroy(); - return; + return false; } // Schedule for authentication; until then, let them wait (but do not block) m_State = csAuthenticating; cRoot::Get()->GetAuthenticator().Authenticate(GetUniqueID(), GetUsername(), cRoot::Get()->GetServer()->GetServerID()); + return true; } @@ -1066,15 +1021,6 @@ void cClientHandle::SendDisconnect(const AString & a_Reason) -void cClientHandle::SendHandshake(const AString & a_ServerName) -{ - m_Protocol->SendHandshake(a_ServerName); -} - - - - - void cClientHandle::SendInventorySlot(int a_WindowID, short a_SlotNum, const cItem & a_Item) { m_Protocol->SendInventorySlot(a_WindowID, a_SlotNum, a_Item); diff --git a/source/cClientHandle.h b/source/cClientHandle.h index 3ae37c2e7..8ef670837 100644 --- a/source/cClientHandle.h +++ b/source/cClientHandle.h @@ -83,7 +83,6 @@ public: bool IsPlaying(void) const {return (m_State == csPlaying); } void SendDisconnect(const AString & a_Reason); - void SendHandshake (const AString & a_ServerName); void SendInventorySlot(int a_WindowID, short a_SlotNum, const cItem & a_Item); void SendChat(const AString & a_Message); void SendPlayerAnimation(const cPlayer & a_Player, char a_Animation); @@ -142,13 +141,9 @@ public: void PacketError(unsigned char a_PacketType); // Calls that cProtocol descendants use for handling packets: - // Packets handled in csConnected: - void HandlePing (void); - void HandleHandshake (const AString & a_Username); - void HandleLogin (int a_ProtocolVersion, const AString & a_Username); - void HandleUnexpectedPacket(int a_PacketType); // the default case -> kick + void HandlePing (void); - // Packets handled while in csPlaying: + void HandleUnexpectedPacket (int a_PacketType); // the default case -> kick void HandleCreativeInventory(short a_SlotNum, const cItem & a_HeldItem); void HandlePlayerPos (double a_PosX, double a_PosY, double a_PosZ, double a_Stance, bool a_IsOnGround); void HandleBlockDig (int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status); @@ -170,6 +165,11 @@ public: void HandleDisconnect (const AString & a_Reason); void HandleKeepAlive (int a_KeepAliveID); + /** Called when the protocol has finished logging the user in. + Return true to allow the user in; false to kick them. + */ + bool HandleLogin(int a_ProtocolVersion, const AString & a_Username); + void SendData(const char * a_Data, int a_Size); private: