From 9f59c27b1f37dee9784e0e6acdc9054f57889d38 Mon Sep 17 00:00:00 2001 From: Anonymous275 <36374260+Anonymous-275@users.noreply.github.com> Date: Wed, 21 Dec 2022 22:26:45 +0000 Subject: [PATCH] - add hash function - add password config - add debug messages for password stages - add pass boolean for heartbeat - adjust network codes --- include/Common.h | 1 + include/TNetwork.h | 1 + src/TConfig.cpp | 4 ++++ src/THeartbeatThread.cpp | 3 ++- src/TNetwork.cpp | 30 +++++++++++++++++++++++++++++- 5 files changed, 37 insertions(+), 2 deletions(-) diff --git a/include/Common.h b/include/Common.h index a2bc21f..26d96d7 100644 --- a/include/Common.h +++ b/include/Common.h @@ -49,6 +49,7 @@ public: std::string Resource { "Resources" }; std::string MapName { "/levels/gridmap_v2/info.json" }; std::string Key {}; + std::string Password{}; std::string SSLKeyPath { "./.ssl/HttpServer/key.pem" }; std::string SSLCertPath { "./.ssl/HttpServer/cert.pem" }; bool HTTPServerEnabled { false }; diff --git a/include/TNetwork.h b/include/TNetwork.h index 3b4980e..bf5d12f 100644 --- a/include/TNetwork.h +++ b/include/TNetwork.h @@ -38,6 +38,7 @@ private: std::thread mUDPThread; std::thread mTCPThread; + static std::string Hash(const std::string& str); std::vector UDPRcvFromClient(ip::udp::endpoint& ClientEndpoint); void HandleDownload(TConnection&& TCPSock); void OnConnect(const std::weak_ptr& c); diff --git a/src/TConfig.cpp b/src/TConfig.cpp index 8c93aa4..92316c2 100644 --- a/src/TConfig.cpp +++ b/src/TConfig.cpp @@ -18,6 +18,7 @@ static constexpr std::string_view StrDescription = "Description"; static constexpr std::string_view StrResourceFolder = "ResourceFolder"; static constexpr std::string_view StrAuthKey = "AuthKey"; static constexpr std::string_view StrLogChat = "LogChat"; +static constexpr std::string_view StrPassword = "Password"; // Misc static constexpr std::string_view StrSendErrors = "SendErrors"; @@ -106,6 +107,7 @@ void TConfig::FlushToFile() { data["General"][StrMap.data()] = Application::Settings.MapName; data["General"][StrDescription.data()] = Application::Settings.ServerDesc; data["General"][StrResourceFolder.data()] = Application::Settings.Resource; + data["General"][StrPassword.data()] = Application::Settings.Password; // Misc data["Misc"][StrHideUpdateMessages.data()] = Application::Settings.HideUpdateMessages; SetComment(data["Misc"][StrHideUpdateMessages.data()].comments(), " Hides the periodic update message which notifies you of a new server version. You should really keep this on and always update as soon as possible. For more information visit https://wiki.beammp.com/en/home/server-maintenance#updating-the-server. An update message will always appear at startup regardless."); @@ -189,6 +191,7 @@ void TConfig::ParseFromFile(std::string_view name) { TryReadValue(data, "General", StrResourceFolder, Application::Settings.Resource); TryReadValue(data, "General", StrAuthKey, Application::Settings.Key); TryReadValue(data, "General", StrLogChat, Application::Settings.LogChat); + TryReadValue(data, "General", StrPassword, Application::Settings.Password); // Misc TryReadValue(data, "Misc", StrSendErrors, Application::Settings.SendErrors); TryReadValue(data, "Misc", StrHideUpdateMessages, Application::Settings.HideUpdateMessages); @@ -240,6 +243,7 @@ void TConfig::PrintDebug() { beammp_debug(std::string(StrHTTPServerIP) + ": \"" + Application::Settings.HTTPServerIP + "\""); // special! beammp_debug("Key Length: " + std::to_string(Application::Settings.Key.length()) + ""); + beammp_debug("Password Protected: " + std::string(Application::Settings.Password.empty() ? "false" : "true")); } void TConfig::ParseOldFormat() { diff --git a/src/THeartbeatThread.cpp b/src/THeartbeatThread.cpp index 873825a..ab0f5a6 100644 --- a/src/THeartbeatThread.cpp +++ b/src/THeartbeatThread.cpp @@ -149,7 +149,8 @@ std::string THeartbeatThread::GenerateCall() { << "&modstotalsize=" << mResourceManager.MaxModSize() << "&modstotal=" << mResourceManager.ModsLoaded() << "&playerslist=" << GetPlayers() - << "&desc=" << Application::Settings.ServerDesc; + << "&desc=" << Application::Settings.ServerDesc + << "&pass=" << (Application::Settings.Password.empty() ? "false" : "true"); return Ret.str(); } THeartbeatThread::THeartbeatThread(TResourceManager& ResourceManager, TServer& Server) diff --git a/src/TNetwork.cpp b/src/TNetwork.cpp index 0b0f024..cf4fec8 100644 --- a/src/TNetwork.cpp +++ b/src/TNetwork.cpp @@ -235,7 +235,8 @@ std::shared_ptr TNetwork::Authentication(TConnection&& RawConnection) { ClientKick(*Client, fmt::format("Invalid version header: '{}' ({})", std::string(reinterpret_cast(Data.data()), Data.size()), Data.size())); return nullptr; } - if (!TCPSend(*Client, StringToVector("S"))) { + + if (!TCPSend(*Client, StringToVector("A"))) { //changed to A for Accepted version // TODO: handle } @@ -322,12 +323,30 @@ std::shared_ptr TNetwork::Authentication(TConnection&& RawConnection) { } if (mServer.ClientCount() < size_t(Application::Settings.MaxPlayers)) { + + if(!Application::Settings.Password.empty()) { // ask password + if(!TCPSend(*Client, StringToVector("S"))) { + // TODO: handle + } + beammp_info("Waiting for password"); + Data = TCPRcv(*Client); + std::string Pass = std::string(reinterpret_cast(Data.data()), Data.size()); + if(Pass != Hash(Application::Settings.Password)) { + beammp_debug(Client->GetName() + " attempted to connect with a wrong password"); + ClientKick(*Client, "Wrong password!"); + return {}; + } else { + beammp_debug(Client->GetName() + " used the correct password"); + } + } + beammp_info("Identification success"); mServer.InsertClient(Client); TCPClient(Client); } else { ClientKick(*Client, "Server full!"); } + return Client; } @@ -943,3 +962,12 @@ std::vector TNetwork::UDPRcvFromClient(ip::udp::endpoint& ClientEndpoin beammp_assert(Rcv <= Ret.size()); return std::vector(Ret.begin(), Ret.begin() + Rcv); } + +std::string TNetwork::Hash(const std::string& str) { + std::stringstream ret; + unsigned char* hash = SHA256(reinterpret_cast(str.c_str()), str.length(), nullptr); + for (int i = 0; i < 32; i++) { + ret << std::hex << (int)hash[i]; + } + return ret.str(); +}