diff options
-rw-r--r-- | MCServer/Plugins/Debuggers/Debuggers.lua | 2 | ||||
-rw-r--r-- | src/ClientHandle.cpp | 12 | ||||
-rw-r--r-- | src/ClientHandle.h | 14 | ||||
-rw-r--r-- | src/Protocol/Protocol17x.cpp | 13 | ||||
-rw-r--r-- | src/Protocol/ProtocolRecognizer.cpp | 2 | ||||
-rw-r--r-- | src/Server.cpp | 7 | ||||
-rw-r--r-- | src/Server.h | 8 | ||||
-rw-r--r-- | src/StringUtils.cpp | 28 | ||||
-rw-r--r-- | src/StringUtils.h | 5 |
9 files changed, 86 insertions, 5 deletions
diff --git a/MCServer/Plugins/Debuggers/Debuggers.lua b/MCServer/Plugins/Debuggers/Debuggers.lua index 0e7e647d5..66e06cb72 100644 --- a/MCServer/Plugins/Debuggers/Debuggers.lua +++ b/MCServer/Plugins/Debuggers/Debuggers.lua @@ -1502,7 +1502,7 @@ function OnPlayerJoined(a_Player) -- Test composite chat chaining: a_Player:SendMessage(cCompositeChat() :AddTextPart("Hello, ") - :AddUrlPart(a_Player:GetName(), "www.mc-server.org", "u@2") + :AddUrlPart(a_Player:GetName(), "http://www.mc-server.org", "u@2") :AddSuggestCommandPart(", and welcome.", "/help", "u") :AddRunCommandPart(" SetDay", "/time set 0") ) diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 170498037..4a3a3c250 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -312,8 +312,16 @@ void cClientHandle::Authenticate(const AString & a_Name, const AString & a_UUID, ASSERT(m_Player == NULL); m_Username = a_Name; - m_UUID = a_UUID; - m_Properties = a_Properties; + + // Only assign UUID and properties if not already pre-assigned (BungeeCord sends those in the Handshake packet): + if (m_UUID.empty()) + { + m_UUID = a_UUID; + } + if (m_Properties.empty()) + { + m_Properties = a_Properties; + } // Send login success (if the protocol supports it): m_Protocol->SendLoginSuccess(); diff --git a/src/ClientHandle.h b/src/ClientHandle.h index 74e89deee..3d0995636 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -64,15 +64,27 @@ public: const AString & GetIPString(void) const { return m_IPString; } // tolua_export + /** Sets the IP string that the client is using. Overrides the IP string that was read from the socket. + Used mainly by BungeeCord compatibility code. */ + void SetIPString(const AString & a_IPString) { m_IPString = a_IPString; } + cPlayer * GetPlayer(void) { return m_Player; } // tolua_export /** Returns the player's UUID, as used by the protocol, in the short form (no dashes) */ const AString & GetUUID(void) const { return m_UUID; } // tolua_export - void SetUUID(const AString & a_UUID) { m_UUID = a_UUID; } + /** Sets the player's UUID, as used by the protocol. Short UUID form (no dashes) is expected. + Used mainly by BungeeCord compatibility code - when authenticating is done on the BungeeCord server + and the results are passed to MCS running in offline mode. */ + void SetUUID(const AString & a_UUID) { ASSERT(a_UUID.size() == 32); m_UUID = a_UUID; } const Json::Value & GetProperties(void) const { return m_Properties; } + /** Sets the player's properties, such as skin image and signature. + Used mainly by BungeeCord compatibility code - property querying is done on the BungeeCord server + and the results are passed to MCS running in offline mode. */ + void SetProperties(const Json::Value & a_Properties) { m_Properties = a_Properties; } + /** Generates an UUID based on the username stored for this client, and stores it in the m_UUID member. This is used for the offline (non-auth) mode, when there's no UUID source. Each username generates a unique and constant UUID, so that when the player reconnects with the same name, their UUID is the same. diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index f07f6a928..7d80e79fb 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -100,6 +100,19 @@ cProtocol172::cProtocol172(cClientHandle * a_Client, const AString & a_ServerAdd m_IsEncrypted(false), m_LastSentDimension(dimNotSet) { + // BungeeCord handling: + // If BC is setup with ip_forward == true, it sends additional data in the login packet's ServerAddress field: + // hostname\00ip-address\00uuid\00profile-properties-as-json + AStringVector Params; + if (cRoot::Get()->GetServer()->ShouldAllowBungeeCord() && SplitZeroTerminatedStrings(a_ServerAddress, Params) && (Params.size() == 4)) + { + LOGD("Player at %s connected via BungeeCord", Params[1].c_str()); + m_ServerAddress = Params[0]; + m_Client->SetIPString(Params[1]); + m_Client->SetUUID(cMojangAPI::MakeUUIDShort(Params[2])); + m_Client->SetProperties(Params[3]); + } + // Create the comm log file, if so requested: if (g_ShouldLogCommIn || g_ShouldLogCommOut) { diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp index 8b395230a..d836291c3 100644 --- a/src/Protocol/ProtocolRecognizer.cpp +++ b/src/Protocol/ProtocolRecognizer.cpp @@ -27,7 +27,7 @@ cProtocolRecognizer::cProtocolRecognizer(cClientHandle * a_Client) : super(a_Client), m_Protocol(NULL), - m_Buffer(512) + m_Buffer(8192) // We need a larger buffer to support BungeeCord - it sends one huge packet at the start { } diff --git a/src/Server.cpp b/src/Server.cpp index 069e2a169..969ffd693 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -259,6 +259,13 @@ bool cServer::InitServer(cIniFile & a_SettingsIni) m_ServerID = sid.str(); m_ServerID.resize(16, '0'); } + + // Check if both BungeeCord and online mode are on, if so, warn the admin: + m_ShouldAllowBungeeCord = a_SettingsIni.GetValueSetB("Authentication", "AllowBungeeCord", false); + if (m_ShouldAllowBungeeCord && m_ShouldAuthenticate) + { + LOGWARNING("WARNING: BungeeCord is allowed and server set to online mode. This is unsafe and will not work properly. Disable either authentication or BungeeCord in settings.ini."); + } m_ShouldLoadOfflinePlayerData = a_SettingsIni.GetValueSetB("PlayerData", "LoadOfflinePlayerData", false); m_ShouldLoadNamedPlayerData = a_SettingsIni.GetValueSetB("PlayerData", "LoadNamedPlayerData", true); diff --git a/src/Server.h b/src/Server.h index f20e6932f..6d659fa40 100644 --- a/src/Server.h +++ b/src/Server.h @@ -131,6 +131,11 @@ public: // tolua_export Loaded from the settings.ini [PlayerData].LoadNamedPlayerData setting. */ bool ShouldLoadNamedPlayerData(void) const { return m_ShouldLoadNamedPlayerData; } + /** Returns true if BungeeCord logins (that specify the player's UUID) are allowed. + Read from settings, admins should set this to true only when they chain to BungeeCord, + it makes the server vulnerable to identity theft through direct connections. */ + bool ShouldAllowBungeeCord(void) const { return m_ShouldAllowBungeeCord; } + private: friend class cRoot; // so cRoot can create and destroy cServer @@ -230,6 +235,9 @@ private: This allows a seamless transition from name-based to UUID-based player storage. Loaded from the settings.ini [PlayerData].LoadNamedPlayerData setting. */ bool m_ShouldLoadNamedPlayerData; + + /** True if BungeeCord handshake packets (with player UUID) should be accepted. */ + bool m_ShouldAllowBungeeCord; cServer(void); diff --git a/src/StringUtils.cpp b/src/StringUtils.cpp index 5f88cbf64..73147eebc 100644 --- a/src/StringUtils.cpp +++ b/src/StringUtils.cpp @@ -869,3 +869,31 @@ void SetBEInt(char * a_Mem, Int32 a_Value) + +bool SplitZeroTerminatedStrings(const AString & a_Strings, AStringVector & a_Output) +{ + a_Output.clear(); + size_t size = a_Strings.size(); + size_t start = 0; + bool res = false; + for (size_t i = 0; i < size; i++) + { + if (a_Strings[i] == 0) + { + a_Output.push_back(a_Strings.substr(start, i - start)); + start = i + 1; + res = true; + } + } + if (start < size) + { + a_Output.push_back(a_Strings.substr(start, size - start)); + res = true; + } + + return res; +} + + + + diff --git a/src/StringUtils.h b/src/StringUtils.h index 72a90a8c2..a76894d05 100644 --- a/src/StringUtils.h +++ b/src/StringUtils.h @@ -99,6 +99,11 @@ extern int GetBEInt(const char * a_Mem); /// Writes four bytes to the specified memory location so that they interpret as BigEndian int extern void SetBEInt(char * a_Mem, Int32 a_Value); +/** Splits a string that has embedded \0 characters, on those characters. +a_Output is first cleared and then each separate string is pushed back into a_Output. +Returns true if there are at least two strings in a_Output (there was at least one \0 separator). */ +extern bool SplitZeroTerminatedStrings(const AString & a_Strings, AStringVector & a_Output); + /// Parses any integer type. Checks bounds and returns errors out of band. template <class T> bool StringToInteger(const AString & a_str, T & a_Num) |