From 800f1c0bc5bd4632bd0f246c756283cc47d31a34 Mon Sep 17 00:00:00 2001 From: x12xx12x <44411062+12xx12@users.noreply.github.com> Date: Sun, 26 Mar 2023 14:48:06 +0200 Subject: Auth SSL Fixes - Fixed Login Breaking bug - Auth and MojangAPI now use UrlClient - fixed bug in UrlClient where one letter was missing in the HTTP Header - added function to verify Urls from config files and error handling on bad Urls in config for Auth --- src/Protocol/Authenticator.cpp | 136 +++++++++++++++++------------------------ 1 file changed, 55 insertions(+), 81 deletions(-) (limited to 'src/Protocol/Authenticator.cpp') diff --git a/src/Protocol/Authenticator.cpp b/src/Protocol/Authenticator.cpp index b0669a354..00b09c30d 100644 --- a/src/Protocol/Authenticator.cpp +++ b/src/Protocol/Authenticator.cpp @@ -1,25 +1,25 @@ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules -#include "Authenticator.h" -#include "MojangAPI.h" -#include "../Root.h" -#include "../Server.h" -#include "../ClientHandle.h" -#include "../UUID.h" - -#include "../IniFile.h" -#include "../JsonUtils.h" -#include "json/json.h" +#include "Protocol/Authenticator.h" -#include "../mbedTLS++/BlockingSslClientSocket.h" +#include "ClientHandle.h" +#include "HTTP/UrlClient.h" +#include "HTTP/UrlParser.h" +#include "IniFile.h" +#include "JsonUtils.h" +#include "json/json.h" +#include "Protocol/MojangAPI.h" +#include "Root.h" +#include "Server.h" +#include "UUID.h" -#define DEFAULT_AUTH_SERVER "sessionserver.mojang.com" -#define DEFAULT_AUTH_ADDRESS "/session/minecraft/hasJoined?username=%USERNAME%&serverId=%SERVERID%" +constexpr char DEFAULT_AUTH_SERVER[] = "sessionserver.mojang.com"; +constexpr char DEFAULT_AUTH_ADDRESS[] = "/session/minecraft/hasJoined?username=%USERNAME%&serverId=%SERVERID%"; @@ -51,6 +51,36 @@ void cAuthenticator::ReadSettings(cSettingsRepositoryInterface & a_Settings) m_Server = a_Settings.GetValueSet ("Authentication", "Server", DEFAULT_AUTH_SERVER); m_Address = a_Settings.GetValueSet ("Authentication", "Address", DEFAULT_AUTH_ADDRESS); m_ShouldAuthenticate = a_Settings.GetValueSetB("Authentication", "Authenticate", true); + + // prepend https:// if missing + constexpr std::string_view HttpPrefix = "http://"; + constexpr std::string_view HttpsPrefix = "https://"; + + if ( + (std::string_view(m_Server).substr(0, HttpPrefix.size()) != HttpPrefix) && + (std::string_view(m_Server).substr(0, HttpsPrefix.size()) != HttpsPrefix) + ) + { + m_Server = "https://" + m_Server; + } + + { + auto [IsSuccessfull, ErrorMessage] = cUrlParser::Validate(m_Server); + if (!IsSuccessfull) + { + LOGWARNING("%s %d: Supplied invalid URL for configuration value [Authentication: Server]: \"%s\", using default! Error: %s", __FUNCTION__, __LINE__, m_Server.c_str(), ErrorMessage.c_str()); + m_Server = DEFAULT_AUTH_SERVER; + } + } + + { + auto [IsSuccessfull, ErrorMessage] = cUrlParser::Validate(m_Server); + if (!IsSuccessfull) + { + LOGWARNING("%s %d: Supplied invalid URL for configuration value [Authentication: Address]: \"%s\", using default! Error: %s", __FUNCTION__, __LINE__, m_Address.c_str(), ErrorMessage.c_str()); + m_Address = DEFAULT_AUTH_ADDRESS; + } + } } @@ -143,7 +173,7 @@ void cAuthenticator::Execute(void) -bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_ServerId, cUUID & a_UUID, Json::Value & a_Properties) +bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_ServerId, cUUID & a_UUID, Json::Value & a_Properties) const { LOGD("Trying to authenticate user %s", a_UserName.c_str()); @@ -152,39 +182,13 @@ bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_S ReplaceURL(ActualAddress, "%USERNAME%", a_UserName); ReplaceURL(ActualAddress, "%SERVERID%", a_ServerId); - AString Request; - Request += "GET " + ActualAddress + " HTTP/1.0\r\n"; - Request += "Host: " + m_Server + "\r\n"; - Request += "User-Agent: Cuberite\r\n"; - Request += "Connection: close\r\n"; - Request += "\r\n"; - - AString Response; - if (!cMojangAPI::SecureRequest(m_Server, Request, Response)) + // Create and send the HTTP request + auto [IsSuccessfull, Response] = cUrlClient::BlockingGet(m_Server + ActualAddress); + if (!IsSuccessfull) { return false; } - // Check the HTTP status line: - const AString Prefix("HTTP/1.1 200 OK"); - AString HexDump; - if (Response.compare(0, Prefix.size(), Prefix)) - { - LOGINFO("User %s failed to auth, bad HTTP status line received", a_UserName.c_str()); - LOGD("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str()); - return false; - } - - // Erase the HTTP headers from the response: - size_t idxHeadersEnd = Response.find("\r\n\r\n"); - if (idxHeadersEnd == AString::npos) - { - LOGINFO("User %s failed to authenticate, bad HTTP response header received", a_UserName.c_str()); - LOGD("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str()); - return false; - } - Response.erase(0, idxHeadersEnd + 4); - // Parse the Json response: if (Response.empty()) { @@ -193,14 +197,14 @@ bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_S Json::Value root; if (!JsonUtils::ParseString(Response, root)) { - LOGWARNING("cAuthenticator: Cannot parse received data (authentication) to JSON!"); + LOGWARNING("%s: Cannot parse received data (authentication) to JSON!", __FUNCTION__); return false; } a_UserName = root.get("name", "Unknown").asString(); a_Properties = root["properties"]; if (!a_UUID.FromString(root.get("id", "").asString())) { - LOGWARNING("cAuthenticator: Recieved invalid UUID format"); + LOGWARNING("%s: Received invalid UUID format", __FUNCTION__); return false; } @@ -212,9 +216,9 @@ bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_S +#ifdef ENABLE_PROPERTIES - -/* In case we want to export this function to the plugin API later - don't forget to add the relevant INI configuration lines for DEFAULT_PROPERTIES_ADDRESS +/* In case we want to export this function to the plugin API later - don't forget to add the relevant INI configuration lines for DEFAULT_PROPERTIES_ADDRESS */ #define DEFAULT_PROPERTIES_ADDRESS "/session/minecraft/profile/%UUID%" @@ -225,42 +229,12 @@ bool cAuthenticator::GetPlayerProperties(const AString & a_UUID, Json::Value & a { LOGD("Trying to get properties for user %s", a_UUID.c_str()); - // Create the GET request: - AString ActualAddress = m_PropertiesAddress; - ReplaceString(ActualAddress, "%UUID%", a_UUID); - - AString Request; - Request += "GET " + ActualAddress + " HTTP/1.0\r\n"; - Request += "Host: " + m_Server + "\r\n"; - Request += "User-Agent: Cuberite\r\n"; - Request += "Connection: close\r\n"; - Request += "\r\n"; - - AString Response; - if (!ConnectSecurelyToAddress(StarfieldCACert(), m_Server, Request, Response)) - { - return false; - } - - // Check the HTTP status line: - const AString Prefix("HTTP/1.1 200 OK"); - AString HexDump; - if (Response.compare(0, Prefix.size(), Prefix)) - { - LOGINFO("Failed to get properties for user %s, bad HTTP status line received", a_UUID.c_str()); - LOGD("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str()); - return false; - } - - // Erase the HTTP headers from the response: - size_t idxHeadersEnd = Response.find("\r\n\r\n"); - if (idxHeadersEnd == AString::npos) + // Create and send the HTTP request + auto [IsSuccessfull, Response] = cUrlClient::BlockingGet(m_Server + ActualAddress); + if (!IsSuccessfull) { - LOGINFO("Failed to get properties for user %s, bad HTTP response header received", a_UUID.c_str()); - LOGD("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str()); return false; } - Response.erase(0, idxHeadersEnd + 4); // Parse the Json response: if (Response.empty()) @@ -279,7 +253,7 @@ bool cAuthenticator::GetPlayerProperties(const AString & a_UUID, Json::Value & a a_Properties = root["properties"]; return true; } -*/ +#endif -- cgit v1.2.3