diff options
| author | Shauren <shauren.trinity@gmail.com> | 2016-03-28 17:12:57 +0200 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2016-03-28 17:12:57 +0200 |
| commit | dde620c402daf4ea8d132fb72a77eabc22f7a6d0 (patch) | |
| tree | 7c12161d7a22915736b0c9a106de896eeb283399 /src/server/bnetserver | |
| parent | 619669c6209441fc2fb5b483d553badee8c30ad5 (diff) | |
Core: Updated to 6.2.4
* Rewrite bnetserver for new authentication protocol
Diffstat (limited to 'src/server/bnetserver')
51 files changed, 1695 insertions, 4785 deletions
diff --git a/src/server/bnetserver/Authentication/AuthCodes.cpp b/src/server/bnetserver/Authentication/AuthCodes.cpp deleted file mode 100644 index 41e2aad35ef..00000000000 --- a/src/server/bnetserver/Authentication/AuthCodes.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "AuthCodes.h" -#include "Define.h" -#include <vector> - -namespace AuthHelper -{ - // List of client builds for verbose version info in realmlist packet - static std::vector<RealmBuildInfo> const ClientBuilds = - { - { 20726, 6, 2, 3, ' ' }, - { 20574, 6, 2, 2, 'a' }, - { 20490, 6, 2, 2, 'a' }, - { 15595, 4, 3, 4, ' ' }, - { 14545, 4, 2, 2, ' ' }, - { 13623, 4, 0, 6, 'a' }, - { 13930, 3, 3, 5, 'a' }, // 3.3.5a China Mainland build - { 12340, 3, 3, 5, 'a' }, - { 11723, 3, 3, 3, 'a' }, - { 11403, 3, 3, 2, ' ' }, - { 11159, 3, 3, 0, 'a' }, - { 10505, 3, 2, 2, 'a' }, - { 9947, 3, 1, 3, ' ' }, - { 8606, 2, 4, 3, ' ' }, - { 6141, 1, 12, 3, ' ' }, - { 6005, 1, 12, 2, ' ' }, - { 5875, 1, 12, 1, ' ' }, - }; - - RealmBuildInfo const* GetBuildInfo(int build) - { - for (std::size_t i = 0; i < ClientBuilds.size(); ++i) - if (ClientBuilds[i].Build == build) - return &ClientBuilds[i]; - - return nullptr; - } - - bool IsBuildSupportingBattlenet(int build) - { - return build >= 15595; - } -} diff --git a/src/server/bnetserver/Authentication/AuthCodes.h b/src/server/bnetserver/Authentication/AuthCodes.h deleted file mode 100644 index dc545445e68..00000000000 --- a/src/server/bnetserver/Authentication/AuthCodes.h +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef _AUTHCODES_H -#define _AUTHCODES_H - -enum GameAccountFlags -{ - GAMEACCOUNT_FLAG_GM = 0x00000001, - GAMEACCOUNT_FLAG_NOKICK = 0x00000002, - GAMEACCOUNT_FLAG_COLLECTOR = 0x00000004, - GAMEACCOUNT_FLAG_WOW_TRIAL = 0x00000008, - GAMEACCOUNT_FLAG_CANCELLED = 0x00000010, - GAMEACCOUNT_FLAG_IGR = 0x00000020, - GAMEACCOUNT_FLAG_WHOLESALER = 0x00000040, - GAMEACCOUNT_FLAG_PRIVILEGED = 0x00000080, - GAMEACCOUNT_FLAG_EU_FORBID_ELV = 0x00000100, - GAMEACCOUNT_FLAG_EU_FORBID_BILLING = 0x00000200, - GAMEACCOUNT_FLAG_WOW_RESTRICTED = 0x00000400, - GAMEACCOUNT_FLAG_PARENTAL_CONTROL = 0x00000800, - GAMEACCOUNT_FLAG_REFERRAL = 0x00001000, - GAMEACCOUNT_FLAG_BLIZZARD = 0x00002000, - GAMEACCOUNT_FLAG_RECURRING_BILLING = 0x00004000, - GAMEACCOUNT_FLAG_NOELECTUP = 0x00008000, - GAMEACCOUNT_FLAG_KR_CERTIFICATE = 0x00010000, - GAMEACCOUNT_FLAG_EXPANSION_COLLECTOR = 0x00020000, - GAMEACCOUNT_FLAG_DISABLE_VOICE = 0x00040000, - GAMEACCOUNT_FLAG_DISABLE_VOICE_SPEAK = 0x00080000, - GAMEACCOUNT_FLAG_REFERRAL_RESURRECT = 0x00100000, - GAMEACCOUNT_FLAG_EU_FORBID_CC = 0x00200000, - GAMEACCOUNT_FLAG_OPENBETA_DELL = 0x00400000, - GAMEACCOUNT_FLAG_PROPASS = 0x00800000, - GAMEACCOUNT_FLAG_PROPASS_LOCK = 0x01000000, - GAMEACCOUNT_FLAG_PENDING_UPGRADE = 0x02000000, - GAMEACCOUNT_FLAG_RETAIL_FROM_TRIAL = 0x04000000, - GAMEACCOUNT_FLAG_EXPANSION2_COLLECTOR = 0x08000000, - GAMEACCOUNT_FLAG_OVERMIND_LINKED = 0x10000000, - GAMEACCOUNT_FLAG_DEMOS = 0x20000000, - GAMEACCOUNT_FLAG_DEATH_KNIGHT_OK = 0x40000000, -}; - -namespace Battlenet -{ - enum AuthResult - { - AUTH_OK = 0, - AUTH_INTERNAL_ERROR = 100, - AUTH_CORRUPTED_MODULE = 101, - AUTH_NO_BATTLETAGS = 102, - AUTH_BAD_SERVER_PROOF = 103, - AUTH_UNKNOWN_ACCOUNT = 104, - AUTH_CLOSED = 105, - AUTH_LOGIN_TIMEOUT = 106, - AUTH_NO_GAME_ACCOUNTS = 107, - AUTH_INVALID_TOKEN = 108, - AUTH_INVALID_PROGRAM = 109, - AUTH_INVALID_OS = 110, - AUTH_UNSUPPORTED_LANGUAGE = 111, - AUTH_REGION_BAD_VERSION = 112, - AUTH_TEMP_OUTAGE = 113, - AUTH_CANT_DOWNLOAD_MODULE = 114, - AUTH_DUPLICATE_LOGON = 115, - AUTH_BAD_CREDENTIALS_2 = 116, - AUTH_VERSION_CHECK_SUCCEEDED = 117, - AUTH_BAD_VERSION_HASH = 118, - AUTH_CANT_RETRIEVE_PORTAL_LIST = 119, - AUTH_DARK_PORTAL_DOES_NOT_EXIST = 120, - AUTH_DARK_PORTAL_FILE_CORRUPTED = 121, - AUTH_BATTLENET_MAINTENANCE = 122, - AUTH_LOGON_TOO_FAST = 123, - AUTH_USE_GRUNT_LOGON = 124, - AUTH_NO_GAME_ACCOUNTS_IN_REGION = 140, - AUTH_ACCOUNT_LOCKED = 141, - - LOGIN_SERVER_BUSY = 200, - LOGIN_NO_GAME_ACCOUNT = 201, - LOGIN_BANNED = 202, - LOGIN_SUSPENDED = 203, - LOGIN_GAME_ACCOUNT_LOCKED = 204, - LOGIN_ALREADY_ONLINE = 205, - LOGIN_NOTIME = 206, - LOGIN_EXPIRED = 207, - LOGIN_EXPIRED_2 = 208, - LOGIN_PARENTALCONTROL = 209, - LOGIN_TRIAL_EXPIRED = 210, - LOGIN_ANTI_INDULGENCE = 211, - LOGIN_INCORRECT_REGION = 212, - LOGIN_LOCKED_ENFORCED = 213, - LOGIN_CHARGEBACK = 214, - LOGIN_IGR_WITHOUT_BNET = 215, - LOGIN_UNLOCKABLE_LOCK = 216, - LOGIN_IGR_REQUIRED = 217, - LOGIN_PAYMENT_CHANGED = 218, - LOGIN_INVALID_PAYMENT = 219, - LOGIN_INVALID_ACCOUNT_STATE = 220 - }; - - namespace Wow - { - enum AuthResult - { - WOW_SUCCESS = 0, - WOW_FAIL_BANNED = 3, - WOW_FAIL_UNKNOWN_ACCOUNT = 4, - WOW_FAIL_INCORRECT_PASSWORD = 5, - WOW_FAIL_ALREADY_ONLINE = 6, - WOW_FAIL_NO_TIME = 7, - WOW_FAIL_DB_BUSY = 8, - WOW_FAIL_VERSION_INVALID = 9, - WOW_FAIL_VERSION_UPDATE = 10, - WOW_FAIL_INVALID_SERVER = 11, - WOW_FAIL_SUSPENDED = 12, - WOW_FAIL_FAIL_NOACCESS = 13, - WOW_SUCCESS_SURVEY = 14, - WOW_FAIL_PARENTCONTROL = 15, - WOW_FAIL_LOCKED_ENFORCED = 16, - WOW_FAIL_TRIAL_ENDED = 17, - WOW_FAIL_OVERMIND_CONVERTED = 18, - WOW_FAIL_ANTI_INDULGENCE = 19, - WOW_FAIL_EXPIRED = 20, - WOW_FAIL_NO_GAME_ACCOUNT = 21, - WOW_FAIL_BILLING_LOCK = 22, - WOW_FAIL_IGR_WITHOUT_BNET = 23, - WOW_FAIL_AA_LOCK = 24, - WOW_FAIL_UNLOCKABLE_LOCK = 25, - WOW_FAIL_MUST_USE_BNET = 26, - WOW_FAIL_OTHER = 255, - }; - } -} - -struct RealmBuildInfo -{ - int Build; - int MajorVersion; - int MinorVersion; - int BugfixVersion; - int HotfixVersion; -}; - -namespace AuthHelper -{ - RealmBuildInfo const* GetBuildInfo(int build); - bool IsBuildSupportingBattlenet(int build); -} - -#endif diff --git a/src/server/bnetserver/Authentication/BattlenetPacketCrypt.cpp b/src/server/bnetserver/Authentication/BattlenetPacketCrypt.cpp deleted file mode 100644 index c23a7931c67..00000000000 --- a/src/server/bnetserver/Authentication/BattlenetPacketCrypt.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "BattlenetPacketCrypt.h" -#include "Cryptography/HmacHash.h" -#include "Cryptography/BigNumber.h" - -Battlenet::PacketCrypt::PacketCrypt() : ::PacketCrypt(SHA256_DIGEST_LENGTH) -{ -} - -void Battlenet::PacketCrypt::Init(BigNumber* K) -{ - uint8 ServerEncryptionKey[SEED_KEY_SIZE] = { 0x68, 0xE0, 0xC7, 0x2E, 0xDD, 0xD6, 0xD2, 0xF3, 0x1E, 0x5A, 0xB1, 0x55, 0xB1, 0x8B, 0x63, 0x1E }; - uint8 ClientDecryptionKey[SEED_KEY_SIZE] = { 0xDE, 0xA9, 0x65, 0xAE, 0x54, 0x3A, 0x1E, 0x93, 0x9E, 0x69, 0x0C, 0xAA, 0x68, 0xDE, 0x78, 0x39 }; - - HmacSha256 serverEncryptHmac(K->GetNumBytes(), K->AsByteArray().get()); - serverEncryptHmac.UpdateData(ServerEncryptionKey, SEED_KEY_SIZE); - serverEncryptHmac.Finalize(); - - HmacSha256 clientDecryptHmac(K->GetNumBytes(), K->AsByteArray().get()); - clientDecryptHmac.UpdateData(ClientDecryptionKey, SEED_KEY_SIZE); - clientDecryptHmac.Finalize(); - - _clientDecrypt.Init(clientDecryptHmac.GetDigest()); - _serverEncrypt.Init(serverEncryptHmac.GetDigest()); - _initialized = true; -} diff --git a/src/server/bnetserver/CMakeLists.txt b/src/server/bnetserver/CMakeLists.txt index 7aa861499d9..c6e8808b69a 100644 --- a/src/server/bnetserver/CMakeLists.txt +++ b/src/server/bnetserver/CMakeLists.txt @@ -16,9 +16,9 @@ CollectSourceFiles( # Exclude ${CMAKE_CURRENT_SOURCE_DIR}/PrecompiledHeaders) -if( WIN32 ) +if (WIN32) list(APPEND PRIVATE_SOURCES ${sources_windows}) - if ( MSVC ) + if (MSVC) list(APPEND PRIVATE_SOURCES bnetserver.rc) endif() endif() @@ -35,7 +35,7 @@ add_executable(bnetserver ${PRIVATE_PCH_SOURCE} ) -if( NOT WIN32 ) +if (NOT WIN32) set_target_properties(bnetserver PROPERTIES COMPILE_DEFINITIONS _TRINITY_BNET_CONFIG="${CONF_DIR}/bnetserver.conf" ) @@ -62,26 +62,32 @@ set_target_properties(bnetserver FOLDER "server") -if( WIN32 ) - if ( MSVC ) +if (WIN32) + if (MSVC) add_custom_command(TARGET bnetserver POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bnetserver.conf.dist ${CMAKE_BINARY_DIR}/bin/$(ConfigurationName)/ + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bnetserver.cert.pem ${CMAKE_BINARY_DIR}/bin/$(ConfigurationName)/ + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bnetserver.key.pem ${CMAKE_BINARY_DIR}/bin/$(ConfigurationName)/ ) - elseif ( MINGW ) + elseif (MINGW) add_custom_command(TARGET bnetserver POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bnetserver.conf.dist ${CMAKE_BINARY_DIR}/bin/ + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bnetserver.cert.pem ${CMAKE_BINARY_DIR}/bin/ + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bnetserver.key.pem ${CMAKE_BINARY_DIR}/bin/ ) endif() endif() -if( UNIX ) +if (UNIX) install(TARGETS bnetserver DESTINATION bin) - install(FILES bnetserver.conf.dist DESTINATION ${CONF_DIR}) -elseif( WIN32 ) + install(FILES bnetserver.conf.dist DESTINATION ${CONF_DIR}) + install(FILES bnetserver.cert.pem bnetserver.key.pem DESTINATION bin) +elseif (WIN32) install(TARGETS bnetserver DESTINATION "${CMAKE_INSTALL_PREFIX}") install(FILES bnetserver.conf.dist DESTINATION "${CMAKE_INSTALL_PREFIX}") + install(FILES bnetserver.cert.pem bnetserver.key.pem DESTINATION "${CMAKE_INSTALL_PREFIX}") endif() # Generate precompiled header diff --git a/src/server/bnetserver/Main.cpp b/src/server/bnetserver/Main.cpp index 65b8d6e772b..f95c7b90d07 100644 --- a/src/server/bnetserver/Main.cpp +++ b/src/server/bnetserver/Main.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -24,25 +23,17 @@ * authentication server */ -#include "ComponentManager.h" -#include "ModuleManager.h" #include "SessionManager.h" -#include "Common.h" -#include "Config.h" -#include "DatabaseEnv.h" -#include "Log.h" #include "AppenderDB.h" #include "ProcessPriority.h" #include "RealmList.h" #include "GitRevision.h" -#include "Util.h" +#include "SslContext.h" #include "DatabaseLoader.h" -#include <cstdlib> +#include "LoginRESTService.h" #include <iostream> -#include <boost/date_time/posix_time/posix_time.hpp> #include <boost/program_options.hpp> -#include <openssl/opensslv.h> -#include <openssl/crypto.h> +#include <google/protobuf/stubs/common.h> using boost::asio::ip::tcp; using namespace boost::program_options; @@ -92,6 +83,8 @@ int main(int argc, char** argv) if (vm.count("help") || vm.count("version")) return 0; + GOOGLE_PROTOBUF_VERIFY_VERSION; + #if PLATFORM == PLATFORM_WINDOWS if (configService.compare("install") == 0) return WinServiceInstall() ? 0 : 1; @@ -135,15 +128,18 @@ int main(int argc, char** argv) } } + if (!Battlenet::SslContext::Initialize()) + { + TC_LOG_ERROR("server.bnetserver", "Failed to initialize SSL context"); + return 1; + } + // Initialize the database connection if (!StartDB()) return 1; _ioService = new boost::asio::io_service(); - // Get the list of realms for the server - sRealmList->Initialize(*_ioService, sConfigMgr->GetIntDefault("RealmsStateUpdateDelay", 10)); - // Start the listening port (acceptor) for auth connections int32 bnport = sConfigMgr->GetIntDefault("BattlenetPort", 1119); if (bnport < 0 || bnport > 0xFFFF) @@ -154,6 +150,17 @@ int main(int argc, char** argv) return 1; } + if (!sLoginService.Start(*_ioService)) + { + StopDB(); + delete _ioService; + TC_LOG_ERROR("server.bnetserver", "Failed to initialize login service"); + return 1; + } + + // Get the list of realms for the server + sRealmList->Initialize(*_ioService, sConfigMgr->GetIntDefault("RealmsStateUpdateDelay", 10)); + std::string bindIp = sConfigMgr->GetStringDefault("BindIP", "0.0.0.0"); sSessionMgr.StartNetwork(*_ioService, bindIp, bnport); @@ -179,9 +186,6 @@ int main(int argc, char** argv) _banExpiryCheckTimer->expires_from_now(boost::posix_time::seconds(_banExpiryCheckInterval)); _banExpiryCheckTimer->async_wait(BanExpiryHandler); - sComponentMgr->Load(); - sModuleMgr->Load(); - #if PLATFORM == PLATFORM_WINDOWS if (m_ServiceStatus != -1) { @@ -197,6 +201,8 @@ int main(int argc, char** argv) _banExpiryCheckTimer->cancel(); _dbPingTimer->cancel(); + sLoginService.Stop(); + sSessionMgr.StopNetwork(); sRealmList->Close(); @@ -211,6 +217,7 @@ int main(int argc, char** argv) delete _banExpiryCheckTimer; delete _dbPingTimer; delete _ioService; + google::protobuf::ShutdownProtobufLibrary(); return 0; } diff --git a/src/server/bnetserver/Packets/AuthenticationPackets.cpp b/src/server/bnetserver/Packets/AuthenticationPackets.cpp deleted file mode 100644 index d9dd3ad6bd7..00000000000 --- a/src/server/bnetserver/Packets/AuthenticationPackets.cpp +++ /dev/null @@ -1,428 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "AuthenticationPackets.h" -#include "Session.h" -#include "Util.h" - -std::string Battlenet::Authentication::RequestCommon::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::Authentication::RequestCommon" << std::endl; - APPEND_FIELD(stream, Program); - APPEND_FIELD(stream, Platform); - APPEND_FIELD(stream, Locale); - APPEND_FIELD(stream, Versions); - return stream.str(); -} - -void Battlenet::Authentication::ResumeRequest::Read() -{ - Common.Program = _stream.ReadFourCC(); - Common.Platform = _stream.ReadFourCC(); - Common.Locale = _stream.ReadFourCC(); - - Common.Versions.resize(_stream.Read<uint32>(6)); - for (size_t i = 0; i < Common.Versions.size(); ++i) - { - Version::Record& component = Common.Versions[i]; - component.ProgramId = _stream.ReadFourCC(); - component.Component = _stream.ReadFourCC(); - component.Version = _stream.Read<uint32>(32); - } - - Account = _stream.ReadString(9, 3); - GameAccountRegion = _stream.Read<uint8>(8); - GameAccountName = _stream.ReadString(5, 1); -} - -std::string Battlenet::Authentication::ResumeRequest::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::Authentication::ResumeRequest" << std::endl; - APPEND_FIELD(stream, Common); - APPEND_FIELD(stream, Account); - APPEND_FIELD(stream, GameAccountRegion); - APPEND_FIELD(stream, GameAccountName); - return stream.str(); -} - -void Battlenet::Authentication::ResumeRequest::CallHandler(Session* session) -{ - session->HandleResumeRequest(*this); -} - -Battlenet::Authentication::ProofResponse::~ProofResponse() -{ - for (size_t i = 0; i < Response.size(); ++i) - delete Response[i]; -} - -void Battlenet::Authentication::ProofResponse::Read() -{ - Response.resize(_stream.Read<uint32>(3)); - for (size_t i = 0; i < Response.size(); ++i) - { - BitStream*& dataStream = Response[i]; - dataStream = new BitStream(_stream.Read<uint32>(10)); - memcpy(dataStream->GetBuffer(), _stream.ReadBytes(dataStream->GetSize()).get(), dataStream->GetSize()); - } -} - -std::string Battlenet::Authentication::ProofResponse::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::Authentication::ProofRequest" << std::endl; - APPEND_FIELD(stream, Response.size()); - return stream.str(); -} - -void Battlenet::Authentication::ProofResponse::CallHandler(Session* session) -{ - session->HandleProofResponse(*this); -} - -void Battlenet::Authentication::LogonRequest3::Read() -{ - Common.Program = _stream.ReadFourCC(); - Common.Platform = _stream.ReadFourCC(); - Common.Locale = _stream.ReadFourCC(); - - Common.Versions.resize(_stream.Read<uint32>(6)); - for (size_t i = 0; i < Common.Versions.size(); ++i) - { - Version::Record& component = Common.Versions[i]; - component.ProgramId = _stream.ReadFourCC(); - component.Component = _stream.ReadFourCC(); - component.Version = _stream.Read<uint32>(32); - } - - if (_stream.Read<uint32>(1)) - Account = _stream.ReadString(9, 3); - - Compatibility = _stream.Read<uint64>(64); -} - -std::string Battlenet::Authentication::LogonRequest3::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::Authentication::LogonRequest3" << std::endl; - APPEND_FIELD(stream, Common); - APPEND_FIELD(stream, Account); - APPEND_FIELD(stream, Compatibility); - return stream.str(); -} - -void Battlenet::Authentication::LogonRequest3::CallHandler(Session* session) -{ - session->HandleLogonRequest(*this); -} - -Battlenet::Authentication::LogonResponse::~LogonResponse() -{ - for (ModuleInfo* m : Result.Success.FinalRequest) - delete m; -} - -void Battlenet::Authentication::LogonResponse::Write() -{ - _stream.Write(Result.Type, 1); - if (Result.Type == ResultType::SUCCESS) - { - _stream.Write(Result.Success.FinalRequest.size(), 3); - for (size_t i = 0; i < Result.Success.FinalRequest.size(); ++i) - { - ModuleInfo* info = Result.Success.FinalRequest[i]; - _stream.WriteBytes(info->Handle.Type.c_str(), 4); - _stream.WriteFourCC(info->Handle.Region); - _stream.WriteBytes(info->Handle.ModuleId, 32); - _stream.Write(info->DataSize, 10); - _stream.WriteBytes(info->Data, info->DataSize); - } - - _stream.Write(Result.Success.PingTimeout + std::numeric_limits<int32>::min(), 32); - _stream.Write(Result.Success.RegulatorRules.is_initialized(), 1); - if (Result.Success.RegulatorRules.is_initialized()) - { - _stream.Write(Result.Success.RegulatorRules->Type == Regulator::LEAKY_BUCKET, 1); - if (Result.Success.RegulatorRules->Type == Regulator::LEAKY_BUCKET) - { - _stream.Write(Result.Success.RegulatorRules->LeakyBucket.Threshold, 32); - _stream.Write(Result.Success.RegulatorRules->LeakyBucket.Rate, 32); - } - } - - _stream.WriteString(Result.Success.FullName.GivenName, 8); - _stream.WriteString(Result.Success.FullName.Surname, 8); - _stream.Write(Result.Success.AccountId, 32); - _stream.Write(Result.Success.Region, 8); - _stream.Write(Result.Success.Flags, 64); - _stream.Write(Result.Success.GameAccountRegion, 8); - _stream.WriteString(Result.Success.GameAccountName, 5, -1); - _stream.Write(Result.Success.GameAccountFlags, 64); - _stream.Write(Result.Success.LogonFailures, 32); - } - else - { - _stream.Write(Result.Failure.Strings.is_initialized(), 1); - if (Result.Failure.Strings.is_initialized()) - { - _stream.WriteBytes(Result.Failure.Strings->Type.c_str(), 4); - _stream.WriteFourCC(Result.Failure.Strings->Region); - _stream.WriteBytes(Result.Failure.Strings->ModuleId, 32); - } - - _stream.Write(Result.Failure.Result.Type, 2); - if (Result.Failure.Result.Type == FailureType::FAILURE) - { - _stream.Write(Result.Failure.Result.Failure.Error, 16); - _stream.Write(Result.Failure.Result.Failure.Wait + std::numeric_limits<int32>::min(), 32); - } - } - - _stream.Write(Raf.is_initialized(), 1); - if (Raf.is_initialized()) - { - _stream.Write(Raf->size(), 10); - _stream.WriteBytes(Raf->data(), Raf->size()); - } -} - -std::string Battlenet::Authentication::LogonResponse::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::Authentication::LogonResponse" << std::endl; - APPEND_FIELD(stream, Result); - APPEND_FIELD(stream, Raf); - return stream.str(); -} - -std::string Battlenet::Authentication::FailureType::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::Authentication::FailureType" << std::endl; - APPEND_FIELD(stream, Strings); - APPEND_FIELD(stream, Result); - return stream.str(); -} - -std::string Battlenet::Authentication::FailureType::ResultType::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::Authentication::ResponseFailure::Result" << std::endl; - switch (Type) - { - case UPDATE: - APPEND_FIELD(stream, Update); - break; - case FAILURE: - APPEND_FIELD(stream, Failure); - break; - case VERSION_CHECK_DISCONNECT: - APPEND_FIELD(stream, VersionCheckDisconnect); - break; - default: - break; - } - return stream.str(); -} - -std::string Battlenet::Authentication::FailureType::ResultType::UpdateType::ToString() const -{ - return "Battlenet::Authentication::ResponseFailure::Result::Update"; -} - -std::string Battlenet::Authentication::FailureType::ResultType::FailureType::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::Authentication::ResponseFailure::Result::Failure" << std::endl; - APPEND_FIELD(stream, Error); - APPEND_FIELD(stream, Wait); - return stream.str(); -} - -std::string Battlenet::Authentication::FailureType::ResultType::VersionCheckDisconnectType::ToString() const -{ - return "Battlenet::Authentication::ResponseFailure::Result::VersionCheckDisconnect"; -} - -std::string Battlenet::Authentication::Regulator::NoneType::ToString() const -{ - return "Battlenet::Regulator::None"; -} - -std::string Battlenet::Authentication::Regulator::LeakyBucketType::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::Regulator::LeakyBucket" << std::endl; - APPEND_FIELD(stream, Threshold); - APPEND_FIELD(stream, Rate); - return stream.str(); -} - -std::string Battlenet::Authentication::Regulator::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::Regulator" << std::endl; - switch (Type) - { - case NONE: - APPEND_FIELD(stream, None); - break; - case LEAKY_BUCKET: - APPEND_FIELD(stream, LeakyBucket); - break; - default: - break; - } - return stream.str(); -} - -std::string Battlenet::Authentication::LogonResponse::ResultType::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::Authentication::LogonResponse::Result" << std::endl; - switch (Type) - { - case SUCCESS: - APPEND_FIELD(stream, Success); - break; - case FAILURE: - APPEND_FIELD(stream, Failure); - break; - default: - break; - } - return stream.str(); -} - -std::string Battlenet::Authentication::LogonResponse::ResultType::SuccessType::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::Authentication::LogonResponse::Result::Success" << std::endl; - APPEND_FIELD(stream, FinalRequest); - APPEND_FIELD(stream, PingTimeout); - APPEND_FIELD(stream, RegulatorRules); - APPEND_FIELD(stream, FullName); - APPEND_FIELD(stream, AccountId); - APPEND_FIELD(stream, Region); - APPEND_FIELD(stream, Flags); - APPEND_FIELD(stream, GameAccountRegion); - APPEND_FIELD(stream, GameAccountName); - APPEND_FIELD(stream, GameAccountFlags); - APPEND_FIELD(stream, LogonFailures); - return stream.str(); -} - -void Battlenet::Authentication::LogonResponse::SetAuthResult(AuthResult result) -{ - Result.Type = result != AUTH_OK ? ResultType::FAILURE : ResultType::SUCCESS; - Result.Failure.Result.Failure.Error = result; -} - -Battlenet::Authentication::ResumeResponse::~ResumeResponse() -{ - for (ModuleInfo* m : Result.Success.FinalRequest) - delete m; -} - -void Battlenet::Authentication::ResumeResponse::Write() -{ - _stream.Write(Result.Type, 1); - if (Result.Type == ResultType::SUCCESS) - { - _stream.Write(Result.Success.FinalRequest.size(), 3); - for (size_t i = 0; i < Result.Success.FinalRequest.size(); ++i) - { - ModuleInfo* info = Result.Success.FinalRequest[i]; - _stream.WriteBytes(info->Handle.Type.c_str(), 4); - _stream.WriteFourCC(info->Handle.Region); - _stream.WriteBytes(info->Handle.ModuleId, 32); - _stream.Write(info->DataSize, 10); - _stream.WriteBytes(info->Data, info->DataSize); - } - - _stream.Write(Result.Success.PingTimeout + std::numeric_limits<int32>::min(), 32); - _stream.Write(Result.Success.RegulatorRules.is_initialized(), 1); - if (Result.Success.RegulatorRules.is_initialized()) - { - _stream.Write(Result.Success.RegulatorRules->Type == Regulator::LEAKY_BUCKET, 1); - if (Result.Success.RegulatorRules->Type == Regulator::LEAKY_BUCKET) - { - _stream.Write(Result.Success.RegulatorRules->LeakyBucket.Threshold, 32); - _stream.Write(Result.Success.RegulatorRules->LeakyBucket.Rate, 32); - } - } - } - else - { - _stream.Write(Result.Failure.Strings.is_initialized(), 1); - if (Result.Failure.Strings.is_initialized()) - { - _stream.WriteBytes(Result.Failure.Strings->Type.c_str(), 4); - _stream.WriteFourCC(Result.Failure.Strings->Region); - _stream.WriteBytes(Result.Failure.Strings->ModuleId, 32); - } - - _stream.Write(Result.Failure.Result.Type, 2); - if (Result.Failure.Result.Type == FailureType::FAILURE) - { - _stream.Write(Result.Failure.Result.Failure.Error, 16); - _stream.Write(Result.Failure.Result.Failure.Wait + std::numeric_limits<int32>::min(), 32); - } - } -} - -std::string Battlenet::Authentication::ResumeResponse::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::Authentication::ResumeResponse" << std::endl; - return stream.str(); -} - -void Battlenet::Authentication::ResumeResponse::SetAuthResult(AuthResult result) -{ - Result.Type = result != AUTH_OK ? ResultType::FAILURE : ResultType::SUCCESS; - Result.Failure.Result.Failure.Error = result; -} - -Battlenet::Authentication::ProofRequest::~ProofRequest() -{ - for (size_t i = 0; i < Modules.size(); ++i) - delete Modules[i]; -} - -void Battlenet::Authentication::ProofRequest::Write() -{ - _stream.Write(Modules.size(), 3); - for (ModuleInfo const* info : Modules) - { - _stream.WriteBytes(info->Handle.Type.c_str(), 4); - _stream.WriteFourCC(info->Handle.Region); - _stream.WriteBytes(info->Handle.ModuleId, 32); - _stream.Write(info->DataSize, 10); - _stream.WriteBytes(info->Data, info->DataSize); - } -} - -std::string Battlenet::Authentication::ProofRequest::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::Authentication::ProofRequest" << std::endl; - APPEND_FIELD(stream, Modules); - return stream.str(); -} diff --git a/src/server/bnetserver/Packets/AuthenticationPackets.h b/src/server/bnetserver/Packets/AuthenticationPackets.h deleted file mode 100644 index 9082585085d..00000000000 --- a/src/server/bnetserver/Packets/AuthenticationPackets.h +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef AuthenticationPackets_h__ -#define AuthenticationPackets_h__ - -#include "PacketsBase.h" -#include "ComponentManager.h" -#include "ModuleManager.h" - -namespace Battlenet -{ - namespace Authentication - { - enum Opcode - { - CMSG_LOGON_REQUEST = 0x0, // Deprecated - CMSG_RESUME_REQUEST = 0x1, - CMSG_PROOF_RESPONSE = 0x2, - CMSG_GENERATE_SINGLE_SIGN_ON_TOKEN_REQUEST_2 = 0x8, // Not implemented - CMSG_LOGON_REQUEST_3 = 0x9, - CMSG_SINGLE_SIGN_ON_REQUEST_3 = 0xA, // Not implemented - - SMSG_LOGON_RESPONSE = 0x0, - SMSG_RESUME_RESPONSE = 0x1, - SMSG_PROOF_REQUEST = 0x2, - SMSG_PATCH = 0x3, // Not implemented - SMSG_AUTHORIZED_LICENSES = 0x4, // Not implemented - SMSG_GENERATE_SINGLE_SIGN_ON_TOKEN_RESPONSE_2 = 0x8 // Not implemented - }; - - struct RequestCommon : public PrintableComponent - { - std::string Program; - std::string Platform; - std::string Locale; - std::vector<Version::Record> Versions; - - std::string ToString() const override; - }; - - class ResumeRequest final : public ClientPacket - { - public: - ResumeRequest(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) - { - ASSERT(header == PacketHeader(CMSG_RESUME_REQUEST, AUTHENTICATION) && "Invalid packet header for ResumeRequest"); - } - - void Read() override; - std::string ToString() const override; - void CallHandler(Session* session) override; - - RequestCommon Common; - std::string Account; - uint8 GameAccountRegion = 0; - std::string GameAccountName; - }; - - class ProofResponse final : public ClientPacket - { - public: - ProofResponse(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) - { - ASSERT(header == PacketHeader(CMSG_PROOF_RESPONSE, AUTHENTICATION) && "Invalid packet header for ProofResponse"); - } - - ~ProofResponse(); - - void Read() override; - std::string ToString() const override; - void CallHandler(Session* session) override; - - std::vector<BitStream*> Response; - }; - - class LogonRequest3 final : public ClientPacket - { - public: - LogonRequest3(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) - { - ASSERT(header == PacketHeader(CMSG_LOGON_REQUEST_3, AUTHENTICATION) && "Invalid packet header for LogonRequest3"); - } - - void Read() override; - std::string ToString() const override; - void CallHandler(Session* session) override; - - RequestCommon Common; - std::string Account; - uint64 Compatibility = 0; - }; - - struct FailureType : public PrintableComponent - { - Optional<Cache::Handle> Strings; - - enum - { - UPDATE = 0, - FAILURE = 1, - VERSION_CHECK_DISCONNECT = 2 - }; - - struct ResultType : public PrintableComponent - { - int32 Type = FAILURE; - - struct UpdateType : public PrintableComponent - { - std::string ToString() const override; - } Update; - - struct FailureType : public PrintableComponent - { - AuthResult Error = AUTH_OK; - int32 Wait = 0; - - std::string ToString() const override; - } Failure; - - struct VersionCheckDisconnectType : public PrintableComponent - { - std::string ToString() const override; - } VersionCheckDisconnect; - - std::string ToString() const override; - } Result; - - std::string ToString() const override; - }; - - struct Regulator : public PrintableComponent - { - enum - { - NONE = 0, - LEAKY_BUCKET = 1 - }; - - int32 Type = LEAKY_BUCKET; - struct NoneType : public PrintableComponent - { - std::string ToString() const override; - } None; - - struct LeakyBucketType : public PrintableComponent - { - uint32 Threshold = 25000000; - uint32 Rate = 1000; - - std::string ToString() const override; - } LeakyBucket; - - std::string ToString() const override; - }; - - class LogonResponse final : public ServerPacket - { - public: - LogonResponse() : ServerPacket(PacketHeader(SMSG_LOGON_RESPONSE, AUTHENTICATION)) - { - } - - ~LogonResponse(); - - void Write() override; - std::string ToString() const override; - void SetAuthResult(AuthResult result); - - struct ResultType : public PrintableComponent - { - enum - { - SUCCESS = 0, - FAILURE = 1 - }; - - int32 Type = SUCCESS; - struct SuccessType : public PrintableComponent - { - std::vector<ModuleInfo*> FinalRequest; - int32 PingTimeout = 120000; - Optional<Regulator> RegulatorRules; - Battlenet::Account::FullName FullName; - uint32 AccountId = 0; - uint8 Region = 2; - uint64 Flags = 0; - uint8 GameAccountRegion = 2; - std::string GameAccountName; - uint64 GameAccountFlags = 0; - uint32 LogonFailures = 0; - - std::string ToString() const override; - } Success; - - FailureType Failure; - - std::string ToString() const override; - } Result; - - Optional<std::vector<uint8>> Raf; - }; - - class ResumeResponse final : public ServerPacket - { - public: - ResumeResponse() : ServerPacket(PacketHeader(SMSG_RESUME_RESPONSE, AUTHENTICATION)) - { - } - - ~ResumeResponse(); - - void Write() override; - std::string ToString() const override; - - void SetAuthResult(AuthResult result); - - struct ResultType - { - enum - { - SUCCESS = 0, - FAILURE = 1 - }; - - int32 Type = SUCCESS; - struct SuccessType - { - std::vector<ModuleInfo*> FinalRequest; - int32 PingTimeout = 120000; - Optional<Regulator> RegulatorRules; - } Success; - - FailureType Failure; - } Result; - }; - - class ProofRequest final : public ServerPacket - { - public: - ProofRequest() : ServerPacket(PacketHeader(SMSG_PROOF_REQUEST, AUTHENTICATION)) { } - ~ProofRequest(); - - void Write() override; - std::string ToString() const override; - - std::vector<ModuleInfo*> Modules; - }; - } -} - -#endif // AuthenticationPackets_h__ diff --git a/src/server/bnetserver/Packets/BitStream.h b/src/server/bnetserver/Packets/BitStream.h deleted file mode 100644 index 0e91c930514..00000000000 --- a/src/server/bnetserver/Packets/BitStream.h +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef BitStream_h__ -#define BitStream_h__ - -#include "Common.h" -#include "ByteConverter.h" -#include "MessageBuffer.h" -#include <exception> -#include <vector> -#include <type_traits> -#include <memory> - -namespace Battlenet -{ - union FloatToInt - { - float AsFloat; - uint32 AsInt; - }; - - class BitStreamPositionException : public std::exception - { - static uint32 const MessageSize = 128; - - public: - BitStreamPositionException(bool read, uint32 operationSize, uint32 position, uint32 streamSize) - { - memset(_message, 0, MessageSize); - snprintf(_message, MessageSize, "Attempted to %s more bits (%u) %s stream than %s (%u)\n", - (read ? "read" : "write"), - operationSize + position, - (read ? "from" : "to"), - (read ? "exist" : "allowed"), - streamSize); - } - - char const* what() const throw() - { - return _message; - } - - private: - char _message[MessageSize]; - }; - - class BitStream - { - public: - static uint32 const MaxSize = 0x4000; - - // length : The maximum number of bytes to read - BitStream(uint32 length) : _writePos(length * 8), _readPos(0) - { - _buffer.resize(length, 0); - } - - BitStream(MessageBuffer&& buffer) : _writePos(uint32(buffer.GetActiveSize()) << 3), _readPos(0), _buffer(buffer.Move()) - { - } - - BitStream() : _writePos(0), _readPos(0) - { - _buffer.reserve(0x1000); - } - - void AlignToNextByte() - { - _readPos = (_readPos + 7) & ~7; - _writePos = (_writePos + 7) & ~7; - } - - std::string ReadString(uint32 bitCount, int32 baseLength = 0) - { - uint32 len = Read<uint32>(bitCount) + baseLength; - AlignToNextByte(); - std::string str(reinterpret_cast<char*>(&_buffer[_readPos >> 3]), len); - _readPos += len * 8; - return str; - } - - std::unique_ptr<uint8[]> ReadBytes(uint32 count) - { - AlignToNextByte(); - if (_readPos + count * 8 > _writePos) - throw BitStreamPositionException(true, count * 8, _readPos, _writePos); - - std::unique_ptr<uint8[]> buf(new uint8[count]); - memcpy(buf.get(), &_buffer[_readPos >> 3], count); - _readPos += count * 8; - return buf; - } - - float ReadFloat() - { - union - { - float AsFloat; - uint32 AsInt; - } convert; - - convert.AsInt = Read<uint32>(32); - return convert.AsFloat; - } - - std::string ReadFourCC() - { - uint32 fcc = Read<uint32>(32); - EndianConvertReverse(fcc); - size_t len = 4; - while (!(fcc & 0xFF) && len) - { - fcc >>= 8; - --len; - } - - return std::string(reinterpret_cast<char*>(&fcc), len); - } - - template<typename T> - T Read(uint32 bitCount) - { - static_assert(std::is_integral<T>::value || std::is_enum<T>::value, "T must be an integer type"); - - if (_readPos + bitCount > _writePos) - throw BitStreamPositionException(true, bitCount, _readPos, _writePos); - - uint64 ret = 0; - while (bitCount != 0) - { - uint32 bitPos = (_readPos & 7); - uint32 bitsLeftInByte = 8 - bitPos; - if (bitsLeftInByte >= bitCount) - bitsLeftInByte = bitCount; - - bitCount -= bitsLeftInByte; - ret |= (uint64)(_buffer[_readPos >> 3] >> bitPos & (uint32)((uint8)(1 << bitsLeftInByte) - 1)) << bitCount; - _readPos += bitsLeftInByte; - } - - return static_cast<T>(ret); - } - - void WriteString(std::string const& str, uint32 bitCount, int32 baseLength = 0) - { - Write(str.length() + baseLength, bitCount); - WriteBytes(str.c_str(), uint32(str.length())); - } - - template<typename T> - void WriteBytes(T* data, uint32 count) - { - AlignToNextByte(); - if (!count || !data) - return; - - if ((_writePos >> 3) + count > MaxSize) - throw BitStreamPositionException(false, count * 8, _writePos, MaxSize * 8); - - _buffer.resize(_buffer.size() + count); - memcpy(&_buffer[_writePos >> 3], data, count); - _writePos += count * 8; - } - - void WriteFloat(float value) - { - union - { - float AsFloat; - uint32 AsInt; - } convert; - - convert.AsFloat = value; - Write(convert.AsInt, 32); - } - - void WriteFourCC(std::string const& fcc) - { - uint32 intVal = *(uint32*)fcc.c_str(); - size_t len = fcc.length(); - EndianConvertReverse(intVal); - // Add padding - while (len++ < 4) - intVal >>= 8; - - Write(intVal, 32); - } - - template<typename T> - void Write(T value, uint32 bitCount) - { - static_assert(std::is_integral<T>::value || std::is_enum<T>::value, "T must be an integer type"); - - if (_writePos + bitCount > 8 * MaxSize) - throw BitStreamPositionException(false, bitCount, _writePos, MaxSize * 8); - - while (bitCount != 0) - { - uint32 bitPos = (_writePos & 7); - uint32 bitsLeftInByte = 8 - bitPos; - if (bitsLeftInByte >= bitCount) - bitsLeftInByte = bitCount; - - bitCount -= bitsLeftInByte; - - uint8 firstHalf = (uint8)(~(((uint8)(1 << bitsLeftInByte) - 1) << bitPos)); - uint8 secondHalf = (uint8)((((uint8)(1 << bitsLeftInByte) - 1) & (uint8)(value >> bitCount)) << bitPos); - - if (_buffer.size() > (_writePos >> 3)) - _buffer[_writePos >> 3] = (uint8)((_buffer[_writePos >> 3] & firstHalf) | secondHalf); - else - _buffer.push_back(secondHalf); - - _writePos += bitsLeftInByte; - } - } - - bool IsRead() const { return _readPos >= _writePos; } - - uint8* GetBuffer() { return _buffer.data(); } - uint8 const* GetBuffer() const { return _buffer.data(); } - - uint32 GetReadPos() const { return _readPos; } - size_t GetSize() const { return ((_writePos + 7) & ~7) / 8; } - - // These methods are meant to only be used when their corresponding actions in the client ignore the value completely - void ReadSkip(uint32 bitCount) { _readPos += bitCount; } - void WriteSkip(uint32 bitCount) { Write(0, bitCount); } - - private: - uint32 _writePos; - uint32 _readPos; - std::vector<uint8> _buffer; - }; - - template<> - bool BitStream::Read<bool>(uint32 bitCount); - - template<> - void BitStream::Write<bool>(bool value, uint32 bitCount); -} - -#endif // BitStream_h__ diff --git a/src/server/bnetserver/Packets/CachePackets.cpp b/src/server/bnetserver/Packets/CachePackets.cpp deleted file mode 100644 index ece7a9db08b..00000000000 --- a/src/server/bnetserver/Packets/CachePackets.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "Session.h" -#include "Util.h" -#include "CachePackets.h" - -void Battlenet::Cache::GetStreamItemsRequest::Read() -{ - _stream.ReadSkip(31); - Token = _stream.Read<uint32>(32); - ReferenceTime = _stream.Read<int32>(32) - std::numeric_limits<int32>::min(); - Direction = _stream.Read<uint8>(1); - MaxItems = _stream.Read<uint8>(6); - Locale = _stream.ReadFourCC(); - Stream.Type = _stream.Read<uint8>(1); - if (Stream.Type == StreamId::DESCRIPTION) - { - Stream.Description.ItemName = _stream.ReadFourCC(); - Stream.Description.Channel = _stream.ReadFourCC(); - } - else - Stream.Index = _stream.Read<uint16>(16); -} - -std::string Battlenet::Cache::GetStreamItemsRequest::StreamId::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::Cache::GetStreamItemsRequest::StreamId" << std::endl; - - if (Type == INDEX) - APPEND_FIELD(stream, Index); - else - APPEND_FIELD(stream, Description); - - return stream.str(); -} - -std::string Battlenet::Cache::GetStreamItemsRequest::StreamId::DescriptionType::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::Cache::GetStreamItemsRequest::StreamId::Description" << std::endl; - APPEND_FIELD(stream, Channel); - APPEND_FIELD(stream, ItemName); - return stream.str(); -} - -std::string Battlenet::Cache::GetStreamItemsRequest::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::Cache::GetStreamItemsRequest" << std::endl; - APPEND_FIELD(stream, Token); - APPEND_FIELD(stream, MaxItems); - APPEND_FIELD(stream, ReferenceTime); - APPEND_FIELD(stream, Direction); - APPEND_FIELD(stream, Stream); - APPEND_FIELD(stream, Locale); - return stream.str(); -} - -void Battlenet::Cache::GetStreamItemsRequest::CallHandler(Session* session) -{ - session->HandleGetStreamItemsRequest(*this); -} - -Battlenet::Cache::GetStreamItemsResponse::~GetStreamItemsResponse() -{ - for (size_t i = 0; i < Items.size(); ++i) - delete Items[i]; -} - -void Battlenet::Cache::GetStreamItemsResponse::Write() -{ - _stream.Write(Offset, 16); - _stream.Write(TotalNumItems, 16); - _stream.Write(Token, 32); - _stream.Write(Items.size(), 6); - for (ModuleInfo const* info : Items) - { - _stream.WriteBytes(info->Handle.Type.c_str(), 4); - _stream.WriteFourCC(info->Handle.Region); - _stream.WriteBytes(info->Handle.ModuleId, 32); - _stream.WriteSkip(27); - _stream.WriteBytes(info->Data, 4); - } -} - -std::string Battlenet::Cache::GetStreamItemsResponse::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::Cache::GetStreamItemsResponse" << std::endl; - APPEND_FIELD(stream, Items); - APPEND_FIELD(stream, Offset); - APPEND_FIELD(stream, TotalNumItems); - APPEND_FIELD(stream, Token); - return stream.str(); -} diff --git a/src/server/bnetserver/Packets/CachePackets.h b/src/server/bnetserver/Packets/CachePackets.h deleted file mode 100644 index 5cdd0905289..00000000000 --- a/src/server/bnetserver/Packets/CachePackets.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef CachePackets_h__ -#define CachePackets_h__ - -#include "ModuleManager.h" -#include "PacketsBase.h" - -namespace Battlenet -{ - namespace Cache - { - enum Opcode - { - CMSG_GATEWAY_LOOKUP_REQUEST = 0x2, // Not implemented - CMSG_CONNECT_REQUEST = 0x4, // Not implemented - CMSG_DATA_CHUNK = 0x7, // Not implemented - CMSG_GET_STREAM_ITEMS_REQUEST = 0x9, - - SMSG_GATEWAY_LOOKUP_RESPONSE = 0x3, // Not implemented - SMSG_CONNECT_RESPONSE = 0x4, // Not implemented - SMSG_PUBLISH_LIST_RESPONSE = 0x7, // Not implemented - SMSG_RESULT = 0x8, // Not implemented - SMSG_GET_STREAM_ITEMS_RESPONSE = 0x9 - }; - - class GetStreamItemsRequest final : public ClientPacket - { - public: - GetStreamItemsRequest(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) - { - ASSERT(header == PacketHeader(CMSG_GET_STREAM_ITEMS_REQUEST, CACHE) && "Invalid packet header for GetStreamItemsRequest"); - } - - void Read() override; - std::string ToString() const override; - void CallHandler(Session* session) override; - - enum - { - BEFORE = 0, - AFTER = 1 - }; - - uint32 Token = 0; - uint8 MaxItems = 0; - int32 ReferenceTime = 0; - uint8 Direction = BEFORE; - - struct StreamId : public PrintableComponent - { - enum - { - INDEX = 0, - DESCRIPTION = 1 - }; - - int32 Type; - - uint16 Index; - struct DescriptionType : public PrintableComponent - { - std::string Channel; - std::string ItemName; - - std::string ToString() const override; - } Description; - - std::string ToString() const override; - } Stream; - - std::string Locale; - }; - - class GetStreamItemsResponse final : public ServerPacket - { - public: - GetStreamItemsResponse() : ServerPacket(PacketHeader(SMSG_GET_STREAM_ITEMS_RESPONSE, CACHE)) - { - } - - ~GetStreamItemsResponse(); - - void Write() override; - std::string ToString() const override; - - std::vector<ModuleInfo*> Items; - uint16 Offset = 0; - uint16 TotalNumItems = 1; - uint32 Token = 0; - }; - } -} - -#endif // CachePackets_h__ diff --git a/src/server/bnetserver/Packets/ChatPackets.h b/src/server/bnetserver/Packets/ChatPackets.h deleted file mode 100644 index 3b1c5c155e0..00000000000 --- a/src/server/bnetserver/Packets/ChatPackets.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef ChatPackets_h__ -#define ChatPackets_h__ - -#include "PacketsBase.h" - -namespace Battlenet -{ - namespace Chat - { - enum Opcode - { - CMSG_JOIN_REQUEST_2 = 0x00, // Not implemented - CMSG_LEAVE_REQUEST = 0x02, // Not implemented - CMSG_INVITE_REQUEST = 0x03, // Not implemented - CMSG_CREATE_AND_INVITE_REQUEST = 0x0A, // Not implemented - CMSG_MESSAGE_SEND = 0x0B, // Not implemented - CMSG_DATAGRAM_CONNECTION_UPDATE = 0x0D, // Not implemented - CMSG_REPORT_SPAM_REQUEST = 0x0E, // Not implemented - CMSG_WHISPER_SEND = 0x13, // Not implemented - CMSG_ENUM_CATEGORY_DESCRIPTIONS = 0x15, // Not implemented - CMSG_ENUM_CONFERENCE_DESCRIPTIONS = 0x17, // Not implemented - CMSG_ENUM_CONFERENCE_MEMBER_COUNTS = 0x19, // Not implemented - CMSG_MODIFY_CHANNEL_LIST_REQUEST = 0x1B, // Deprecated in client - CMSG_GET_MEMBER_COUNT_REQUEST = 0x1F, // Not implemented - CMSG_MODIFY_CHANNEL_LIST_REQUEST_2 = 0x20, // Not implemented - CMSG_GAME_DATA_SEND_REQUEST = 0x22, // Not implemented - - SMSG_MEMBERSHIP_CHANGE_NOTIFY = 0x01, // Not implemented - SMSG_INVITE_NOTIFY = 0x04, // Not implemented - SMSG_INVITE_CANCELED = 0x07, // Not implemented - SMSG_MESSAGE_RECV = 0x0B, // Not implemented - SMSG_MESSAGE_UNDELIVERABLE = 0x0C, // Not implemented - SMSG_DATAGRAM_CONNECTION_UPDATE = 0x0D, // Not implemented - SMSG_INVITE_FAILURE = 0x0F, // Not implemented - SMSG_SYSTEM_MESSAGE = 0x10, // Not implemented - SMSG_MESSAGE_BLOCKED = 0x12, // Not implemented - SMSG_WHISPER_RECV = 0x13, // Not implemented - SMSG_WHISPER_UNDELIVERABLE = 0x14, // Not implemented - SMSG_CATEGORY_DESCRIPTIONS = 0x16, // Not implemented - SMSG_CONFERENCE_DESCRIPTIONS = 0x18, // Not implemented - SMSG_CONFERENCE_MEMBER_COUNTS = 0x1A, // Not implemented - SMSG_JOIN_NOTIFY_2 = 0x1B, // Not implemented - SMSG_MODIFY_CHANNEL_LIST_RESPONSE = 0x1C, // Deprecated in client - SMSG_CONFIG_CHANGED = 0x1D, // Not implemented - SMSG_WHISPER_ECHO_RECV = 0x1E, // Not implemented - SMSG_GET_MEMBER_COUNT_RESPONSE = 0x1F, // Not implemented - SMSG_MODIFY_CHANNEL_LIST_RESPONSE_2 = 0x21, // Not implemented - SMSG_GAME_DATA_SEND_RESPONSE = 0x23, // Not implemented - SMSG_GAME_DATA_RECV = 0x24 // Not implemented - }; - } -} - -#endif // ChatPackets_h__ diff --git a/src/server/bnetserver/Packets/ConnectionPackets.cpp b/src/server/bnetserver/Packets/ConnectionPackets.cpp deleted file mode 100644 index cdb438085f1..00000000000 --- a/src/server/bnetserver/Packets/ConnectionPackets.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "Session.h" -#include "ConnectionPackets.h" - -std::string Battlenet::Connection::Ping::ToString() const -{ - return "Battlenet::Connection::Ping"; -} - -void Battlenet::Connection::Ping::CallHandler(Session* session) -{ - session->HandlePing(*this); -} - -std::string Battlenet::Connection::EnableEncryption::ToString() const -{ - return "Battlenet::Connection::EnableEncryption"; -} - -void Battlenet::Connection::EnableEncryption::CallHandler(Session* session) -{ - session->HandleEnableEncryption(*this); -} - -std::string Battlenet::Connection::LogoutRequest::ToString() const -{ - return "Battlenet::Connection::LogoutRequest"; -} - -void Battlenet::Connection::LogoutRequest::CallHandler(Session* session) -{ - session->HandleLogoutRequest(*this); -} - -void Battlenet::Connection::DisconnectRequest::Read() -{ - Error = _stream.Read<uint16>(16); - Timeout = _stream.Read<uint32>(32); -} - -std::string Battlenet::Connection::DisconnectRequest::ToString() const -{ - std::ostringstream str; - str << "Battlenet::Connection::DisconnectRequest" << std::endl; - APPEND_FIELD(str, Error); - APPEND_FIELD(str, Timeout); - return str.str(); -} - -void Battlenet::Connection::ConnectionClosing::Read() -{ - Packets.resize(_stream.Read<uint8>(6)); - for (size_t i = 0; i < Packets.size(); ++i) - { - PacketInfo& info = Packets[i]; - info.Command = _stream.ReadFourCC(); - info.Time = _stream.Read<uint32>(32); - info.Size = _stream.Read<uint32>(16); - info.Layer = _stream.ReadFourCC(); - info.Offset = _stream.Read<uint32>(16); - } - - Reason = _stream.Read<ClosingReason>(4); - _stream.ReadBytes(_stream.Read<uint8>(8)); // BadData - - if (_stream.Read<bool>(1)) // HasHeader - { - Header.Command = _stream.Read<uint32>(6); - if (_stream.Read<bool>(1)) - Header.Channel = _stream.Read<int32>(4); - } - - Now = _stream.Read<time_t>(32); -} - -std::string Battlenet::Connection::ConnectionClosing::PacketInfo::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::Connection::ConnectionClosing::PacketInfo" << std::endl; - APPEND_FIELD(stream, Layer); - APPEND_FIELD(stream, Command); - APPEND_FIELD(stream, Offset); - APPEND_FIELD(stream, Size); - APPEND_FIELD(stream, Time); - return stream.str(); -} - -std::string Battlenet::Connection::ConnectionClosing::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::Connection::ConnectionClosing" << std::endl; - APPEND_FIELD(stream, Header); - APPEND_FIELD(stream, Reason); - APPEND_FIELD(stream, Packets); - APPEND_FIELD(stream, Now); - return stream.str(); -} - -void Battlenet::Connection::ConnectionClosing::CallHandler(Session* session) -{ - session->HandleConnectionClosing(*this); -} - -std::string Battlenet::Connection::Pong::ToString() const -{ - return "Battlenet::Connection::Pong"; -} diff --git a/src/server/bnetserver/Packets/ConnectionPackets.h b/src/server/bnetserver/Packets/ConnectionPackets.h deleted file mode 100644 index 9987c65d770..00000000000 --- a/src/server/bnetserver/Packets/ConnectionPackets.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef ConnectionPackets_h__ -#define ConnectionPackets_h__ - -#include "PacketsBase.h" - -namespace Battlenet -{ - namespace Connection - { - enum Opcode - { - CMSG_PING = 0x0, - CMSG_ENABLE_ENCRYPTION = 0x5, - CMSG_LOGOUT_REQUEST = 0x6, - CMSG_DISCONNECT_REQUEST = 0x7, // Not handled - CMSG_CONNECTION_CLOSING = 0x9, - - SMSG_PONG = 0x0, - SMSG_BOOM = 0x1, // Not implemented - SMSG_REGULATOR_UPDATE = 0x2, // Not implemented - SMSG_SERVER_VERSION = 0x3, // Not implemented - SMSG_STUN_SERVERS = 0x4 // Not implemented - }; - - class Ping final : public ClientPacket - { - public: - Ping(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) - { - ASSERT(header == PacketHeader(CMSG_PING, CONNECTION) && "Invalid packet header for Ping"); - } - - void Read() override { } - std::string ToString() const override; - void CallHandler(Session* session) override; - }; - - class EnableEncryption final : public ClientPacket - { - public: - EnableEncryption(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) - { - ASSERT(header == PacketHeader(CMSG_ENABLE_ENCRYPTION, CONNECTION) && "Invalid packet header for EnableEncryption"); - } - - void Read() override { } - std::string ToString() const override; - void CallHandler(Session* session) override; - uint8* GetRemainingData() { return _stream.GetBuffer() + (((_stream.GetReadPos() + 7) & ~7) / 8); } - size_t GetRemainingSize() const { return _stream.GetSize() - (((_stream.GetReadPos() + 7) & ~7) / 8); } - }; - - class LogoutRequest final : public ClientPacket - { - public: - LogoutRequest(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) - { - ASSERT(header == PacketHeader(CMSG_LOGOUT_REQUEST, CONNECTION) && "Invalid packet header for LogoutRequest"); - } - - void Read() override { } - std::string ToString() const override; - void CallHandler(Session* session) override; - }; - - class DisconnectRequest final : public ClientPacket - { - public: - DisconnectRequest(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) - { - ASSERT(header == PacketHeader(CMSG_DISCONNECT_REQUEST, CONNECTION) && "Invalid packet header for DisconnectRequest"); - } - - void Read() override; - std::string ToString() const override; - - uint16 Error = 0; - uint32 Timeout = 0; - }; - - class ConnectionClosing final : public ClientPacket - { - public: - enum ClosingReason - { - PACKET_TOO_LARGE = 1, - PACKET_CORRUPT = 2, - PACKET_INVALID = 3, - PACKET_INCORRECT = 4, - HEADER_CORRUPT = 5, - HEADER_IGNORED = 6, - HEADER_INCORRECT = 7, - PACKET_REJECTED = 8, - CHANNEL_UNHANDLED = 9, - COMMAND_UNHANDLED = 10, - COMMAND_BAD_PERMISSIONS = 11, - DIRECT_CALL = 12, - TIMEOUT = 13, - }; - - struct PacketInfo : public PrintableComponent - { - std::string Layer; - std::string Command; - uint16 Offset; - uint16 Size; - uint32 Time; - - std::string ToString() const override; - }; - - ConnectionClosing(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) - { - ASSERT(header == PacketHeader(CMSG_CONNECTION_CLOSING, CONNECTION) && "Invalid packet header for ConnectionClosing"); - } - - void Read() override; - std::string ToString() const override; - void CallHandler(Session* session) override; - - PacketHeader Header; - ClosingReason Reason = PACKET_CORRUPT; - std::vector<PacketInfo> Packets; - time_t Now = 0; - }; - - class Pong final : public ServerPacket - { - public: - Pong() : ServerPacket(PacketHeader(SMSG_PONG, CONNECTION)) - { - } - - void Write() override { } - std::string ToString() const override; - }; - } -} - -#endif // ConnectionPackets_h__ diff --git a/src/server/bnetserver/Packets/FriendsPackets.cpp b/src/server/bnetserver/Packets/FriendsPackets.cpp deleted file mode 100644 index 90a124fb915..00000000000 --- a/src/server/bnetserver/Packets/FriendsPackets.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "FriendsPackets.h" - -void Battlenet::Friends::SendInvitationRequest::Read() -{ - Token = _stream.Read<uint32>(32); - - if (_stream.Read<bool>(1)) - PresenceId = _stream.Read<uint32>(32); - - if (_stream.Read<bool>(1)) - AccountMail = _stream.ReadString(9, 3); - - if (_stream.Read<bool>(1)) - AccountId = _stream.Read<uint32>(32); - - if (_stream.Read<bool>(1)) - { - GameAccount = boost::in_place(); - GameAccount->Region = _stream.Read<uint8>(8); - GameAccount->ProgramId = _stream.ReadFourCC(); - GameAccount->Id = _stream.Read<uint32>(32); - } - - _stream.ReadSkip(7); - - if (_stream.Read<bool>(1)) - Nickname = _stream.ReadString(7); - - Source = _stream.ReadFourCC(); - Role = _stream.Read<uint32>(32); - - if (_stream.Read<bool>(1)) - InvitationMsg = _stream.ReadString(9); -} - -std::string Battlenet::Friends::SendInvitationRequest::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::Friends::SendInvitationRequest" << std::endl; - APPEND_FIELD(stream, Token); - APPEND_FIELD(stream, PresenceId); - APPEND_FIELD(stream, GameAccount); - APPEND_FIELD(stream, AccountId); - APPEND_FIELD(stream, AccountMail); - APPEND_FIELD(stream, Nickname); - APPEND_FIELD(stream, InvitationMsg); - APPEND_FIELD(stream, Source); - APPEND_FIELD(stream, Role); - return stream.str(); -} - -void Battlenet::Friends::SendInvitationRequest::CallHandler(Session* /*session*/) -{ -} diff --git a/src/server/bnetserver/Packets/FriendsPackets.h b/src/server/bnetserver/Packets/FriendsPackets.h deleted file mode 100644 index 8f1f513f521..00000000000 --- a/src/server/bnetserver/Packets/FriendsPackets.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef FriendsPackets_h__ -#define FriendsPackets_h__ - -#include "PacketsBase.h" - -namespace Battlenet -{ - namespace Friends - { - enum Opcode - { - CMSG_FRIEND_INVITE = 0x01, // Not implemented - CMSG_FRIEND_INVITE_RESPONSE = 0x02, // Not implemented - CMSG_FRIEND_REMOVE = 0x04, // Not implemented - CMSG_FRIEND_NOTE = 0x05, // Not implemented - CMSG_TOONS_OF_FRIEND_REQUEST = 0x06, // Not implemented - CMSG_BLOCK_ADD = 0x08, // Not implemented - CMSG_BLOCK_REMOVE = 0x0A, // Not implemented - CMSG_GET_FRIENDS_OF_FRIEND = 0x0B, // Not implemented - CMSG_GET_SOCIAL_NETWORK_FRIENDS = 0x0D, // Deprecated in client - CMSG_SOCIAL_NETWORK_CONNECT = 0x0F, // Deprecated in client - CMSG_SOCIAL_NETWORK_DISCONNECT = 0x11, // Deprecated in client - CMSG_SOCIAL_NETWORK_CHECK_CONNECTED = 0x13, // Deprecated in client - CMSG_REALID_FRIEND_INVITE = 0x16, // Deprecated in client - CMSG_SEND_INVITATION_REQUEST = 0x1A, // Not implemented - - SMSG_FRIEND_INVITE_NOTIFY = 0x01, // Not implemented - SMSG_FRIEND_INVITE_RESULT = 0x03, // Not implemented - SMSG_TOONS_OF_FRIEND_NOTIFY = 0x06, // Not implemented - SMSG_BLOCK_INVITE_NOTIFY = 0x07, // Deprecated in client - SMSG_BLOCK_ADD_FAILURE = 0x09, // Not implemented - SMSG_FRIENDS_OF_FRIEND = 0x0C, // Deprecated in client - SMSG_SOCIAL_NETWORK_FRIENDS = 0x0E, // Deprecated in client - SMSG_SOCIAL_NETWORK_CONNECT_RESULT = 0x10, // Deprecated in client - SMSG_SOCIAL_NETWORK_DISCONNECT_RESULT = 0x12, // Deprecated in client - SMSG_SOCIAL_NETWORK_CHECK_CONNECTED_RESULT = 0x14, // Deprecated in client - SMSG_MAX_FRIENDS_NOTIFY = 0x15, // Not implemented - SMSG_FRIENDS_LIST_NOTIFY_3 = 0x18, // Deprecated in client - SMSG_SEND_INVITATION_RESULT = 0x1B, // Not implemented - SMSG_FRIEND_INVITATION_ADDED_NOTIFY = 0x1C, // Not implemented - SMSG_FRIEND_INVITATION_REMOVED_NOTIFY = 0x1D, // Not implemented - SMSG_FRIENDS_LIST_NOTIFY_5 = 0x1E, // Not implemented - SMSG_ACCOUNT_BLOCK_ADDED_NOTIFY = 0x1F, // Not implemented - SMSG_ACCOUNT_BLOCK_REMOVED_NOTIFY = 0x20, // Not implemented - SMSG_TOON_BLOCK_NOTIFY = 0x21, // Not implemented - SMSG_FRIENDS_OF_FRIEND_RESULT = 0x22 // Not implemented - }; - - class SendInvitationRequest final : public ClientPacket - { - public: - SendInvitationRequest(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) { } - - void Read() override; - std::string ToString() const override; - void CallHandler(Session* session) override; - - uint32 Token = 0; - - Optional<uint32> PresenceId; - Optional<GameAccount::Handle> GameAccount; - Optional<uint32> AccountId; - Optional<std::string> AccountMail; - Optional<std::string> Nickname; - - Optional<std::string> InvitationMsg; - std::string Source; - uint32 Role = 0; - }; - } -} - -#endif // FriendsPackets_h__ diff --git a/src/server/bnetserver/Packets/PacketManager.cpp b/src/server/bnetserver/Packets/PacketManager.cpp deleted file mode 100644 index 588ca1a0a86..00000000000 --- a/src/server/bnetserver/Packets/PacketManager.cpp +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "PacketManager.h" - -Battlenet::ClientPacket* Battlenet::PacketManager::CreateClientPacket(PacketHeader const& header, BitStream& stream) -{ - auto packetInfo = _clientPacketTable.find(header); - if (packetInfo == _clientPacketTable.end()) - return nullptr; - - if (!packetInfo->second.Constructor) - return nullptr; - - ClientPacket* packet = packetInfo->second.Constructor(header, stream); - packet->Read(); - return packet; -} - -char const* Battlenet::PacketManager::GetClientPacketName(PacketHeader const& header) -{ - auto packetInfo = _clientPacketTable.find(header); - if (packetInfo == _clientPacketTable.end()) - return nullptr; - - return packetInfo->second.Name; -} - -char const* Battlenet::PacketManager::GetServerPacketName(PacketHeader const& header) -{ - auto packetInfo = _serverPacketTable.find(header); - if (packetInfo == _serverPacketTable.end()) - return nullptr; - - return packetInfo->second.Name; -} - -bool Battlenet::PacketManager::IsHandled(PacketHeader const& header) -{ - auto packetInfo = _clientPacketTable.find(header); - if (packetInfo == _clientPacketTable.end()) - return false; - - return packetInfo->second.HasHandler; -} - -Battlenet::PacketManager::PacketManager() -{ - RegisterAuthenticationPackets(); - RegisterConnectionPackets(); - RegisterWoWRealmPackets(); - RegisterFriendsPackets(); - RegisterPresencePackets(); - RegisterChatPackets(); - RegisterSupportPackets(); - RegisterCachePackets(); - RegisterAchievementPackets(); - RegisterProfilePackets(); -} - -#define REGISTER_CLIENT_PACKET(header, packetClass) RegisterClientPacket<packetClass>(header, #packetClass) -#define REGISTER_SERVER_PACKET(header, packetClass) RegisterPacketName(_serverPacketTable, header, #packetClass) -#define REGISTER_CLIENT_PACKET_NAME(header, name) RegisterPacketName(_clientPacketTable, header, name) -#define REGISTER_SERVER_PACKET_NAME(header, name) RegisterPacketName(_serverPacketTable, header, name) - -void Battlenet::PacketManager::RegisterAuthenticationPackets() -{ - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Authentication::CMSG_LOGON_REQUEST, AUTHENTICATION), "Authentication::LogonRequest"); - REGISTER_CLIENT_PACKET(PacketHeader(Authentication::CMSG_RESUME_REQUEST, AUTHENTICATION), Authentication::ResumeRequest); - REGISTER_CLIENT_PACKET(PacketHeader(Authentication::CMSG_PROOF_RESPONSE, AUTHENTICATION), Authentication::ProofResponse); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Authentication::CMSG_GENERATE_SINGLE_SIGN_ON_TOKEN_REQUEST_2, AUTHENTICATION), "Authentication::GenerateSingleSignOnTokenRequest2"); - REGISTER_CLIENT_PACKET(PacketHeader(Authentication::CMSG_LOGON_REQUEST_3, AUTHENTICATION), Authentication::LogonRequest3); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Authentication::CMSG_SINGLE_SIGN_ON_REQUEST_3, AUTHENTICATION), "Authentication::SingleSignOnRequest3"); - - REGISTER_SERVER_PACKET(PacketHeader(Authentication::SMSG_LOGON_RESPONSE, AUTHENTICATION), Authentication::LogonResponse); - REGISTER_SERVER_PACKET(PacketHeader(Authentication::SMSG_RESUME_RESPONSE, AUTHENTICATION), Authentication::ResumeResponse); - REGISTER_SERVER_PACKET(PacketHeader(Authentication::SMSG_PROOF_REQUEST, AUTHENTICATION), Authentication::ProofRequest); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Authentication::SMSG_PATCH, AUTHENTICATION), "Authentication::Patch"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Authentication::SMSG_AUTHORIZED_LICENSES, AUTHENTICATION), "Authentication::AuthorizedLicenses"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Authentication::SMSG_GENERATE_SINGLE_SIGN_ON_TOKEN_RESPONSE_2, AUTHENTICATION), "Authentication::GenerateSingleSignOnTokenResponse2"); -} - -void Battlenet::PacketManager::RegisterConnectionPackets() -{ - REGISTER_CLIENT_PACKET(PacketHeader(Connection::CMSG_PING, CONNECTION), Connection::Ping); - REGISTER_CLIENT_PACKET(PacketHeader(Connection::CMSG_ENABLE_ENCRYPTION, CONNECTION), Connection::EnableEncryption); - REGISTER_CLIENT_PACKET(PacketHeader(Connection::CMSG_LOGOUT_REQUEST, CONNECTION), Connection::LogoutRequest); - REGISTER_CLIENT_PACKET(PacketHeader(Connection::CMSG_DISCONNECT_REQUEST, CONNECTION), Connection::DisconnectRequest); - REGISTER_CLIENT_PACKET(PacketHeader(Connection::CMSG_CONNECTION_CLOSING, CONNECTION), Connection::ConnectionClosing); - - REGISTER_SERVER_PACKET(PacketHeader(Connection::SMSG_PONG, CONNECTION), Connection::Pong); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Connection::SMSG_BOOM, CONNECTION), "Connection::Boom"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Connection::SMSG_REGULATOR_UPDATE, CONNECTION), "Connection::RegulatorUpdate"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Connection::SMSG_SERVER_VERSION, CONNECTION), "Connection::ServerVersion"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Connection::SMSG_STUN_SERVERS, CONNECTION), "Connection::STUNServers"); -} - -void Battlenet::PacketManager::RegisterWoWRealmPackets() -{ - REGISTER_CLIENT_PACKET(PacketHeader(WoWRealm::CMSG_LIST_SUBSCRIBE_REQUEST, WOWREALM), WoWRealm::ListSubscribeRequest); - REGISTER_CLIENT_PACKET(PacketHeader(WoWRealm::CMSG_LIST_UNSUBSCRIBE, WOWREALM), WoWRealm::ListUnsubscribe); - REGISTER_CLIENT_PACKET(PacketHeader(WoWRealm::CMSG_JOIN_REQUEST_V2, WOWREALM), WoWRealm::JoinRequestV2); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(WoWRealm::CMSG_MULTI_LOGON_REQUEST_V2, WOWREALM), "WoWRealm::MultiLogonRequestV2"); - - REGISTER_SERVER_PACKET(PacketHeader(WoWRealm::SMSG_LIST_SUBSCRIBE_RESPONSE, WOWREALM), WoWRealm::ListSubscribeResponse); - REGISTER_SERVER_PACKET(PacketHeader(WoWRealm::SMSG_LIST_UPDATE, WOWREALM), WoWRealm::ListUpdate); - REGISTER_SERVER_PACKET(PacketHeader(WoWRealm::SMSG_LIST_COMPLETE, WOWREALM), WoWRealm::ListComplete); - REGISTER_SERVER_PACKET(PacketHeader(WoWRealm::SMSG_TOON_READY, WOWREALM), WoWRealm::ToonReady); - REGISTER_SERVER_PACKET(PacketHeader(WoWRealm::SMSG_TOON_LOGGED_OUT, WOWREALM), WoWRealm::ToonLoggedOut); - REGISTER_SERVER_PACKET(PacketHeader(WoWRealm::SMSG_JOIN_RESPONSE_V2, WOWREALM), WoWRealm::JoinResponseV2); -} - -void Battlenet::PacketManager::RegisterFriendsPackets() -{ - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_FRIEND_INVITE, FRIENDS), "Friends::FriendInvite"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_FRIEND_INVITE_RESPONSE, FRIENDS), "Friends::FriendInviteResponse"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_FRIEND_REMOVE, FRIENDS), "Friends::FriendRemove"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_FRIEND_NOTE, FRIENDS), "Friends::FriendNote"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_TOONS_OF_FRIEND_REQUEST, FRIENDS), "Friends::ToonsOfFriendRequest"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_BLOCK_ADD, FRIENDS), "Friends::BlockAdd"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_BLOCK_REMOVE, FRIENDS), "Friends::BlockRemove"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_GET_FRIENDS_OF_FRIEND, FRIENDS), "Friends::GetFriendsOfFriend"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_GET_SOCIAL_NETWORK_FRIENDS, FRIENDS), "Friends::GetSocialNetworkFriends"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_SOCIAL_NETWORK_CONNECT, FRIENDS), "Friends::SocialNetworkConnect"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_SOCIAL_NETWORK_DISCONNECT, FRIENDS), "Friends::SocialNetworkDisconnect"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_SOCIAL_NETWORK_CHECK_CONNECTED, FRIENDS), "Friends::SocialNetworkCheckConnected"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Friends::CMSG_REALID_FRIEND_INVITE, FRIENDS), "Friends::RealIdFriendInvite"); - REGISTER_CLIENT_PACKET(PacketHeader(Friends::CMSG_SEND_INVITATION_REQUEST, FRIENDS), Friends::SendInvitationRequest); - - REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_FRIEND_INVITE_NOTIFY, FRIENDS), "Friends::FriendInviteNotify"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_FRIEND_INVITE_RESULT, FRIENDS), "Friends::FriendInviteResult"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_TOONS_OF_FRIEND_NOTIFY, FRIENDS), "Friends::ToonsOfFriendNotify"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_BLOCK_INVITE_NOTIFY, FRIENDS), "Friends::BlockInviteNotify"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_BLOCK_ADD_FAILURE, FRIENDS), "Friends::BlockAddFailure"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_FRIENDS_OF_FRIEND, FRIENDS), "Friends::FriendsOfFriend"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_SOCIAL_NETWORK_FRIENDS, FRIENDS), "Friends::SocialNetworkFriends"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_SOCIAL_NETWORK_CONNECT_RESULT, FRIENDS), "Friends::SocialNetworkConnectResult"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_SOCIAL_NETWORK_DISCONNECT_RESULT, FRIENDS), "Friends::SocialNetworkDisconnectResult"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_SOCIAL_NETWORK_CHECK_CONNECTED_RESULT, FRIENDS), "Friends::SocialNetworkCheckConnectedResult"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_MAX_FRIENDS_NOTIFY, FRIENDS), "Friends::MaxFriendsNotify"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_FRIENDS_LIST_NOTIFY_3, FRIENDS), "Friends::FriendsListNotify3"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_SEND_INVITATION_RESULT, FRIENDS), "SendInvitationResult"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_FRIEND_INVITATION_ADDED_NOTIFY, FRIENDS), "Friends::FriendInvitationAddedNotify"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_FRIEND_INVITATION_REMOVED_NOTIFY, FRIENDS), "Friends::FriendInvitationRemovedNotify"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_FRIENDS_LIST_NOTIFY_5, FRIENDS), "Friends::FriendsListNotify5"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_ACCOUNT_BLOCK_ADDED_NOTIFY, FRIENDS), "Friends::AccountBlockAddedNotify"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_ACCOUNT_BLOCK_REMOVED_NOTIFY, FRIENDS), "Friends::AccountBlockRemovedNotify"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_TOON_BLOCK_NOTIFY, FRIENDS), "Friends::ToonBlockNotify"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Friends::SMSG_FRIENDS_OF_FRIEND_RESULT, FRIENDS), "Friends::FriendsOfFriendResult"); -} - -void Battlenet::PacketManager::RegisterPresencePackets() -{ - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Presence::CMSG_UPDATE_REQUEST, PRESENCE), "Presence::UpdateRequest"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Presence::CMSG_STATISTIC_SUBSCRIBE, PRESENCE), "Presence::StatisticSubscribe"); - - REGISTER_SERVER_PACKET_NAME(PacketHeader(Presence::SMSG_UPDATE_NOTIFY, PRESENCE), "Presence::UpdateNotify"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Presence::SMSG_FIELD_SPEC_ANNOUNCE, PRESENCE), "Presence::FieldSpecAnnounce"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Presence::SMSG_STATISTICS_UPDATE, PRESENCE), "Presence::StatisticsUpdate"); -} - -void Battlenet::PacketManager::RegisterChatPackets() -{ - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_JOIN_REQUEST_2, CHAT), "Chat::JoinRequest2"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_LEAVE_REQUEST, CHAT), "Chat::LeaveRequest"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_INVITE_REQUEST, CHAT), "Chat::InviteRequest"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_CREATE_AND_INVITE_REQUEST, CHAT), "Chat::CreateAndInviteRequest"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_MESSAGE_SEND, CHAT), "Chat::MessageSend"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_DATAGRAM_CONNECTION_UPDATE, CHAT), "Chat::DatagramConnectionUpdate"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_REPORT_SPAM_REQUEST, CHAT), "Chat::ReportSpamRequest"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_WHISPER_SEND, CHAT), "Chat::WhisperSend"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_ENUM_CATEGORY_DESCRIPTIONS, CHAT), "Chat::EnumCategoryDescriptions"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_ENUM_CONFERENCE_DESCRIPTIONS, CHAT), "Chat::EnumConferenceDescriptions"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_ENUM_CONFERENCE_MEMBER_COUNTS, CHAT), "Chat::EnumConferenceMemberCounts"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_MODIFY_CHANNEL_LIST_REQUEST, CHAT), "Chat::ModifyChannelListRequest"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_GET_MEMBER_COUNT_REQUEST, CHAT), "Chat::GetMemberCountRequest"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_MODIFY_CHANNEL_LIST_REQUEST_2, CHAT), "Chat::ModifyChannelListRequest2"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Chat::CMSG_GAME_DATA_SEND_REQUEST, CHAT), "Chat::GameDataSendRequest"); - - REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_MEMBERSHIP_CHANGE_NOTIFY, CHAT), "Chat::MembershipChangeNotify"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_INVITE_NOTIFY, CHAT), "Chat::InviteNotify"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_INVITE_CANCELED, CHAT), "Chat::InviteCanceled"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_MESSAGE_RECV, CHAT), "Chat::MessageRecv"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_MESSAGE_UNDELIVERABLE, CHAT), "Chat::MessageUndeliverable"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_DATAGRAM_CONNECTION_UPDATE, CHAT), "Chat::DatagramConnectionUpdate"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_INVITE_FAILURE, CHAT), "Chat::InviteFailed"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_SYSTEM_MESSAGE, CHAT), "Chat::SystemMessage"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_MESSAGE_BLOCKED, CHAT), "Chat::MessageBlocked"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_WHISPER_RECV, CHAT), "Chat::WhisperRecv"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_WHISPER_UNDELIVERABLE, CHAT), "Chat::WhisperUndeliverable"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_CATEGORY_DESCRIPTIONS, CHAT), "Chat::CategoryDescriptions"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_CONFERENCE_DESCRIPTIONS, CHAT), "Chat::ConferenceDescriptions"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_CONFERENCE_MEMBER_COUNTS, CHAT), "Chat::ConferenceMemberCounts"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_JOIN_NOTIFY_2, CHAT), "Chat::JoinNotify2"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_MODIFY_CHANNEL_LIST_RESPONSE, CHAT), "Chat::ModifyChannelListResponse"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_CONFIG_CHANGED, CHAT), "Chat::ConfigChanged"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_WHISPER_ECHO_RECV, CHAT), "Chat::WhisperEchoRecv"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_GET_MEMBER_COUNT_RESPONSE, CHAT), "Chat::GetMemberCountResponse"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_MODIFY_CHANNEL_LIST_RESPONSE_2, CHAT), "Chat::ModifyChannelListResponse2"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_GAME_DATA_SEND_RESPONSE, CHAT), "Chat::GameDataSendResponse"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Chat::SMSG_GAME_DATA_RECV, CHAT), "Chat::GameDataRecv"); -} - -void Battlenet::PacketManager::RegisterSupportPackets() -{ - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Support::CMSG_COMPLAINT_REQUEST, SUPPORT), "Support::ComplaintRequest"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Support::CMSG_COMPLAINT_REQUEST_2, SUPPORT), "Support::ComplaintRequest2"); -} - -void Battlenet::PacketManager::RegisterAchievementPackets() -{ - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Achievement::CMSG_LISTEN_REQUEST, ACHIEVEMENT), "Achievement::ListenRequest"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Achievement::CMSG_CRITERIA_FLUSH_REQUEST, ACHIEVEMENT), "Achievement::CriteriaFlushRequest"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Achievement::CMSG_CHANGE_TROPHY_CASE_REQUEST, ACHIEVEMENT), "Achievement::ChangeTrophyCaseRequest"); - - REGISTER_SERVER_PACKET_NAME(PacketHeader(Achievement::SMSG_DATA, ACHIEVEMENT), "Achievement::Data"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Achievement::SMSG_CRITERIA_FLUSH_RESPONSE, ACHIEVEMENT), "Achievement::CriteriaFlushResponse"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Achievement::SMSG_ACHIEVEMENT_HANDLE_UPDATE, ACHIEVEMENT), "Achievement::AchievementHandleUpdate"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Achievement::SMSG_CHANGE_TROPHY_CASE_RESULT, ACHIEVEMENT), "Achievement::ChangeTrophyCaseResult"); -} - -void Battlenet::PacketManager::RegisterCachePackets() -{ - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Cache::CMSG_GATEWAY_LOOKUP_REQUEST, CACHE), "Cache::GatewayLookupRequest"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Cache::CMSG_CONNECT_REQUEST, CACHE), "Cache::ConnectRequest"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Cache::CMSG_DATA_CHUNK, CACHE), "Cache::DataChunk"); - REGISTER_CLIENT_PACKET(PacketHeader(Cache::CMSG_GET_STREAM_ITEMS_REQUEST, CACHE), Cache::GetStreamItemsRequest); - - REGISTER_SERVER_PACKET_NAME(PacketHeader(Cache::SMSG_GATEWAY_LOOKUP_RESPONSE, CACHE), "Cache::GatewayLookupResponse"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Cache::SMSG_CONNECT_RESPONSE, CACHE), "Cache::ConnectResponse"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Cache::SMSG_PUBLISH_LIST_RESPONSE, CACHE), "Cache::PublishListResponse"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Cache::SMSG_RESULT, CACHE), "Cache::Result"); - REGISTER_SERVER_PACKET(PacketHeader(Cache::SMSG_GET_STREAM_ITEMS_RESPONSE, CACHE), Cache::GetStreamItemsResponse); -} - -void Battlenet::PacketManager::RegisterProfilePackets() -{ - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Profile::CMSG_READ_REQUEST, PROFILE), "Profile::ReadRequest"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Profile::CMSG_ADDRESS_QUERY_REQUEST, PROFILE), "Profile::AddressQueryRequest"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Profile::CMSG_RESOLVE_TOON_HANDLE_TO_NAME_REQUEST, PROFILE), "Profile::ResolveHandleToToonNameRequest"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Profile::CMSG_RESOLVE_TOON_NAME_TO_HANDLE_REQUEST, PROFILE), "Profile::ResolveToonNameToHandleRequest"); - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Profile::CMSG_CHANGE_SETTINGS, PROFILE), "Profile::ChangeSettings"); - - REGISTER_SERVER_PACKET_NAME(PacketHeader(Profile::SMSG_READ_RESPONSE, PROFILE), "Profile::ReadResponse"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Profile::SMSG_ADDRESS_QUERY_RESPONSE, PROFILE), "Profile::AddressQueryResponse"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Profile::SMSG_RESOLVE_TOON_HANDLE_TO_NAME_RESPONSE, PROFILE), "Profile::ResolveHandleToToonNameResponse"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Profile::SMSG_RESOLVE_TOON_NAME_TO_HANDLE_RESPONSE, PROFILE), "Profile::ResolveToonNameToHandleResponse"); - REGISTER_SERVER_PACKET_NAME(PacketHeader(Profile::SMSG_SETTINGS_AVAILABLE, PROFILE), "Profile::SettingsAvailable"); -} diff --git a/src/server/bnetserver/Packets/PacketManager.h b/src/server/bnetserver/Packets/PacketManager.h deleted file mode 100644 index 50fcaaa0d05..00000000000 --- a/src/server/bnetserver/Packets/PacketManager.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef PacketManager_h__ -#define PacketManager_h__ - -#include "Packets.h" -#include <map> -#include <type_traits> - -template<typename T> -struct has_call_handler -{ - template<typename U, void(U::*)(Battlenet::Session*)> struct test_has_call_handler { }; - template<typename U> static char Test(test_has_call_handler<U, &U::CallHandler>*); - template<typename U> static int Test(...); - static const bool value = sizeof(Test<T>(nullptr)) == sizeof(char); -}; - -namespace Battlenet -{ - class PacketManager - { - typedef ClientPacket*(*PacketCreateFn)(PacketHeader const& header, BitStream& stream); - - struct PacketInfo - { - PacketCreateFn Constructor; - char const* Name; - bool HasHandler; - }; - - PacketManager(); - - void RegisterAuthenticationPackets(); - void RegisterConnectionPackets(); - void RegisterWoWRealmPackets(); - void RegisterFriendsPackets(); - void RegisterPresencePackets(); - void RegisterChatPackets(); - void RegisterSupportPackets(); - void RegisterAchievementPackets(); - void RegisterCachePackets(); - void RegisterProfilePackets(); - - template<class PacketType> - static ClientPacket* New(PacketHeader const& header, BitStream& stream) - { - return new PacketType(header, stream); - } - - void RegisterPacketName(std::map<PacketHeader, PacketInfo>& packetTable, PacketHeader const& header, char const* name) - { - PacketInfo& info = packetTable[header]; - info.Constructor = nullptr; - info.Name = name; - info.HasHandler = false; - } - - template<class PacketType> - void RegisterClientPacket(PacketHeader const& header, char const* name) - { - PacketInfo& info = _clientPacketTable[header]; - info.Constructor = &New<PacketType>; - info.Name = name; - info.HasHandler = has_call_handler<PacketType>::value; - } - - public: - ClientPacket* CreateClientPacket(PacketHeader const& header, BitStream& stream); - - char const* GetClientPacketName(PacketHeader const& header); - char const* GetServerPacketName(PacketHeader const& header); - - bool IsHandled(PacketHeader const& header); - - static PacketManager& Instance() - { - static PacketManager instance; - return instance; - } - - private: - std::map<PacketHeader, PacketInfo> _clientPacketTable; - std::map<PacketHeader, PacketInfo> _serverPacketTable; - }; -} - -#define sPacketManager Battlenet::PacketManager::Instance() - -#endif // PacketManager_h__ diff --git a/src/server/bnetserver/Packets/Packets.h b/src/server/bnetserver/Packets/Packets.h deleted file mode 100644 index 834bb735a16..00000000000 --- a/src/server/bnetserver/Packets/Packets.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef Packets_h__ -#define Packets_h__ - -#include "AuthenticationPackets.h" -#include "ConnectionPackets.h" -#include "WoWRealmPackets.h" -#include "FriendsPackets.h" -#include "PresencePackets.h" -#include "ChatPackets.h" -#include "SupportPackets.h" -#include "AchievementPackets.h" -#include "CachePackets.h" -#include "ProfilePackets.h" - -#endif // Packets_h__ diff --git a/src/server/bnetserver/Packets/PacketsBase.h b/src/server/bnetserver/Packets/PacketsBase.h deleted file mode 100644 index 856fbe258c3..00000000000 --- a/src/server/bnetserver/Packets/PacketsBase.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef PacketsBase_h__ -#define PacketsBase_h__ - -#include "AuthCodes.h" -#include "BitStream.h" -#include "Common.h" -#include "Errors.h" -#include "PacketsCommon.h" -#include <string> -#include <boost/asio/ip/tcp.hpp> - -using boost::asio::ip::tcp; - -namespace Battlenet -{ - class BitStream; - class Session; - - enum Channel - { - AUTHENTICATION = 0, - CONNECTION = 1, - WOWREALM = 2, - FRIENDS = 3, - PRESENCE = 4, - CHAT = 5, - SUPPORT = 7, - ACHIEVEMENT = 8, - CACHE = 11, - PROFILE = 14 - }; - - struct PacketHeader : public PrintableComponent - { - PacketHeader(uint32 opcode, uint32 channel) : Command(opcode), Channel(channel) { } - PacketHeader() : Command(0), Channel(AUTHENTICATION) { } - - uint32 Command; - int32 Channel; - - bool operator<(PacketHeader const& right) const - { - if (Command < right.Command) - return true; - if (Command > right.Command) - return false; - - return Channel < right.Channel; - } - - bool operator==(PacketHeader const& right) const - { - return Command == right.Command && Channel == right.Channel; - } - - std::string ToString() const override; - }; - - class Packet : public PrintableComponent - { - public: - Packet(PacketHeader const& header, BitStream& stream) : _header(header), _stream(stream) { } - virtual ~Packet() { } - - PacketHeader const& GetHeader() const { return _header; } - - virtual void Write() = 0; - virtual void Read() = 0; - - protected: - PacketHeader _header; - BitStream& _stream; - - private: - Packet(Packet const& right) = delete; - Packet& operator=(Packet const& right) = delete; - }; - - class ClientPacket : public Packet - { - public: - ClientPacket(PacketHeader const& header, BitStream& stream) : Packet(header, stream) { } - - void Write() override final { ASSERT(!"Write not implemented for client packets."); } - virtual void CallHandler(Session* session); - }; - - class ServerPacket : public Packet - { - public: - ServerPacket(PacketHeader const& header); - ~ServerPacket(); - - void Read() override final { ASSERT(!"Read not implemented for server packets."); } - - uint8* GetData() { return _stream.GetBuffer(); } - uint8 const* GetData() const { return _stream.GetBuffer(); } - size_t GetSize() const { return _stream.GetSize(); } - }; -} - -#endif // PacketsBase_h__ diff --git a/src/server/bnetserver/Packets/PacketsCommon.cpp b/src/server/bnetserver/Packets/PacketsCommon.cpp deleted file mode 100644 index 59ab8540faf..00000000000 --- a/src/server/bnetserver/Packets/PacketsCommon.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "PacketsCommon.h" -#include "Util.h" - -std::string Battlenet::Version::Record::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::Version::Record" << std::endl; - APPEND_FIELD(stream, ProgramId); - APPEND_FIELD(stream, Component); - APPEND_FIELD(stream, Version); - return stream.str(); -} - -std::string Battlenet::Cache::Handle::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::Cache::Handle" << std::endl; - APPEND_FIELD(stream, Type); - APPEND_FIELD(stream, Region); - stream << "ModuleId: " << ByteArrayToHexStr(ModuleId, 32) << std::endl; - return stream.str(); -} - -std::string Battlenet::Account::FullName::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::Account::FullName" << std::endl; - APPEND_FIELD(stream, GivenName); - APPEND_FIELD(stream, Surname); - return stream.str(); -} - -std::string Battlenet::GameAccount::Handle::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::GameAccount::Handle" << std::endl; - APPEND_FIELD(stream, Region); - APPEND_FIELD(stream, ProgramId); - APPEND_FIELD(stream, Id); - return stream.str(); -} - -std::string Battlenet::PrintableRealmHandle::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::RealmHandle" << std::endl; - APPEND_FIELD(stream, Region); - APPEND_FIELD(stream, Site); - APPEND_FIELD(stream, Realm); - return stream.str(); -} - -std::string Battlenet::Toon::FullName::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::Toon::FullName" << std::endl; - APPEND_FIELD(stream, Region); - APPEND_FIELD(stream, ProgramId); - APPEND_FIELD(stream, Realm); - APPEND_FIELD(stream, Name); - return stream.str(); -} - -std::string Battlenet::Toon::Handle::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::Toon::Handle" << std::endl; - APPEND_FIELD(stream, Region); - APPEND_FIELD(stream, ProgramId); - APPEND_FIELD(stream, Realm); - APPEND_FIELD(stream, Id); - return stream.str(); -} - -std::string Battlenet::Profile::RecordAddress::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::Profile::RecordAddress" << std::endl; - APPEND_FIELD(stream, Label); - APPEND_FIELD(stream, Id); - return stream.str(); -} - -std::ostream& Battlenet::Format::FieldToString(std::ostream& stream, char const* fieldName, PrintableComponent const& u, std::true_type) -{ - if (fieldName[0]) - stream << fieldName << ": "; - return stream << u.ToString(); -} - -std::ostream& Battlenet::Format::FieldToString(std::ostream& stream, char const* fieldName, uint8 const& u, std::false_type) -{ - return FieldToString(stream, fieldName, uint32(u), std::false_type()); -} diff --git a/src/server/bnetserver/Packets/PacketsCommon.h b/src/server/bnetserver/Packets/PacketsCommon.h deleted file mode 100644 index c2a264c3eae..00000000000 --- a/src/server/bnetserver/Packets/PacketsCommon.h +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef PacketsCommon_h__ -#define PacketsCommon_h__ - -#include "Common.h" -#include "Realm/Realm.h" -#include <typeinfo> - -namespace Battlenet -{ - struct PrintableComponent - { - virtual ~PrintableComponent() { } - - virtual std::string ToString() const = 0; - }; - - namespace Format - { - template<typename T> - struct is_printable : std::is_base_of<PrintableComponent, typename std::remove_pointer<T>::type>::type - { - }; - - template<typename T> - typename std::enable_if<!std::is_pointer<T>::value, T>::type const& Dereference(T const& t) { return t; }; - - template<typename T> - typename std::enable_if<std::is_pointer<T>::value, typename std::remove_pointer<T>::type>::type const& Dereference(T const& t) { return *t; }; - - template<typename T> - std::ostream& FieldToString(std::ostream& stream, char const* fieldName, T const& u, std::false_type) - { - if (fieldName[0]) - stream << fieldName << ": "; - return stream << u << std::endl; - } - - std::ostream& FieldToString(std::ostream& stream, char const* fieldName, PrintableComponent const& u, std::true_type); - std::ostream& FieldToString(std::ostream& stream, char const* fieldName, uint8 const& u, std::false_type); - - template<typename T> - std::ostream& FieldToString(std::ostream& stream, char const* fieldName, std::vector<T> const& u, std::false_type) - { - stream << fieldName << ":" << std::endl; - for (T const& t : u) - FieldToString(stream, "", Dereference(t), is_printable<T>()); - return stream; - } - - template<typename T> - std::ostream& FieldToString(std::ostream& stream, char const* fieldName, Optional<T> const& u) - { - if (u) - FieldToString(stream, fieldName, Dereference(*u), is_printable<T>()); - return stream; - } - - template<typename T> - std::ostream& FieldToString(std::ostream& stream, char const* fieldName, T const& u) - { - return FieldToString(stream, fieldName, Dereference(u), is_printable<T>()); - } - } - -#define APPEND_FIELD(stream, field) Format::FieldToString(stream, #field, field) - - namespace Version - { - struct Record : public PrintableComponent - { - std::string ProgramId; - std::string Component; - uint32 Version; - - std::string ToString() const override; - }; - } - - namespace Cache - { - struct Handle : public PrintableComponent - { - std::string Type; - std::string Region; - uint8 ModuleId[32] = { }; - - std::string ToString() const override; - }; - } - - namespace Account - { - struct FullName : public PrintableComponent - { - std::string GivenName; - std::string Surname; - - std::string ToString() const override; - }; - } - - namespace GameAccount - { - struct Handle : public PrintableComponent - { - uint8 Region = 0; - std::string ProgramId; - uint32 Id = 0; - - std::string ToString() const override; - }; - } - - // For use in packets - struct PrintableRealmHandle : public RealmHandle, public PrintableComponent - { - PrintableRealmHandle() : RealmHandle() { } - PrintableRealmHandle(uint8 region, uint8 battlegroup, uint32 index) - : RealmHandle(region, battlegroup, index) { } - - PrintableRealmHandle& operator=(RealmHandle const& r) - { - RealmHandle::operator=(r); - return *this; - } - - std::string ToString() const override; - }; - - namespace Toon - { - struct FullName : public PrintableComponent - { - uint8 Region = 0; - std::string ProgramId; - uint32 Realm = 0; - std::string Name; - - std::string ToString() const override; - }; - - struct Handle : public PrintableComponent - { - uint8 Region = 0; - std::string ProgramId; - uint32 Realm = 0; - uint64 Id = 0; - - std::string ToString() const override; - }; - } - - namespace Profile - { - struct RecordAddress : public PrintableComponent - { - uint32 Label = 0; - uint64 Id = 0; - - std::string ToString() const override; - }; - } -} - -#endif // PacketsCommon_h__ diff --git a/src/server/bnetserver/Packets/ProfilePackets.h b/src/server/bnetserver/Packets/ProfilePackets.h deleted file mode 100644 index afa2f076c58..00000000000 --- a/src/server/bnetserver/Packets/ProfilePackets.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef ProfilePackets_h__ -#define ProfilePackets_h__ - -#include "PacketsBase.h" - -namespace Battlenet -{ - namespace Profile - { - enum Opcode - { - CMSG_READ_REQUEST = 0x0, // Not implemented - CMSG_ADDRESS_QUERY_REQUEST = 0x1, // Not implemented - CMSG_RESOLVE_TOON_HANDLE_TO_NAME_REQUEST = 0x2, // Not implemented - CMSG_RESOLVE_TOON_NAME_TO_HANDLE_REQUEST = 0x3, // Not implemented - CMSG_CHANGE_SETTINGS = 0x5, // Not implemented - - SMSG_READ_RESPONSE = 0x0, // Not implemented - SMSG_ADDRESS_QUERY_RESPONSE = 0x1, // Not implemented - SMSG_RESOLVE_TOON_HANDLE_TO_NAME_RESPONSE = 0x2, // Not implemented - SMSG_RESOLVE_TOON_NAME_TO_HANDLE_RESPONSE = 0x3, // Not implemented - SMSG_SETTINGS_AVAILABLE = 0x4 // Not implemented - }; - } -} - -#endif // ProfilePackets_h__ diff --git a/src/server/bnetserver/Packets/WoWRealmPackets.cpp b/src/server/bnetserver/Packets/WoWRealmPackets.cpp deleted file mode 100644 index ca066b9064c..00000000000 --- a/src/server/bnetserver/Packets/WoWRealmPackets.cpp +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "WoWRealmPackets.h" -#include "Session.h" -#include <boost/lexical_cast.hpp> -#include <boost/asio/ip/address.hpp> - -void Battlenet::WoWRealm::ListSubscribeRequest::CallHandler(Session* session) -{ - session->HandleListSubscribeRequest(*this); -} - -void Battlenet::WoWRealm::ListUnsubscribe::CallHandler(Session* session) -{ - session->HandleListUnsubscribe(*this); -} - -void Battlenet::WoWRealm::JoinRequestV2::Read() -{ - ClientSalt = _stream.Read<uint32>(32); - _stream.ReadSkip(20); - Id.Region = _stream.Read<uint8>(8); - _stream.ReadSkip(12); - Id.Site = _stream.Read<uint8>(8); - Id.Realm = _stream.Read<uint32>(32); -} - -std::string Battlenet::WoWRealm::JoinRequestV2::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::WoWRealm::JoinRequestV2" << std::endl; - APPEND_FIELD(stream, Id); - APPEND_FIELD(stream, ClientSalt); - return stream.str(); -} - -void Battlenet::WoWRealm::JoinRequestV2::CallHandler(Session* session) -{ - session->HandleJoinRequestV2(*this); -} - -void Battlenet::WoWRealm::ListSubscribeResponse::Write() -{ - _stream.Write(Type, 1); - if (Type == SUCCESS) - { - _stream.Write(ToonCounts.size(), 7); - for (ToonCountEntry const& entry : ToonCounts) - { - _stream.Write(entry.Realm.Region, 8); - _stream.WriteSkip(12); - _stream.Write(entry.Realm.Site, 8); - _stream.Write(entry.Realm.Realm, 32); - _stream.Write(entry.Count, 16); - } - } - else - _stream.Write(Failure, 8); -} - -std::string Battlenet::WoWRealm::ListSubscribeResponse::ToonCountEntry::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::WoWRealm::ListSubscribeResponse::ToonCountEntry" << std::endl; - APPEND_FIELD(stream, Realm); - APPEND_FIELD(stream, Count); - return stream.str(); -} - -std::string Battlenet::WoWRealm::ListSubscribeResponse::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::WoWRealm::ListSubscribeResponse" << std::endl; - - if (Type == SUCCESS) - APPEND_FIELD(stream, ToonCounts); - else - APPEND_FIELD(stream, Failure); - - return stream.str(); -} - -void Battlenet::WoWRealm::ListUpdate::Write() -{ - _stream.Write(State.Type, 1); - if (State.Type == StateType::UPDATE) - { - _stream.Write(State.Update.Category, 32); - _stream.WriteFloat(State.Update.Population); - _stream.Write(State.Update.StateFlags, 8); - _stream.WriteSkip(19); - _stream.Write(State.Update.Type + -std::numeric_limits<int32>::min(), 32); - _stream.WriteString(State.Update.Name, 10); - _stream.Write(State.Update.PrivilegedData.is_initialized(), 1); - if (State.Update.PrivilegedData.is_initialized()) - { - _stream.WriteString(State.Update.PrivilegedData->Version, 5); - _stream.Write(State.Update.PrivilegedData->ConfigId, 32); - - boost::asio::ip::address_v4::bytes_type ip = State.Update.PrivilegedData->Address.address().to_v4().to_bytes(); - uint16 port = State.Update.PrivilegedData->Address.port(); - - EndianConvertReverse(ip); - EndianConvertReverse(port); - - _stream.WriteBytes(ip.data(), 4); - _stream.WriteBytes(&port, 2); - } - - _stream.Write(State.Update.InfoFlags, 8); - } - - _stream.Write(Id.Region, 8); - _stream.WriteSkip(12); - _stream.Write(Id.Site, 8); - _stream.Write(Id.Realm, 32); -} - -std::string Battlenet::WoWRealm::ListUpdate::PrivilegedDataType::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::WoWRealm::RealmInfo::PrivilegedData" << std::endl; - APPEND_FIELD(stream, Version); - APPEND_FIELD(stream, ConfigId); - APPEND_FIELD(stream, Address); - return stream.str(); -} - -std::string Battlenet::WoWRealm::ListUpdate::StateType::UpdateType::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::WoWRealm::ListUpdate::State::Update" << std::endl; - APPEND_FIELD(stream, InfoFlags); - APPEND_FIELD(stream, Name); - APPEND_FIELD(stream, Type); - APPEND_FIELD(stream, Category); - APPEND_FIELD(stream, StateFlags); - APPEND_FIELD(stream, Population); - APPEND_FIELD(stream, PrivilegedData); - return stream.str(); -} - -std::string Battlenet::WoWRealm::ListUpdate::StateType::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::WoWRealm::ListUpdate::State" << std::endl; - - if (Type == UPDATE) - APPEND_FIELD(stream, Update); - else - APPEND_FIELD(stream, Delete); - - return stream.str(); -} - -std::string Battlenet::WoWRealm::ListUpdate::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::WoWRealm::ListUpdate" << std::endl; - APPEND_FIELD(stream, Id); - APPEND_FIELD(stream, State); - return stream.str(); -} - -void Battlenet::WoWRealm::ToonReady::Write() -{ - _stream.Write(Name.Region, 8); - _stream.WriteFourCC(Name.ProgramId); - _stream.Write(Name.Realm, 32); - _stream.WriteString(Name.Name, 7, -2); - _stream.WriteSkip(21); - _stream.Write(ProfileAddress.Id, 64); - _stream.Write(ProfileAddress.Label, 32); - _stream.Write(Handle.Id, 64); - _stream.Write(Handle.Realm, 32); - _stream.Write(Handle.Region, 8); - _stream.WriteFourCC(Handle.ProgramId); -} - -std::string Battlenet::WoWRealm::ToonReady::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::WoWRealm::ToonReady" << std::endl; - APPEND_FIELD(stream, Name); - APPEND_FIELD(stream, Handle); - APPEND_FIELD(stream, ProfileAddress); - return stream.str(); -} - -void Battlenet::WoWRealm::JoinResponseV2::Write() -{ - _stream.Write(Type, 1); - if (Type == SUCCESS) - { - _stream.Write(Success.ServerSalt, 32); - _stream.Write(Success.IPv4.size(), 5); - for (tcp::endpoint const& addr : Success.IPv4) - { - boost::asio::ip::address_v4::bytes_type ip = addr.address().to_v4().to_bytes(); - uint16 port = addr.port(); - - EndianConvertReverse(port); - - _stream.WriteBytes(ip.data(), 4); - _stream.WriteBytes(&port, 2); - } - - _stream.Write(Success.IPv6.size(), 5); - for (tcp::endpoint const& addr : Success.IPv6) - { - boost::asio::ip::address_v6::bytes_type ip = addr.address().to_v6().to_bytes(); - uint16 port = addr.port(); - - EndianConvertReverse(port); - - _stream.WriteBytes(ip.data(), 16); - _stream.WriteBytes(&port, 2); - } - } - else - _stream.Write(Failure, 8); -} - -std::string Battlenet::WoWRealm::JoinResponseV2::SuccessType::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::WoWRealm::JoinResponseV2::Success" << std::endl; - APPEND_FIELD(stream, ServerSalt); - APPEND_FIELD(stream, IPv4); - APPEND_FIELD(stream, IPv6); - return stream.str(); -} - -std::string Battlenet::WoWRealm::JoinResponseV2::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::WoWRealm::JoinResponseV2" << std::endl; - - if (Type == SUCCESS) - APPEND_FIELD(stream, Success); - else - APPEND_FIELD(stream, Failure); - - return stream.str(); -} diff --git a/src/server/bnetserver/Packets/WoWRealmPackets.h b/src/server/bnetserver/Packets/WoWRealmPackets.h deleted file mode 100644 index 320270abb61..00000000000 --- a/src/server/bnetserver/Packets/WoWRealmPackets.h +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef WoWRealmPackets_h__ -#define WoWRealmPackets_h__ - -#include "PacketsBase.h" -#include "RealmList.h" - -namespace Battlenet -{ - namespace WoWRealm - { - enum Opcode - { - CMSG_LIST_SUBSCRIBE_REQUEST = 0x0, - CMSG_LIST_UNSUBSCRIBE = 0x1, - CMSG_JOIN_REQUEST_V2 = 0x8, - CMSG_MULTI_LOGON_REQUEST_V2 = 0x9, // Not implemented - - SMSG_LIST_SUBSCRIBE_RESPONSE = 0x0, - SMSG_LIST_UPDATE = 0x2, - SMSG_LIST_COMPLETE = 0x3, - SMSG_TOON_READY = 0x6, // Not implemented - SMSG_TOON_LOGGED_OUT = 0x7, // Not implemented - SMSG_JOIN_RESPONSE_V2 = 0x8 - }; - - class ListSubscribeRequest final : public ClientPacket - { - public: - ListSubscribeRequest(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) - { - ASSERT(header == PacketHeader(CMSG_LIST_SUBSCRIBE_REQUEST, WOWREALM) && "Invalid packet header for ListSubscribeRequest"); - } - - void Read() override { } - std::string ToString() const override { return "Battlenet::WoWRealm::ListSubscribeRequest"; } - - void CallHandler(Session* session) override; - }; - - class ListUnsubscribe final : public ClientPacket - { - public: - ListUnsubscribe(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) - { - ASSERT(header == PacketHeader(CMSG_LIST_UNSUBSCRIBE, WOWREALM) && "Invalid packet header for ListUnsubscribe"); - } - - void Read() override { } - std::string ToString() const override { return "Battlenet::WoWRealm::ListUnsubscribe"; } - void CallHandler(Session* session) override; - }; - - class JoinRequestV2 final : public ClientPacket - { - public: - JoinRequestV2(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) - { - ASSERT(header == PacketHeader(CMSG_JOIN_REQUEST_V2, WOWREALM) && "Invalid packet header for RealmJoinRequest"); - } - - void Read() override; - std::string ToString() const override; - void CallHandler(Session* session) override; - - uint32 ClientSalt = 0; - PrintableRealmHandle Id; - }; - - class ListSubscribeResponse final : public ServerPacket - { - public: - ListSubscribeResponse() : ServerPacket(PacketHeader(SMSG_LIST_SUBSCRIBE_RESPONSE, WOWREALM)) - { - } - - struct ToonCountEntry : public PrintableComponent - { - ToonCountEntry(PrintableRealmHandle const& realm, uint16 count) : Realm(realm), Count(count) { } - - PrintableRealmHandle Realm; - uint16 Count; - - std::string ToString() const override; - }; - - void Write() override; - std::string ToString() const override; - - enum - { - SUCCESS = 0, - FAILURE = 1 - }; - - int32 Type = SUCCESS; - - std::vector<ToonCountEntry> ToonCounts; - Wow::AuthResult Failure = Wow::WOW_SUCCESS; - }; - - class ListUpdate final : public ServerPacket - { - public: - ListUpdate() : ServerPacket(PacketHeader(SMSG_LIST_UPDATE, WOWREALM)) - { - } - - void Write() override; - std::string ToString() const override; - - PrintableRealmHandle Id; - - struct PrivilegedDataType : public PrintableComponent - { - std::string Version; - uint32 ConfigId = 0; - tcp::endpoint Address; - - std::string ToString() const override; - }; - - struct StateType : public PrintableComponent - { - enum - { - DELETED = 0, - UPDATE = 1 - }; - - int32 Type = UPDATE; - struct DeleteType : public PrintableComponent - { - std::string ToString() const override { return "Battlenet::WoWRealm::ListUpdate::State::Delete"; } - } Delete; - - struct UpdateType : public PrintableComponent - { - uint8 InfoFlags = 0; - std::string Name; - int32 Type = 0; - uint32 Category = 0; - uint8 StateFlags = 0; - float Population = 0.0f; - Optional<PrivilegedDataType> PrivilegedData; - - std::string ToString() const override; - } Update; - - std::string ToString() const override; - } State; - }; - - class ListComplete final : public ServerPacket - { - public: - ListComplete() : ServerPacket(PacketHeader(SMSG_LIST_COMPLETE, WOWREALM)) - { - } - - void Write() override { } - std::string ToString() const override { return "Battlenet::WoWRealm::ListComplete"; } - }; - - class ToonReady final : public ServerPacket - { - public: - ToonReady() : ServerPacket(PacketHeader(SMSG_TOON_READY, WOWREALM)) - { - } - - void Write() override; - std::string ToString() const override; - - Toon::FullName Name; - Toon::Handle Handle; - Profile::RecordAddress ProfileAddress; - }; - - class ToonLoggedOut final : public ServerPacket - { - public: - ToonLoggedOut() : ServerPacket(PacketHeader(SMSG_TOON_LOGGED_OUT, WOWREALM)) - { - } - - void Write() override { } - std::string ToString() const override { return "Battlenet::WoWRealm::ToonLoggedOut"; } - }; - - class JoinResponseV2 final : public ServerPacket - { - public: - JoinResponseV2() : ServerPacket(PacketHeader(SMSG_JOIN_RESPONSE_V2, WOWREALM)) - { - } - - void Write() override; - std::string ToString() const override; - - enum - { - SUCCESS = 0, - FAILURE = 1 - }; - - int32 Type = SUCCESS; - struct SuccessType : public PrintableComponent - { - uint32 ServerSalt; - std::vector<tcp::endpoint> IPv4; - std::vector<tcp::endpoint> IPv6; - - std::string ToString() const override; - } Success; - - Wow::AuthResult Failure = Wow::WOW_SUCCESS; - }; - } -} - -#endif // WoWRealmPackets_h__ diff --git a/src/server/bnetserver/PrecompiledHeaders/bnetPCH.h b/src/server/bnetserver/PrecompiledHeaders/bnetPCH.h index 82cd5393489..0be88a714d5 100644 --- a/src/server/bnetserver/PrecompiledHeaders/bnetPCH.h +++ b/src/server/bnetserver/PrecompiledHeaders/bnetPCH.h @@ -1,10 +1,5 @@ -#include "Common.h" #include "Configuration/Config.h" -#include "Database/DatabaseEnv.h" -#include "Log.h" -#include "ComponentManager.h" -#include "ModuleManager.h" -#include "RealmList.h" -#include "ByteBuffer.h" -#include "Packets.h" -#include "Session.h" +#include "LoginRESTService.h" +#include "SessionManager.h" +#include "SslContext.h" +#include "ServiceDispatcher.h" diff --git a/src/server/bnetserver/REST/LoginRESTService.cpp b/src/server/bnetserver/REST/LoginRESTService.cpp new file mode 100644 index 00000000000..9ce21be9459 --- /dev/null +++ b/src/server/bnetserver/REST/LoginRESTService.cpp @@ -0,0 +1,433 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "LoginRESTService.h" +#include "Configuration/Config.h" +#include "DatabaseEnv.h" +#include "ProtobufJSON.h" +#include "Realm.h" +#include "SessionManager.h" +#include "SHA1.h" +#include "SHA256.h" +#include "SslContext.h" +#include "Util.h" +#include "httpget.h" +#include "httppost.h" +#include "soapH.h" + +int ns1__executeCommand(soap*, char*, char**) { return SOAP_OK; } + +int32 handle_get_plugin(soap* soapClient) +{ + return sLoginService.HandleGet(soapClient); +} + +int32 handle_post_plugin(soap* soapClient) +{ + return sLoginService.HandlePost(soapClient); +} + +bool LoginRESTService::Start(boost::asio::io_service& ioService) +{ + _bindIP = sConfigMgr->GetStringDefault("BindIP", "0.0.0.0"); + _port = sConfigMgr->GetIntDefault("LoginREST.Port", 8081); + if (_port < 0 || _port > 0xFFFF) + { + TC_LOG_ERROR("server.rest", "Specified login service port (%d) out of allowed range (1-65535), defaulting to 8081", _port); + _port = 8081; + } + + boost::system::error_code ec; + boost::asio::ip::tcp::resolver resolver(ioService); + boost::asio::ip::tcp::resolver::iterator end; + + std::string configuredAddress = sConfigMgr->GetStringDefault("LoginREST.ExternalAddress", "127.0.0.1"); + boost::asio::ip::tcp::resolver::query externalAddressQuery(boost::asio::ip::tcp::v4(), configuredAddress, std::to_string(_port)); + boost::asio::ip::tcp::resolver::iterator endPoint = resolver.resolve(externalAddressQuery, ec); + if (endPoint == end || ec) + { + TC_LOG_ERROR("server.rest", "Could not resolve LoginREST.ExternalAddress %s", configuredAddress.c_str()); + return false; + } + + _externalAddress = endPoint->endpoint(); + + configuredAddress = sConfigMgr->GetStringDefault("LoginREST.LocalAddress", "127.0.0.1"); + boost::asio::ip::tcp::resolver::query localAddressQuery(boost::asio::ip::tcp::v4(), configuredAddress, std::to_string(_port)); + endPoint = resolver.resolve(localAddressQuery, ec); + if (endPoint == end || ec) + { + TC_LOG_ERROR("server.rest", "Could not resolve LoginREST.ExternalAddress %s", configuredAddress.c_str()); + return false; + } + + _localAddress = endPoint->endpoint(); + + // set up form inputs + Battlenet::JSON::Login::FormInput* input; + _formInputs.set_type(Battlenet::JSON::Login::LOGIN_FORM); + input = _formInputs.add_inputs(); + input->set_input_id("account_name"); + input->set_type("text"); + input->set_label("E-mail"); + input->set_max_length(320); + + input = _formInputs.add_inputs(); + input->set_input_id("password"); + input->set_type("password"); + input->set_label("Password"); + input->set_max_length(16); + + input = _formInputs.add_inputs(); + input->set_input_id("log_in_submit"); + input->set_type("submit"); + input->set_label("Log In"); + + _loginTicketCleanupTimer = new boost::asio::deadline_timer(ioService); + _loginTicketCleanupTimer->expires_from_now(boost::posix_time::seconds(10)); + _loginTicketCleanupTimer->async_wait(std::bind(&LoginRESTService::CleanupLoginTickets, this, std::placeholders::_1)); + + _thread = std::thread(std::bind(&LoginRESTService::Run, this)); + return true; +} + +void LoginRESTService::Stop() +{ + _stopped = true; + _loginTicketCleanupTimer->cancel(); + _thread.join(); +} + +boost::asio::ip::tcp::endpoint const& LoginRESTService::GetAddressForClient(boost::asio::ip::address const& address) const +{ + if (address.is_loopback()) + return _localAddress; + + if (boost::asio::ip::address_v4::netmask(_localAddress.address().to_v4()).to_ulong() & address.to_v4().to_ulong()) + return _localAddress; + + return _externalAddress; +} + +void LoginRESTService::Run() +{ + soap soapServer(SOAP_C_UTFSTRING, SOAP_C_UTFSTRING); + + // check every 3 seconds if world ended + soapServer.accept_timeout = 3; + soapServer.recv_timeout = 5; + soapServer.send_timeout = 5; + if (!soap_valid_socket(soap_bind(&soapServer, _bindIP.c_str(), _port, 100))) + { + TC_LOG_ERROR("server.rest", "Couldn't bind to %s:%d", _bindIP.c_str(), _port); + return; + } + + TC_LOG_INFO("server.rest", "Login service bound to http://%s:%d", _bindIP.c_str(), _port); + + http_post_handlers handlers[] = + { + { "application/json;charset=utf-8", handle_post_plugin }, + { "application/json", handle_post_plugin }, + { NULL } + }; + + soap_register_plugin_arg(&soapServer, &http_get, handle_get_plugin); + soap_register_plugin_arg(&soapServer, &http_post, handlers); + soap_register_plugin_arg(&soapServer, &ContentTypePlugin::Init, "application/json;charset=utf-8"); + + // Use our already ready ssl context + soapServer.ctx = Battlenet::SslContext::instance().native_handle(); + soapServer.ssl_flags = SOAP_SSL_RSA; + + while (!_stopped) + { + if (!soap_valid_socket(soap_accept(&soapServer))) + continue; // ran into an accept timeout + + std::unique_ptr<soap> soapClient = Trinity::make_unique<soap>(soapServer); + boost::asio::ip::address_v4 address(soapClient->ip); + if (soap_ssl_accept(soapClient.get()) != SOAP_OK) + { + TC_LOG_DEBUG("server.rest", "Failed SSL handshake from IP=%s", address.to_string().c_str()); + continue; + } + + TC_LOG_DEBUG("server.rest", "Accepted connection from IP=%s", address.to_string().c_str()); + + std::thread([soapClient{ std::move(soapClient) }] + { + soap_serve(soapClient.get()); + }).detach(); + } + + // and release the context handle here - soap does not own it so it should not free it on exit + soapServer.ctx = nullptr; + + TC_LOG_INFO("server.rest", "Login service exiting..."); +} + +int32 LoginRESTService::HandleGet(soap* soapClient) +{ + boost::asio::ip::address_v4 address(soapClient->ip); + std::string ip_address = address.to_string(); + + TC_LOG_DEBUG("server.rest", "[%s:%d] Handling GET request path=\"%s\"", ip_address.c_str(), soapClient->port, soapClient->path); + + static std::string const expectedPath = "/bnetserver/login/"; + if (strstr(soapClient->path, expectedPath.c_str()) != &soapClient->path[0]) + return 404; + + return SendResponse(soapClient, _formInputs); +} + +int32 LoginRESTService::HandlePost(soap* soapClient) +{ + boost::asio::ip::address_v4 address(soapClient->ip); + std::string ip_address = address.to_string(); + + TC_LOG_DEBUG("server.rest", "[%s:%d] Handling POST request path=\"%s\"", ip_address.c_str(), soapClient->port, soapClient->path); + + static std::string const expectedPath = "/bnetserver/login/"; + if (strstr(soapClient->path, expectedPath.c_str()) != &soapClient->path[0]) + return 404; + + char *buf; + size_t len; + soap_http_body(soapClient, &buf, &len); + + Battlenet::JSON::Login::LoginForm loginForm; + Battlenet::JSON::Login::LoginResult loginResult; + if (!JSON::Deserialize(buf, &loginForm)) + { + if (soap_register_plugin_arg(soapClient, &ResponseCodePlugin::Init, nullptr) != SOAP_OK) + return 500; + + ResponseCodePlugin* responseCode = reinterpret_cast<ResponseCodePlugin*>(soap_lookup_plugin(soapClient, ResponseCodePlugin::PluginId)); + ASSERT(responseCode); + + responseCode->ErrorCode = 400; + + loginResult.set_authentication_state(Battlenet::JSON::Login::LOGIN); + loginResult.set_error_code("UNABLE_TO_DECODE"); + loginResult.set_error_message("There was an internal error while connecting to Battle.net. Please try again later."); + return SendResponse(soapClient, loginResult); + } + + std::string login; + std::string password; + + for (int32 i = 0; i < loginForm.inputs_size(); ++i) + { + if (loginForm.inputs(i).input_id() == "account_name") + login = loginForm.inputs(i).value(); + else if (loginForm.inputs(i).input_id() == "password") + password = loginForm.inputs(i).value(); + } + + Utf8ToUpperOnlyLatin(login); + Utf8ToUpperOnlyLatin(password); + + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_ACCOUNT_INFO); + stmt->setString(0, login); + stmt->setString(1, CalculateShaPassHash(login, std::move(password))); + if (PreparedQueryResult result = LoginDatabase.Query(stmt)) + { + std::unique_ptr<Battlenet::Session::AccountInfo> accountInfo = Trinity::make_unique<Battlenet::Session::AccountInfo>(); + accountInfo->LoadResult(result); + + stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_CHARACTER_COUNTS_BY_BNET_ID); + stmt->setUInt32(0, accountInfo->Id); + if (PreparedQueryResult characterCountsResult = LoginDatabase.Query(stmt)) + { + do + { + Field* fields = characterCountsResult->Fetch(); + accountInfo->GameAccounts[fields[0].GetUInt32()] + .CharacterCounts[Battlenet::RealmHandle{ fields[3].GetUInt8(), fields[4].GetUInt8(), fields[2].GetUInt32() }.GetAddress()] = fields[1].GetUInt8(); + + } while (characterCountsResult->NextRow()); + } + + stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_LAST_PLAYER_CHARACTERS); + stmt->setUInt32(0, accountInfo->Id); + if (PreparedQueryResult lastPlayerCharactersResult = LoginDatabase.Query(stmt)) + { + Field* fields = lastPlayerCharactersResult->Fetch(); + Battlenet::RealmHandle realmId{ fields[1].GetUInt8(), fields[2].GetUInt8(), fields[3].GetUInt32() }; + Battlenet::Session::LastPlayedCharacterInfo& lastPlayedCharacter = accountInfo->GameAccounts[fields[0].GetUInt32()] + .LastPlayedCharacters[realmId.GetSubRegionAddress()]; + + lastPlayedCharacter.RealmId = realmId; + lastPlayedCharacter.CharacterName = fields[4].GetString(); + lastPlayedCharacter.CharacterGUID = fields[5].GetUInt64(); + lastPlayedCharacter.LastPlayedTime = fields[6].GetUInt32(); + } + + BigNumber ticket; + ticket.SetRand(20 * 8); + + loginResult.set_login_ticket("TC-" + ByteArrayToHexStr(ticket.AsByteArray(20).get(), 20)); + + AddLoginTicket(loginResult.login_ticket(), std::move(accountInfo)); + } + + loginResult.set_authentication_state(Battlenet::JSON::Login::DONE); + return SendResponse(soapClient, loginResult); +} + +int32 LoginRESTService::SendResponse(soap* soapClient, google::protobuf::Message const& response) +{ + std::string jsonResponse = JSON::Serialize(response); + + soap_response(soapClient, SOAP_FILE); + soap_send_raw(soapClient, jsonResponse.c_str(), jsonResponse.length()); + return soap_end_send(soapClient); +} + +std::string LoginRESTService::CalculateShaPassHash(std::string const& name, std::string const& password) +{ + SHA256Hash email; + email.UpdateData(name); + email.Finalize(); + + SHA256Hash sha; + sha.UpdateData(ByteArrayToHexStr(email.GetDigest(), email.GetLength())); + sha.UpdateData(":"); + sha.UpdateData(password); + sha.Finalize(); + + return ByteArrayToHexStr(sha.GetDigest(), sha.GetLength(), true); +} + +std::unique_ptr<Battlenet::Session::AccountInfo> LoginRESTService::VerifyLoginTicket(std::string const& id) +{ + std::unique_lock<std::mutex> lock(_loginTicketMutex); + + auto itr = _validLoginTickets.find(id); + if (itr != _validLoginTickets.end()) + { + if (itr->second.ExpiryTime > time(nullptr)) + { + std::unique_ptr<Battlenet::Session::AccountInfo> accountInfo = std::move(itr->second.Account); + _validLoginTickets.erase(itr); + return accountInfo; + } + } + + return std::unique_ptr<Battlenet::Session::AccountInfo>(); +} + +void LoginRESTService::AddLoginTicket(std::string const& id, std::unique_ptr<Battlenet::Session::AccountInfo> accountInfo) +{ + std::unique_lock<std::mutex> lock(_loginTicketMutex); + + _validLoginTickets[id] = { id, std::move(accountInfo), time(nullptr) + 10 }; +} + +void LoginRESTService::CleanupLoginTickets(boost::system::error_code const& error) +{ + if (error) + return; + + time_t now = time(nullptr); + + { + std::unique_lock<std::mutex> lock(_loginTicketMutex); + for (auto itr = _validLoginTickets.begin(); itr != _validLoginTickets.end();) + { + if (itr->second.ExpiryTime < now) + itr = _validLoginTickets.erase(itr); + else + ++itr; + } + } + + _loginTicketCleanupTimer->expires_from_now(boost::posix_time::seconds(10)); + _loginTicketCleanupTimer->async_wait(std::bind(&LoginRESTService::CleanupLoginTickets, this, std::placeholders::_1)); +} + +Namespace namespaces[] = +{ + { NULL, NULL, NULL, NULL } +}; + +LoginRESTService& LoginRESTService::Instance() +{ + static LoginRESTService instance; + return instance; +} + +char const* const LoginRESTService::ResponseCodePlugin::PluginId = "bnet-error-code"; + +int32 LoginRESTService::ResponseCodePlugin::Init(soap* s, soap_plugin* p, void* /*arg*/) +{ + ResponseCodePlugin* data = new ResponseCodePlugin(); + data->fresponse = s->fresponse; + + p->id = PluginId; + p->fdelete = &Destroy; + p->data = data; + + s->fresponse = &ChangeResponse; + return SOAP_OK; +} + +void LoginRESTService::ResponseCodePlugin::Destroy(soap* s, soap_plugin* p) +{ + ResponseCodePlugin* data = reinterpret_cast<ResponseCodePlugin*>(p->data); + s->fresponse = data->fresponse; + delete data; +} + +int32 LoginRESTService::ResponseCodePlugin::ChangeResponse(soap* s, int32 originalResponse, size_t contentLength) +{ + ResponseCodePlugin* self = reinterpret_cast<ResponseCodePlugin*>(soap_lookup_plugin(s, PluginId)); + return self->fresponse(s, self->ErrorCode && originalResponse == SOAP_FILE ? self->ErrorCode : originalResponse, contentLength); +} + +char const* const LoginRESTService::ContentTypePlugin::PluginId = "bnet-content-type"; + +int32 LoginRESTService::ContentTypePlugin::Init(soap* s, soap_plugin* p, void* arg) +{ + ContentTypePlugin* data = new ContentTypePlugin(); + data->fposthdr = s->fposthdr; + data->ContentType = reinterpret_cast<char const*>(arg); + + p->id = PluginId; + p->fdelete = &Destroy; + p->data = data; + + s->fposthdr = &OnSetHeader; + return SOAP_OK; +} + +void LoginRESTService::ContentTypePlugin::Destroy(soap* s, soap_plugin* p) +{ + ContentTypePlugin* data = reinterpret_cast<ContentTypePlugin*>(p->data); + s->fposthdr = data->fposthdr; + delete data; +} + +int32 LoginRESTService::ContentTypePlugin::OnSetHeader(soap* s, char const* key, char const* value) +{ + ContentTypePlugin* self = reinterpret_cast<ContentTypePlugin*>(soap_lookup_plugin(s, PluginId)); + if (key && !strcmp("Content-Type", key)) + value = self->ContentType; + + return self->fposthdr(s, key, value); +} diff --git a/src/server/bnetserver/REST/LoginRESTService.h b/src/server/bnetserver/REST/LoginRESTService.h new file mode 100644 index 00000000000..01c08577688 --- /dev/null +++ b/src/server/bnetserver/REST/LoginRESTService.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef LoginRESTService_h__ +#define LoginRESTService_h__ + +#include "Session.h" +#include "Define.h" +#include "Login.pb.h" +#include <boost/asio/io_service.hpp> +#include <boost/asio/ip/tcp.hpp> +#include <boost/asio/ip/address.hpp> +#include <boost/asio/deadline_timer.hpp> +#include <atomic> +#include <mutex> +#include <thread> + +struct soap; +struct soap_plugin; + +class LoginRESTService +{ +public: + LoginRESTService() : _stopped(false), _port(0) { } + + static LoginRESTService& Instance(); + + bool Start(boost::asio::io_service& ioService); + void Stop(); + + boost::asio::ip::tcp::endpoint const& GetAddressForClient(boost::asio::ip::address const& address) const; + + std::unique_ptr<Battlenet::Session::AccountInfo> VerifyLoginTicket(std::string const& id); + +private: + void Run(); + + friend int32 handle_get_plugin(soap* soapClient); + int32 HandleGet(soap* soapClient); + + friend int32 handle_post_plugin(soap* soapClient); + int32 HandlePost(soap* soapClient); + + int32 SendResponse(soap* soapClient, google::protobuf::Message const& response); + + std::string CalculateShaPassHash(std::string const& name, std::string const& password); + + void AddLoginTicket(std::string const& id, std::unique_ptr<Battlenet::Session::AccountInfo> accountInfo); + void CleanupLoginTickets(boost::system::error_code const& error); + + struct LoginTicket + { + std::string Id; + std::unique_ptr<Battlenet::Session::AccountInfo> Account; + std::time_t ExpiryTime; + }; + + struct ResponseCodePlugin + { + static char const* const PluginId; + static int32 Init(soap* s, soap_plugin*, void*); + static void Destroy(soap* s, soap_plugin* p); + static int32 ChangeResponse(soap* s, int32 originalResponse, size_t contentLength); + + int32(*fresponse)(soap* s, int32 status, size_t length); + int32 ErrorCode; + }; + + struct ContentTypePlugin + { + static char const* const PluginId; + static int32 Init(soap* s, soap_plugin* p, void*); + static void Destroy(soap* s, soap_plugin* p); + static int32 OnSetHeader(soap* s, char const* key, char const* value); + + int32(*fposthdr)(soap* s, char const* key, char const* value); + char const* ContentType; + }; + + std::thread _thread; + std::atomic<bool> _stopped; + Battlenet::JSON::Login::FormInputs _formInputs; + std::string _bindIP; + int32 _port; + boost::asio::ip::tcp::endpoint _externalAddress; + boost::asio::ip::tcp::endpoint _localAddress; + std::mutex _loginTicketMutex; + std::unordered_map<std::string, LoginTicket> _validLoginTickets; + boost::asio::deadline_timer* _loginTicketCleanupTimer; +}; + +#define sLoginService LoginRESTService::Instance() + +#endif // LoginRESTService_h__ diff --git a/src/server/bnetserver/Server/ComponentManager.cpp b/src/server/bnetserver/Server/ComponentManager.cpp deleted file mode 100644 index 216c0603985..00000000000 --- a/src/server/bnetserver/Server/ComponentManager.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "ComponentManager.h" -#include "DatabaseEnv.h" - -Battlenet::ComponentMgr::~ComponentMgr() -{ - for (Version::Record* component : _components) - delete component; -} - -void Battlenet::ComponentMgr::Load() -{ - QueryResult result = LoginDatabase.Query("SELECT Program, Platform, Build FROM battlenet_components"); - if (result) - { - do - { - Field* fields = result->Fetch(); - Version::Record* component = new Version::Record(); - component->ProgramId = fields[0].GetString(); - component->Component = fields[1].GetString(); - component->Version = fields[2].GetUInt32(); - - _components.insert(component); - _programs.insert(component->ProgramId); - _platforms.insert(component->Component); - - } while (result->NextRow()); - } -} - -bool Battlenet::ComponentMgr::HasComponent(Battlenet::Version::Record const* component) const -{ - for (Version::Record const* c : _components) - if (component->ProgramId == c->ProgramId && component->Component == c->Component && component->Version == c->Version) - return true; - - return false; -} diff --git a/src/server/bnetserver/Server/ComponentManager.h b/src/server/bnetserver/Server/ComponentManager.h deleted file mode 100644 index 464ddbfcd89..00000000000 --- a/src/server/bnetserver/Server/ComponentManager.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef ComponentManager_h__ -#define ComponentManager_h__ - -#include "Define.h" -#include "PacketsCommon.h" -#include <cstring> -#include <string> -#include <set> - -namespace Battlenet -{ - class ComponentMgr - { - ComponentMgr() { } - ~ComponentMgr(); - - public: - void Load(); - bool HasComponent(Version::Record const* component) const; - bool HasProgram(std::string const& program) const { return _programs.count(program) != 0; } - bool HasPlatform(std::string const& platform) const { return _platforms.count(platform) != 0; } - - static ComponentMgr* instance() - { - static ComponentMgr instance; - return &instance; - } - - private: - std::set<Version::Record*> _components; - std::set<std::string> _programs; - std::set<std::string> _platforms; - }; -} - -#define sComponentMgr Battlenet::ComponentMgr::instance() - -#endif // ComponentManager_h__ diff --git a/src/server/bnetserver/Server/ModuleManager.cpp b/src/server/bnetserver/Server/ModuleManager.cpp deleted file mode 100644 index 2919dacf2ad..00000000000 --- a/src/server/bnetserver/Server/ModuleManager.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "ModuleManager.h" -#include "DatabaseEnv.h" - -Battlenet::ModuleManager::~ModuleManager() -{ - for (auto const& m : _modules) - delete m.second; -} - -void Battlenet::ModuleManager::Load() -{ - QueryResult result = LoginDatabase.Query("SELECT `Hash`, `Name`, `Type`, `System`, `Data` FROM battlenet_modules"); - if (result) - { - do - { - Field* fields = result->Fetch(); - ModuleInfo* module = new ModuleInfo(); - module->Handle.Type = fields[2].GetString(); - HexStrToByteArray(fields[0].GetString(), module->Handle.ModuleId); - std::string data = fields[4].GetString(); - module->DataSize = data.length() / 2; - if (module->DataSize) - { - module->Data = new uint8[data.length() / 2]; - HexStrToByteArray(data, module->Data); - } - - _modules[{ fields[3].GetString(), fields[1].GetString() }] = module; - } while (result->NextRow()); - } -} - -Battlenet::ModuleInfo* Battlenet::ModuleManager::CreateModule(std::string const& os, std::string const& name) const -{ - ModuleKey key { os, name }; - if (!_modules.count(key)) - return nullptr; - - return new ModuleInfo(*_modules.at(key)); -} - -std::string Battlenet::ModuleInfo::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::ModuleInput" << std::endl; - APPEND_FIELD(stream, Handle); - return stream.str(); -} diff --git a/src/server/bnetserver/Server/ModuleManager.h b/src/server/bnetserver/Server/ModuleManager.h deleted file mode 100644 index 457bae4573b..00000000000 --- a/src/server/bnetserver/Server/ModuleManager.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef ModuleManager_h__ -#define ModuleManager_h__ - -#include "PacketsCommon.h" - -namespace Battlenet -{ - struct ModuleKey - { - std::string Platform; - std::string Name; - - bool operator<(ModuleKey const& right) const - { - int32 res = Platform.compare(right.Platform); - if (res < 0) - return true; - else if (res > 0) - return false; - - return Name < right.Name; - } - }; - - struct ModuleInfo : public PrintableComponent - { - ModuleInfo() : DataSize(0), Data(nullptr) { Handle.Region = "EU"; } - ModuleInfo(ModuleInfo const& right) : DataSize(right.DataSize), Data(nullptr) - { - Handle.Type = right.Handle.Type; - Handle.Region = right.Handle.Region; - memcpy(Handle.ModuleId, right.Handle.ModuleId, 32); - if (DataSize) - { - Data = new uint8[DataSize]; - memcpy(Data, right.Data, DataSize); - } - } - - virtual ~ModuleInfo() - { - delete[] Data; - } - - Cache::Handle Handle; - uint32 DataSize; - uint8* Data; - - std::string ToString() const override; - }; - - class ModuleManager - { - ModuleManager() { } - ~ModuleManager(); - - public: - void Load(); - ModuleInfo* CreateModule(std::string const& os, std::string const& name) const; - - static ModuleManager* instance() - { - static ModuleManager instance; - return &instance; - } - - private: - std::map<ModuleKey, ModuleInfo*> _modules; - }; -} - -#define sModuleMgr Battlenet::ModuleManager::instance() - -#endif // ModuleManager_h__ diff --git a/src/server/bnetserver/Server/Session.cpp b/src/server/bnetserver/Server/Session.cpp index 4d54562501f..66d55480796 100644 --- a/src/server/bnetserver/Server/Session.cpp +++ b/src/server/bnetserver/Server/Session.cpp @@ -15,30 +15,21 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "AuthCodes.h" -#include "BitStream.h" -#include "PacketManager.h" -#include "SessionManager.h" +#include "Session.h" +#include "BattlenetRpcErrorCodes.h" +#include "ByteConverter.h" #include "Database/DatabaseEnv.h" -#include "HmacHash.h" -#include "Log.h" +#include "LoginRESTService.h" +#include "ProtobufJSON.h" #include "RealmList.h" -#include "SHA256.h" -#include <map> +#include "ServiceDispatcher.h" +#include "RealmList.pb.h" +#include <zlib.h> -Battlenet::Session::ModuleHandler const Battlenet::Session::ModuleHandlers[MODULE_COUNT] = -{ - &Battlenet::Session::HandlePasswordModule, - &Battlenet::Session::UnhandledModule, - &Battlenet::Session::UnhandledModule, - &Battlenet::Session::HandleSelectGameAccountModule, - &Battlenet::Session::HandleRiskFingerprintModule, - &Battlenet::Session::HandleResumeModule, -}; - -void Battlenet::AccountInfo::LoadResult(Field* fields) +void Battlenet::Session::AccountInfo::LoadResult(PreparedQueryResult result) { // ba.id, ba.email, ba.locked, ba.lock_country, ba.last_ip, ba.failed_logins, bab.unbandate > UNIX_TIMESTAMP() OR bab.unbandate = bab.bandate, bab.unbandate = bab.bandate FROM battlenet_accounts ba LEFT JOIN battlenet_account_bans bab WHERE email = ? + Field* fields = result->Fetch(); Id = fields[0].GetUInt32(); Login = fields[1].GetString(); IsLockedToIP = fields[2].GetBool(); @@ -47,9 +38,17 @@ void Battlenet::AccountInfo::LoadResult(Field* fields) FailedLogins = fields[5].GetUInt32(); IsBanned = fields[6].GetUInt64() != 0; IsPermanenetlyBanned = fields[7].GetUInt64() != 0; + + static uint32 const GameAccountFieldsOffset = 8; + + do + { + GameAccounts[result->Fetch()[GameAccountFieldsOffset].GetUInt32()].LoadResult(result->Fetch() + GameAccountFieldsOffset); + + } while (result->NextRow()); } -void Battlenet::GameAccountInfo::LoadResult(Field* fields) +void Battlenet::Session::GameAccountInfo::LoadResult(Field* fields) { // a.id, a.username, ab.unbandate > UNIX_TIMESTAMP() OR ab.unbandate = ab.bandate, ab.unbandate = ab.bandate, aa.gmlevel Id = fields[0].GetUInt32(); @@ -65,204 +64,215 @@ void Battlenet::GameAccountInfo::LoadResult(Field* fields) DisplayName = Name; } -Battlenet::Session::Session(tcp::socket&& socket) : Socket(std::move(socket)), _accountInfo(new AccountInfo()), _gameAccountInfo(nullptr), _locale(), - _os(), _build(0), _ipCountry(), I(), s(), v(), b(), B(), K(), - _reconnectProof(), _crypt(), _authed(false), _subscribedToRealmListUpdates(false), _toonOnline(false) +Battlenet::Session::Session(tcp::socket&& socket) : BattlenetSocket(std::move(socket)), _accountInfo(new AccountInfo()), _gameAccountInfo(nullptr), _locale(), + _os(), _build(0), _ipCountry(), _authed(false), _requestToken(0) { - static uint8 const N_Bytes[] = - { - 0xAB, 0x24, 0x43, 0x63, 0xA9, 0xC2, 0xA6, 0xC3, 0x3B, 0x37, 0xE4, 0x61, 0x84, 0x25, 0x9F, 0x8B, - 0x3F, 0xCB, 0x8A, 0x85, 0x27, 0xFC, 0x3D, 0x87, 0xBE, 0xA0, 0x54, 0xD2, 0x38, 0x5D, 0x12, 0xB7, - 0x61, 0x44, 0x2E, 0x83, 0xFA, 0xC2, 0x21, 0xD9, 0x10, 0x9F, 0xC1, 0x9F, 0xEA, 0x50, 0xE3, 0x09, - 0xA6, 0xE5, 0x5E, 0x23, 0xA7, 0x77, 0xEB, 0x00, 0xC7, 0xBA, 0xBF, 0xF8, 0x55, 0x8A, 0x0E, 0x80, - 0x2B, 0x14, 0x1A, 0xA2, 0xD4, 0x43, 0xA9, 0xD4, 0xAF, 0xAD, 0xB5, 0xE1, 0xF5, 0xAC, 0xA6, 0x13, - 0x1C, 0x69, 0x78, 0x64, 0x0B, 0x7B, 0xAF, 0x9C, 0xC5, 0x50, 0x31, 0x8A, 0x23, 0x08, 0x01, 0xA1, - 0xF5, 0xFE, 0x31, 0x32, 0x7F, 0xE2, 0x05, 0x82, 0xD6, 0x0B, 0xED, 0x4D, 0x55, 0x32, 0x41, 0x94, - 0x29, 0x6F, 0x55, 0x7D, 0xE3, 0x0F, 0x77, 0x19, 0xE5, 0x6C, 0x30, 0xEB, 0xDE, 0xF6, 0xA7, 0x86 - }; - - N.SetBinary(N_Bytes, sizeof(N_Bytes)); - g.SetDword(2); - - SHA256Hash sha; - sha.UpdateBigNumbers(&N, &g, NULL); - sha.Finalize(); - k.SetBinary(sha.GetDigest(), sha.GetLength()); + _headerLengthBuffer.Resize(2); } Battlenet::Session::~Session() { - if (_authed) - sSessionMgr.RemoveSession(this); - - delete _accountInfo; } -void Battlenet::Session::_SetVSFields(std::string const& pstr) +void Battlenet::Session::AsyncHandshake() { - s.SetRand(uint32(BufferSizes::SRP_6_S) * 8); + underlying_stream().async_handshake(ssl::stream_base::server, std::bind(&Session::HandshakeHandler, shared_from_this(), std::placeholders::_1)); +} - BigNumber p; - p.SetHexStr(pstr.c_str()); +void Battlenet::Session::Start() +{ + std::string ip_address = GetRemoteIpAddress().to_string(); + TC_LOG_TRACE("session", "%s Accepted connection", GetClientInfo().c_str()); - SHA256Hash sha; - sha.UpdateBigNumbers(&s, &p, NULL); - sha.Finalize(); - BigNumber x; - x.SetBinary(sha.GetDigest(), sha.GetLength()); - v = g.ModExp(x, N); + // Verify that this IP is not in the ip_banned table + LoginDatabase.Execute(LoginDatabase.GetPreparedStatement(LOGIN_DEL_EXPIRED_IP_BANS)); - PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_VS_FIELDS); - stmt->setString(0, v.AsHexStr()); - stmt->setString(1, s.AsHexStr()); - stmt->setString(2, _accountInfo->Login); + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_IP_INFO); + stmt->setString(0, ip_address); + stmt->setUInt32(1, inet_addr(ip_address.c_str())); - LoginDatabase.Execute(stmt); + _queryCallback = std::bind(&Battlenet::Session::CheckIpCallback, this, std::placeholders::_1); + _queryFuture = LoginDatabase.AsyncQuery(stmt); } -void Battlenet::Session::LogUnhandledPacket(PacketHeader const& header) +void Battlenet::Session::CheckIpCallback(PreparedQueryResult result) { - TC_LOG_DEBUG("session.packets", "%s Received unhandled packet %s", GetClientInfo().c_str(), sPacketManager.GetClientPacketName(header)); + if (result) + { + bool banned = false; + do + { + Field* fields = result->Fetch(); + if (fields[0].GetUInt64() != 0) + banned = true; + + if (!fields[1].GetString().empty()) + _ipCountry = fields[1].GetString(); + + } while (result->NextRow()); + + if (banned) + { + TC_LOG_DEBUG("session", "%s tries to log in using banned IP!", GetClientInfo().c_str()); + CloseSocket(); + return; + } + } + + AsyncHandshake(); } -void Battlenet::Session::HandleLogonRequest(Authentication::LogonRequest3 const& logonRequest) +bool Battlenet::Session::Update() { - if (_queryCallback) - { - Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); - logonResponse->SetAuthResult(AUTH_LOGON_TOO_FAST); - AsyncWrite(logonResponse); - TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s attempted to log too quick after previous attempt!", GetClientInfo().c_str()); - return; - } + if (!BattlenetSocket::Update()) + return false; - if (logonRequest.Common.Program != "WoW") + if (_queryFuture.valid() && _queryFuture.wait_for(std::chrono::seconds(0)) == std::future_status::ready) { - Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); - logonResponse->SetAuthResult(AUTH_INVALID_PROGRAM); - AsyncWrite(logonResponse); - TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s attempted to log in with game other than WoW (using %s)!", GetClientInfo().c_str(), logonRequest.Common.Program.c_str()); - return; + auto callback = std::move(_queryCallback); + _queryCallback = nullptr; + callback(_queryFuture.get()); } - if (!sComponentMgr->HasPlatform(logonRequest.Common.Platform)) - { - Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); - logonResponse->SetAuthResult(AUTH_INVALID_OS); - AsyncWrite(logonResponse); - TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s attempted to log in from an unsupported platform (using %s)!", GetClientInfo().c_str(), logonRequest.Common.Platform.c_str()); - return; - } + return true; +} - if (!sComponentMgr->HasPlatform(logonRequest.Common.Locale)) - { - Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); - logonResponse->SetAuthResult(AUTH_UNSUPPORTED_LANGUAGE); - AsyncWrite(logonResponse); - TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s attempted to log in with unsupported locale (using %s)!", GetClientInfo().c_str(), logonRequest.Common.Locale.c_str()); +void Battlenet::Session::AsyncWrite(MessageBuffer* packet) +{ + if (!IsOpen()) return; - } - for (Version::Record const& component : logonRequest.Common.Versions) - { - if (!sComponentMgr->HasComponent(&component)) - { - Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); - if (!sComponentMgr->HasProgram(component.ProgramId)) - { - logonResponse->SetAuthResult(AUTH_INVALID_PROGRAM); - TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s is using unsupported component program %s!", GetClientInfo().c_str(), component.ProgramId.c_str()); - } - else if (!sComponentMgr->HasPlatform(component.Component)) - { - logonResponse->SetAuthResult(AUTH_INVALID_OS); - TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s is using unsupported component platform %s!", GetClientInfo().c_str(), component.Component.c_str()); - } - else - { - if (component.ProgramId != "WoW" || AuthHelper::IsBuildSupportingBattlenet(component.Version)) - logonResponse->SetAuthResult(AUTH_REGION_BAD_VERSION); - else - logonResponse->SetAuthResult(AUTH_USE_GRUNT_LOGON); + QueuePacket(std::move(*packet)); +} - TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s is using unsupported component version %u!", GetClientInfo().c_str(), component.Version); - } +void Battlenet::Session::SendResponse(uint32 token, pb::Message const* response) +{ + Header header; + header.set_token(token); + header.set_service_id(0xFE); + header.set_size(response->ByteSize()); - AsyncWrite(logonResponse); - return; - } + uint16 headerSize = header.ByteSize(); + EndianConvertReverse(headerSize); - if (component.Component == "base") - _build = component.Version; - } + MessageBuffer packet; + packet.Write(&headerSize, sizeof(headerSize)); + uint8* ptr = packet.GetWritePointer(); + packet.WriteCompleted(header.ByteSize()); + header.SerializeToArray(ptr, header.ByteSize()); + ptr = packet.GetWritePointer(); + packet.WriteCompleted(response->ByteSize()); + response->SerializeToArray(ptr, response->ByteSize()); + + AsyncWrite(&packet); +} - std::string login = logonRequest.Account; - _locale = logonRequest.Common.Locale; - _os = logonRequest.Common.Platform; +void Battlenet::Session::SendResponse(uint32 token, uint32 status) +{ + Header header; + header.set_token(token); + header.set_status(status); + header.set_service_id(0xFE); - Utf8ToUpperOnlyLatin(login); - PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_ACCOUNT_INFO); - stmt->setString(0, login); + uint16 headerSize = header.ByteSize(); + EndianConvertReverse(headerSize); - _queryCallback = std::bind(&Battlenet::Session::HandleLogonRequestCallback, this, std::placeholders::_1); - _queryFuture = LoginDatabase.AsyncQuery(stmt); + MessageBuffer packet; + packet.Write(&headerSize, sizeof(headerSize)); + uint8* ptr = packet.GetWritePointer(); + packet.WriteCompleted(header.ByteSize()); + header.SerializeToArray(ptr, header.ByteSize()); + + AsyncWrite(&packet); } -void Battlenet::Session::HandleLogonRequestCallback(PreparedQueryResult result) +void Battlenet::Session::SendRequest(uint32 serviceHash, uint32 methodId, pb::Message const* request) { - if (!result) + Header header; + header.set_service_id(0); + header.set_service_hash(serviceHash); + header.set_method_id(methodId); + header.set_size(request->ByteSize()); + header.set_token(_requestToken++); + + uint16 headerSize = header.ByteSize(); + EndianConvertReverse(headerSize); + + MessageBuffer packet; + packet.Write(&headerSize, sizeof(headerSize)); + uint8* ptr = packet.GetWritePointer(); + packet.WriteCompleted(header.ByteSize()); + header.SerializeToArray(ptr, header.ByteSize()); + ptr = packet.GetWritePointer(); + packet.WriteCompleted(request->ByteSize()); + request->SerializeToArray(ptr, request->ByteSize()); + + AsyncWrite(&packet); +} + +uint32 Battlenet::Session::HandleLogon(authentication::v1::LogonRequest const* logonRequest) +{ + if (logonRequest->program() != "WoW") { - Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); - logonResponse->SetAuthResult(AUTH_UNKNOWN_ACCOUNT); - AsyncWrite(logonResponse); - TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s is trying to log in from unknown account!", GetClientInfo().c_str()); - return; + TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s attempted to log in with game other than WoW (using %s)!", GetClientInfo().c_str(), logonRequest->program().c_str()); + return ERROR_BAD_PROGRAM; } - Field* fields = result->Fetch(); - _accountInfo->LoadResult(fields); - - std::string pStr = fields[8].GetString(); - std::string databaseV = fields[9].GetString(); - std::string databaseS = fields[10].GetString(); + if (logonRequest->platform() != "Win" && logonRequest->platform() != "Wn64" && logonRequest->platform() != "Mc64") + { + TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s attempted to log in from an unsupported platform (using %s)!", GetClientInfo().c_str(), logonRequest->platform().c_str()); + return ERROR_BAD_PLATFORM; + } - _gameAccounts.resize(result->GetRowCount()); - uint32 i = 0; - do + if (GetLocaleByName(logonRequest->locale()) == LOCALE_enUS && logonRequest->locale() != "enUS") { - _gameAccounts[i++].LoadResult(result->Fetch() + 11); + TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s attempted to log in with unsupported locale (using %s)!", GetClientInfo().c_str(), logonRequest->locale().c_str()); + return ERROR_BAD_LOCALE; + } - } while (result->NextRow()); + _locale = logonRequest->locale(); + _os = logonRequest->platform(); + + ip::tcp::endpoint const& endpoint = sLoginService.GetAddressForClient(GetRemoteIpAddress()); + + challenge::v1::ChallengeExternalRequest externalChallenge; + externalChallenge.set_payload_type("web_auth_url"); + externalChallenge.set_payload(Trinity::StringFormat("https://%s:%u/bnetserver/login/", endpoint.address().to_string().c_str(), endpoint.port())); + Service<challenge::v1::ChallengeListener>(this).OnExternalChallenge(&externalChallenge); + return ERROR_OK; +} + +uint32 Battlenet::Session::HandleVerifyWebCredentials(authentication::v1::VerifyWebCredentialsRequest const* verifyWebCredentialsRequest) +{ + authentication::v1::LogonResult logonResult; + logonResult.set_error_code(0); + _accountInfo = sLoginService.VerifyLoginTicket(verifyWebCredentialsRequest->web_credentials()); + if (!_accountInfo) + return ERROR_DENIED; std::string ip_address = GetRemoteIpAddress().to_string(); + // If the IP is 'locked', check that the player comes indeed from the correct IP address if (_accountInfo->IsLockedToIP) { - TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] Account '%s' is locked to IP - '%s' is logging in from '%s'", _accountInfo->Login.c_str(), _accountInfo->LastIP.c_str(), ip_address.c_str()); + TC_LOG_DEBUG("session", "[Session::HandleVerifyWebCredentials] Account '%s' is locked to IP - '%s' is logging in from '%s'", + _accountInfo->Login.c_str(), _accountInfo->LastIP.c_str(), ip_address.c_str()); if (_accountInfo->LastIP != ip_address) - { - Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); - logonResponse->SetAuthResult(AUTH_ACCOUNT_LOCKED); - AsyncWrite(logonResponse); - return; - } + return ERROR_RISK_ACCOUNT_LOCKED; } else { - TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] Account '%s' is not locked to ip", _accountInfo->Login.c_str()); + TC_LOG_DEBUG("session", "[Session::HandleVerifyWebCredentials] Account '%s' is not locked to ip", _accountInfo->Login.c_str()); if (_accountInfo->LockCountry.empty() || _accountInfo->LockCountry == "00") - TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] Account '%s' is not locked to country", _accountInfo->Login.c_str()); + TC_LOG_DEBUG("session", "[Session::HandleVerifyWebCredentials] Account '%s' is not locked to country", _accountInfo->Login.c_str()); else if (!_accountInfo->LockCountry.empty() && !_ipCountry.empty()) { - TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] Account '%s' is locked to country: '%s' Player country is '%s'", _accountInfo->Login.c_str(), _accountInfo->LockCountry.c_str(), _ipCountry.c_str()); + TC_LOG_DEBUG("session", "[Session::HandleVerifyWebCredentials] Account '%s' is locked to country: '%s' Player country is '%s'", + _accountInfo->Login.c_str(), _accountInfo->LockCountry.c_str(), _ipCountry.c_str()); + if (_ipCountry != _accountInfo->LockCountry) - { - Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); - logonResponse->SetAuthResult(AUTH_ACCOUNT_LOCKED); - AsyncWrite(logonResponse); - return; - } + return ERROR_RISK_ACCOUNT_LOCKED; } } @@ -271,886 +281,391 @@ void Battlenet::Session::HandleLogonRequestCallback(PreparedQueryResult result) { if (_accountInfo->IsPermanenetlyBanned) { - Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); - logonResponse->SetAuthResult(LOGIN_BANNED); - AsyncWrite(logonResponse); - TC_LOG_DEBUG("session", "'%s:%d' [Battlenet::LogonRequest] Banned account %s tried to login!", ip_address.c_str(), GetRemotePort(), _accountInfo->Login.c_str()); - return; + TC_LOG_DEBUG("session", "%s [Session::HandleVerifyWebCredentials] Banned account %s tried to login!", GetClientInfo().c_str(), _accountInfo->Login.c_str()); + return ERROR_GAME_ACCOUNT_BANNED; } else { - Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); - logonResponse->SetAuthResult(LOGIN_SUSPENDED); - AsyncWrite(logonResponse); - TC_LOG_DEBUG("session", "'%s:%d' [Battlenet::LogonRequest] Temporarily banned account %s tried to login!", ip_address.c_str(), GetRemotePort(), _accountInfo->Login.c_str()); - return; + TC_LOG_DEBUG("session", "%s [Session::HandleVerifyWebCredentials] Temporarily banned account %s tried to login!", GetClientInfo().c_str(), _accountInfo->Login.c_str()); + return ERROR_GAME_ACCOUNT_SUSPENDED; } } - SHA256Hash sha; - sha.UpdateData(_accountInfo->Login); - sha.Finalize(); - - I.SetBinary(sha.GetDigest(), sha.GetLength()); - - ModuleInfo* password = sModuleMgr->CreateModule(_os, "Password"); - ModuleInfo* thumbprint = sModuleMgr->CreateModule(_os, "Thumbprint"); - - if (databaseV.size() != size_t(BufferSizes::SRP_6_V) * 2 || databaseS.size() != size_t(BufferSizes::SRP_6_S) * 2) - _SetVSFields(pStr); - else + logonResult.mutable_account_id()->set_low(_accountInfo->Id); + logonResult.mutable_account_id()->set_high(UI64LIT(0x100000000000000)); + for (auto itr = _accountInfo->GameAccounts.begin(); itr != _accountInfo->GameAccounts.end(); ++itr) { - s.SetHexStr(databaseS.c_str()); - v.SetHexStr(databaseV.c_str()); + if (!itr->second.IsBanned) + { + EntityId* gameAccountId = logonResult.add_game_account_id(); + gameAccountId->set_low(itr->second.Id); + gameAccountId->set_high(UI64LIT(0x200000200576F57)); + } } - b.SetRand(128 * 8); - B = ((v * k) + g.ModExp(b, N)) % N; - BigNumber unk; - unk.SetRand(128 * 8); - - BitStream passwordData; - uint8 state = 0; - passwordData.WriteBytes(&state, 1); - passwordData.WriteBytes(I.AsByteArray(32).get(), 32); - passwordData.WriteBytes(s.AsByteArray(32).get(), 32); - passwordData.WriteBytes(B.AsByteArray(128).get(), 128); - passwordData.WriteBytes(unk.AsByteArray(128).get(), 128); - - password->DataSize = passwordData.GetSize(); - password->Data = new uint8[password->DataSize]; - memcpy(password->Data, passwordData.GetBuffer(), password->DataSize); - - _modulesWaitingForData.push(MODULE_PASSWORD); - - Authentication::ProofRequest* proofRequest = new Authentication::ProofRequest(); - proofRequest->Modules.push_back(password); - // if has authenticator, send Token module - proofRequest->Modules.push_back(thumbprint); - AsyncWrite(proofRequest); -} + if (!_ipCountry.empty()) + logonResult.set_geoip_country(_ipCountry); -void Battlenet::Session::HandleResumeRequest(Authentication::ResumeRequest const& resumeRequest) -{ - if (_queryCallback) - { - Authentication::ResumeResponse* logonResponse = new Authentication::ResumeResponse(); - logonResponse->SetAuthResult(AUTH_LOGON_TOO_FAST); - AsyncWrite(logonResponse); - TC_LOG_DEBUG("session", "[Battlenet::ResumeRequest] %s attempted to log too quick after previous attempt!", GetClientInfo().c_str()); - return; - } - - std::string login = resumeRequest.Account; - _locale = resumeRequest.Common.Locale; - _os = resumeRequest.Common.Platform; - auto baseComponent = std::find_if(resumeRequest.Common.Versions.begin(), resumeRequest.Common.Versions.end(), [](Version::Record const& c) { return c.ProgramId == "base"; }); - if (baseComponent != resumeRequest.Common.Versions.end()) - _build = baseComponent->Version; + BigNumber k; + k.SetRand(8 * 64); + logonResult.set_session_key(k.AsByteArray(64).get(), 64); - Utf8ToUpperOnlyLatin(login); - PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_RECONNECT_INFO); - stmt->setString(0, login); - stmt->setString(1, resumeRequest.GameAccountName); + _authed = true; - _queryCallback = std::bind(&Battlenet::Session::HandleResumeRequestCallback, this, std::placeholders::_1); - _queryFuture = LoginDatabase.AsyncQuery(stmt); + Service<authentication::v1::AuthenticationListener>(this).OnLogonComplete(&logonResult); + return ERROR_OK; } -void Battlenet::Session::HandleResumeRequestCallback(PreparedQueryResult result) +uint32 Battlenet::Session::HandleGetAccountState(account::v1::GetAccountStateRequest const* request, account::v1::GetAccountStateResponse* response) { - if (!result) - { - Authentication::ResumeResponse* resumeResponse = new Authentication::ResumeResponse(); - resumeResponse->SetAuthResult(AUTH_UNKNOWN_ACCOUNT); - AsyncWrite(resumeResponse); - return; - } - - Field* fields = result->Fetch(); - _accountInfo->LoadResult(fields); - K.SetHexStr(fields[8].GetString().c_str()); - - _gameAccounts.resize(1); - _gameAccountInfo = &_gameAccounts[0]; - _gameAccountInfo->LoadResult(fields + 9); - - ModuleInfo* thumbprint = sModuleMgr->CreateModule(_os, "Thumbprint"); - ModuleInfo* resume = sModuleMgr->CreateModule(_os, "Resume"); - BitStream resumeData; - uint8 state = 0; - _reconnectProof.SetRand(16 * 8); + if (!_authed) + return ERROR_DENIED; - resumeData.WriteBytes(&state, 1); - resumeData.WriteBytes(_reconnectProof.AsByteArray().get(), 16); - - resume->DataSize = resumeData.GetSize(); - resume->Data = new uint8[resume->DataSize]; - memcpy(resume->Data, resumeData.GetBuffer(), resume->DataSize); + if (request->options().field_privacy_info()) + { + response->mutable_state()->mutable_privacy_info()->set_is_using_rid(false); + response->mutable_state()->mutable_privacy_info()->set_is_real_id_visible_for_view_friends(false); + response->mutable_state()->mutable_privacy_info()->set_is_hidden_from_friend_finder(true); - _modulesWaitingForData.push(MODULE_RESUME); + response->mutable_tags()->set_privacy_info_tag(0xD7CA834D); + } - Authentication::ProofRequest* proofRequest = new Authentication::ProofRequest(); - proofRequest->Modules.push_back(thumbprint); - proofRequest->Modules.push_back(resume); - AsyncWrite(proofRequest); + return ERROR_OK; } -void Battlenet::Session::HandleProofResponse(Authentication::ProofResponse const& proofResponse) +uint32 Battlenet::Session::HandleGetGameAccountState(account::v1::GetGameAccountStateRequest const* request, account::v1::GetGameAccountStateResponse* response) { - if (_modulesWaitingForData.size() < proofResponse.Response.size()) - { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(AUTH_CORRUPTED_MODULE); - AsyncWrite(complete); - return; - } + if (!_authed) + return ERROR_DENIED; - ServerPacket* response = nullptr; - for (size_t i = 0; i < proofResponse.Response.size(); ++i) + if (request->options().field_game_level_info()) { - if (!(this->*(ModuleHandlers[_modulesWaitingForData.front()]))(proofResponse.Response[i], &response)) - break; + auto itr = _accountInfo->GameAccounts.find(request->game_account_id().low()); + if (itr != _accountInfo->GameAccounts.end()) + { + response->mutable_state()->mutable_game_level_info()->set_name(itr->second.DisplayName); + response->mutable_state()->mutable_game_level_info()->set_program(5730135); // WoW + } - _modulesWaitingForData.pop(); + response->mutable_tags()->set_game_level_info_tag(0x5C46D483); } - if (!response) + if (request->options().field_game_status()) { - response = new Authentication::LogonResponse(); - static_cast<Authentication::LogonResponse*>(response)->SetAuthResult(AUTH_INTERNAL_ERROR); - } - - AsyncWrite(response); -} - -void Battlenet::Session::HandlePing(Connection::Ping const& /*ping*/) -{ - AsyncWrite(new Connection::Pong()); -} + auto itr = _accountInfo->GameAccounts.find(request->game_account_id().low()); + if (itr != _accountInfo->GameAccounts.end()) + { + response->mutable_state()->mutable_game_status()->set_is_suspended(itr->second.IsBanned); + response->mutable_state()->mutable_game_status()->set_is_banned(itr->second.IsPermanenetlyBanned); + } -void Battlenet::Session::HandleEnableEncryption(Connection::EnableEncryption& enableEncryption) -{ - _crypt.Init(&K); - _crypt.DecryptRecv(enableEncryption.GetRemainingData(), enableEncryption.GetRemainingSize()); -} + response->mutable_state()->mutable_game_status()->set_program(5730135); // WoW + response->mutable_tags()->set_game_status_tag(0x98B75F99); + } -void Battlenet::Session::HandleLogoutRequest(Connection::LogoutRequest const& /*logoutRequest*/) -{ - PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_SESSION_KEY); - stmt->setString(0, ""); - stmt->setBool(1, false); - stmt->setUInt32(2, _accountInfo->Id); - LoginDatabase.Execute(stmt); + return ERROR_OK; } -void Battlenet::Session::HandleConnectionClosing(Connection::ConnectionClosing const& /*connectionClosing*/) +std::unordered_map<std::string, Battlenet::Session::ClientRequestHandler> const Battlenet::Session::ClientRequestHandlers = { -} + { "Command_RealmListTicketRequest_v1_b9", &Battlenet::Session::GetRealmListTicket }, + { "Command_LastCharPlayedRequest_v1_b9", &Battlenet::Session::GetLastCharPlayed }, + { "Command_RealmListRequest_v1_b9", &Battlenet::Session::GetRealmList }, + { "Command_RealmJoinRequest_v1_b9", &Battlenet::Session::JoinRealm }, +}; -void Battlenet::Session::HandleListSubscribeRequest(WoWRealm::ListSubscribeRequest const& /*listSubscribeRequest*/) +uint32 Battlenet::Session::HandleProcessClientRequest(game_utilities::v1::ClientRequest const* request, game_utilities::v1::ClientResponse* response) { - if (_subscribedToRealmListUpdates || _queryCallback) - return; - - PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_CHARACTER_COUNTS); - stmt->setUInt32(0, _gameAccountInfo->Id); - - _queryCallback = std::bind(&Battlenet::Session::HandleListSubscribeRequestCallback, this, std::placeholders::_1); - _queryFuture = LoginDatabase.AsyncQuery(stmt); -} + if (!_authed) + return ERROR_DENIED; -void Battlenet::Session::HandleListSubscribeRequestCallback(PreparedQueryResult result) -{ - WoWRealm::ListSubscribeResponse* listSubscribeResponse = new WoWRealm::ListSubscribeResponse(); + Attribute const* command = nullptr; + std::unordered_map<std::string, Variant const*> params; - if (result) + for (int32 i = 0; i < request->attribute_size(); ++i) { - do - { - Field* fields = result->Fetch(); - listSubscribeResponse->ToonCounts.emplace_back(PrintableRealmHandle(fields[2].GetUInt8(), fields[3].GetUInt8(), fields[1].GetUInt32()), uint16(fields[0].GetUInt8())); - } while (result->NextRow()); + Attribute const& attr = request->attribute(i); + params[attr.name()] = &attr.value(); + if (strstr(attr.name().c_str(), "Command_") == attr.name().c_str()) + command = &attr; } - AsyncWrite(listSubscribeResponse); - - for (RealmList::RealmMap::value_type const& i : sRealmList->GetRealms()) - AsyncWrite(BuildListUpdate(&i.second)); - - AsyncWrite(new WoWRealm::ListComplete()); - - _subscribedToRealmListUpdates = true; -} - -void Battlenet::Session::HandleListUnsubscribe(WoWRealm::ListUnsubscribe const& /*listUnsubscribe*/) -{ - _subscribedToRealmListUpdates = false; -} - -void Battlenet::Session::HandleJoinRequestV2(WoWRealm::JoinRequestV2 const& joinRequest) -{ - WoWRealm::JoinResponseV2* joinResponse = new WoWRealm::JoinResponseV2(); - Realm const* realm = sRealmList->GetRealm(joinRequest.Id); - if (!realm || realm->Flags & (REALM_FLAG_VERSION_MISMATCH | REALM_FLAG_OFFLINE) || realm->Build != _build) + if (!command) { - joinResponse->Type = WoWRealm::JoinResponseV2::FAILURE; - AsyncWrite(joinResponse); - return; + TC_LOG_ERROR("session.rpc", "%s sent ClientRequest with no command.", GetClientInfo().c_str()); + return ERROR_RPC_MALFORMED_REQUEST; } - joinResponse->Success.ServerSalt = rand32(); - - uint8 sessionKey[40]; - HmacSha1 hmac(K.GetNumBytes(), K.AsByteArray().get()); - hmac.UpdateData((uint8*)"WoW\0", 4); - hmac.UpdateData((uint8*)&joinRequest.ClientSalt, 4); - hmac.UpdateData((uint8*)&joinResponse->Success.ServerSalt, 4); - hmac.Finalize(); - - memcpy(sessionKey, hmac.GetDigest(), hmac.GetLength()); - - HmacSha1 hmac2(K.GetNumBytes(), K.AsByteArray().get()); - hmac2.UpdateData((uint8*)"WoW\0", 4); - hmac2.UpdateData((uint8*)&joinResponse->Success.ServerSalt, 4); - hmac2.UpdateData((uint8*)&joinRequest.ClientSalt, 4); - hmac2.Finalize(); - - memcpy(sessionKey + hmac.GetLength(), hmac2.GetDigest(), hmac2.GetLength()); - - LoginDatabase.DirectPExecute("UPDATE account SET sessionkey = '%s', last_ip = '%s', last_login = NOW(), locale = %u, failed_logins = 0, os = '%s' WHERE id = %u", - ByteArrayToHexStr(sessionKey, 40, true).c_str(), GetRemoteIpAddress().to_string().c_str(), GetLocaleByName(_locale), _os.c_str(), _gameAccountInfo->Id); - - joinResponse->Success.IPv4.push_back(realm->GetAddressForClient(GetRemoteIpAddress())); - - AsyncWrite(joinResponse); -} - -void Battlenet::Session::HandleGetStreamItemsRequest(Cache::GetStreamItemsRequest const& getStreamItemsRequest) -{ - if (getStreamItemsRequest.Stream.Type != Cache::GetStreamItemsRequest::StreamId::DESCRIPTION) - return; - - if (ModuleInfo* module = sModuleMgr->CreateModule(getStreamItemsRequest.Locale, getStreamItemsRequest.Stream.Description.ItemName)) + auto itr = ClientRequestHandlers.find(command->name()); + if (itr == ClientRequestHandlers.end()) { - Cache::GetStreamItemsResponse* getStreamItemsResponse = new Cache::GetStreamItemsResponse(); - getStreamItemsResponse->Token = getStreamItemsRequest.Token; - getStreamItemsResponse->Items.push_back(module); - AsyncWrite(getStreamItemsResponse); + TC_LOG_ERROR("session.rpc", "%s sent ClientRequest with unknown command %s.", GetClientInfo().c_str(), command->name().c_str()); + return ERROR_RPC_NOT_IMPLEMENTED; } -} -inline std::string PacketToStringHelper(Battlenet::ClientPacket const* packet) -{ - if (sLog->ShouldLog("session.packets", LOG_LEVEL_TRACE)) - return packet->ToString(); - - return sPacketManager.GetClientPacketName(packet->GetHeader()); + return (this->*itr->second)(params, response); } -inline std::string PacketToStringHelper(Battlenet::ServerPacket const* packet) +inline Variant const* GetParam(std::unordered_map<std::string, Variant const*> const& params, char const* paramName) { - if (sLog->ShouldLog("session.packets", LOG_LEVEL_TRACE)) - return packet->ToString(); - - return sPacketManager.GetServerPacketName(packet->GetHeader()); + auto itr = params.find(paramName); + return itr != params.end() ? itr->second : nullptr; } -void Battlenet::Session::ReadHandler() +uint32 Battlenet::Session::GetRealmListTicket(std::unordered_map<std::string, Variant const*> const& params, game_utilities::v1::ClientResponse* response) { - BitStream stream(std::move(GetReadBuffer())); - _crypt.DecryptRecv(stream.GetBuffer(), stream.GetSize()); - - while (!stream.IsRead()) + if (Variant const* identity = GetParam(params, "Param_Identity")) { - try + ::JSON::RealmList::RealmListTicketIdentity data; + std::size_t jsonStart = identity->blob_value().find(':'); + if (jsonStart != std::string::npos && ::JSON::Deserialize(identity->blob_value().substr(jsonStart + 1), &data)) { - PacketHeader header; - header.Command = stream.Read<uint32>(6); - if (stream.Read<bool>(1)) - header.Channel = stream.Read<int32>(4); - - if (header.Channel != AUTHENTICATION && (header.Channel != CONNECTION || header.Command != Connection::CMSG_PING) && !_authed) - { - TC_LOG_DEBUG("session.packets", "%s Received not allowed %s. Client has not authed yet.", GetClientInfo().c_str(), header.ToString().c_str()); - CloseSocket(); - return; - } + auto itr = _accountInfo->GameAccounts.find(data.gameaccountid()); + if (itr != _accountInfo->GameAccounts.end()) + _gameAccountInfo = &itr->second; + } + } - if (ClientPacket* packet = sPacketManager.CreateClientPacket(header, stream)) - { - if (sPacketManager.IsHandled(header)) - TC_LOG_DEBUG("session.packets", "%s Received %s", GetClientInfo().c_str(), PacketToStringHelper(packet).c_str()); + if (!_gameAccountInfo) + return ERROR_UTIL_SERVER_INVALID_IDENTITY_ARGS; - packet->CallHandler(this); - delete packet; - } - else if (sPacketManager.GetClientPacketName(header)) - { - LogUnhandledPacket(header); - break; - } - else + if (Variant const* clientInfo = GetParam(params, "Param_ClientInfo")) + { + ::JSON::RealmList::RealmListTicketClientInformation data; + std::size_t jsonStart = clientInfo->blob_value().find(':'); + if (jsonStart != std::string::npos && ::JSON::Deserialize(clientInfo->blob_value().substr(jsonStart + 1), &data)) + { + if (_clientSecret.size() == data.info().secret().size()) { - TC_LOG_DEBUG("session.packets", "%s Received unknown %s", GetClientInfo().c_str(), header.ToString().c_str()); - break; + _build = data.info().version().versionbuild(); + memcpy(_clientSecret.data(), data.info().secret().data(), _clientSecret.size()); } - - stream.AlignToNextByte(); - } - catch (BitStreamPositionException const& e) - { - TC_LOG_ERROR("session.packets", "%s Exception thrown during packet processing %s", GetClientInfo().c_str(), e.what()); - CloseSocket(); - return; } } - GetReadBuffer().Resize(size_t(BufferSizes::Read)); - AsyncRead(); -} + if (!_build) + return ERROR_WOW_SERVICES_DENIED_REALM_LIST_TICKET; -void Battlenet::Session::Start() -{ - std::string ip_address = GetRemoteIpAddress().to_string(); - TC_LOG_TRACE("session", "Accepted connection from %s", ip_address.c_str()); + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_LAST_LOGIN_INFO); + stmt->setString(0, GetRemoteIpAddress().to_string()); + stmt->setUInt8(1, GetLocaleByName(_locale)); + stmt->setString(2, _os); + stmt->setUInt32(3, _accountInfo->Id); - PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_IP_INFO); - stmt->setString(0, ip_address); - stmt->setUInt32(1, inet_addr(ip_address.c_str())); + LoginDatabase.Execute(stmt); - _queryCallback = std::bind(&Battlenet::Session::CheckIpCallback, this, std::placeholders::_1); - _queryFuture = LoginDatabase.AsyncQuery(stmt); + Attribute* attribute = response->add_attribute(); + attribute->set_name("Param_RealmListTicket"); + attribute->mutable_value()->set_blob_value("AuthRealmListTicket"); + + return ERROR_OK; } -void Battlenet::Session::CheckIpCallback(PreparedQueryResult result) +uint32 Battlenet::Session::GetLastCharPlayed(std::unordered_map<std::string, Variant const*> const& params, game_utilities::v1::ClientResponse* response) { - if (result) + if (Variant const* subRegion = GetParam(params, "Command_LastCharPlayedRequest_v1_b9")) { - bool banned = false; - do + auto lastPlayerChar = _gameAccountInfo->LastPlayedCharacters.find(subRegion->string_value()); + if (lastPlayerChar != _gameAccountInfo->LastPlayedCharacters.end()) { - Field* fields = result->Fetch(); - if (fields[0].GetUInt64() != 0) - banned = true; + std::vector<uint8> compressed = sRealmList->GetRealmEntryJSON(lastPlayerChar->second.RealmId, _build); - if (!fields[1].GetString().empty()) - _ipCountry = fields[1].GetString(); + if (compressed.empty()) + return ERROR_UTIL_SERVER_FAILED_TO_SERIALIZE_RESPONSE; - } while (result->NextRow()); + Attribute* attribute = response->add_attribute(); + attribute->set_name("Param_RealmEntry"); + attribute->mutable_value()->set_blob_value(compressed.data(), compressed.size()); - if (banned) - { - Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); - logonResponse->SetAuthResult(AUTH_INTERNAL_ERROR); - AsyncWrite(logonResponse); - TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] Banned ip '%s:%d' tries to login!", GetRemoteIpAddress().to_string().c_str(), GetRemotePort()); - return; + attribute = response->add_attribute(); + attribute->set_name("Param_CharacterName"); + attribute->mutable_value()->set_string_value(lastPlayerChar->second.CharacterName); + + attribute = response->add_attribute(); + attribute->set_name("Param_CharacterGUID"); + attribute->mutable_value()->set_blob_value(&lastPlayerChar->second.CharacterGUID, sizeof(lastPlayerChar->second.CharacterGUID)); + + attribute = response->add_attribute(); + attribute->set_name("Param_LastPlayedTime"); + attribute->mutable_value()->set_int_value(int32(lastPlayerChar->second.LastPlayedTime)); } + + return ERROR_OK; } - AsyncRead(); + return ERROR_UTIL_SERVER_UNKNOWN_REALM; } -bool Battlenet::Session::Update() +uint32 Battlenet::Session::GetRealmList(std::unordered_map<std::string, Variant const*> const& params, game_utilities::v1::ClientResponse* response) { - EncryptableBuffer* queued; - MessageBuffer buffer((std::size_t(BufferSizes::Read))); - while (_bufferQueue.Dequeue(queued)) - { - std::size_t packetSize = queued->Buffer.GetActiveSize(); - if (queued->Encrypt) - _crypt.EncryptSend(queued->Buffer.GetReadPointer(), packetSize); - - if (buffer.GetRemainingSpace() < packetSize) - { - QueuePacket(std::move(buffer)); - buffer.Resize(std::size_t(BufferSizes::Read)); - } + if (!_gameAccountInfo) + return ERROR_USER_SERVER_BAD_WOW_ACCOUNT; - if (buffer.GetRemainingSpace() >= packetSize) - buffer.Write(queued->Buffer.GetReadPointer(), packetSize); - else // single packet larger than 16384 bytes - client will reject. - QueuePacket(std::move(queued->Buffer)); + std::string subRegionId; + if (Variant const* subRegion = GetParam(params, "Command_RealmListRequest_v1_b9")) + subRegionId = subRegion->string_value(); - delete queued; - } + std::vector<uint8> compressed = sRealmList->GetRealmList(_build, subRegionId); - if (buffer.GetActiveSize() > 0) - QueuePacket(std::move(buffer)); + if (compressed.empty()) + return ERROR_UTIL_SERVER_FAILED_TO_SERIALIZE_RESPONSE; - if (!BattlenetSocket::Update()) - return false; + Attribute* attribute = response->add_attribute(); + attribute->set_name("Param_RealmList"); + attribute->mutable_value()->set_blob_value(compressed.data(), compressed.size()); - if (_queryFuture.valid() && _queryFuture.wait_for(std::chrono::seconds(0)) == std::future_status::ready) + ::JSON::RealmList::RealmCharacterCountList realmCharacterCounts; + for (auto const& characterCount : _gameAccountInfo->CharacterCounts) { - auto callback = _queryCallback; - _queryCallback = nullptr; - callback(_queryFuture.get()); + ::JSON::RealmList::RealmCharacterCountEntry* countEntry = realmCharacterCounts.add_counts(); + countEntry->set_wowrealmaddress(characterCount.first); + countEntry->set_count(characterCount.second); } - return true; -} - -void Battlenet::Session::AsyncWrite(ServerPacket* packet) -{ - if (!IsOpen()) - { - delete packet; - return; - } + std::string json = "JSONRealmCharacterCountList:" + ::JSON::Serialize(realmCharacterCounts); - TC_LOG_DEBUG("session.packets", "%s Sending %s", GetClientInfo().c_str(), PacketToStringHelper(packet).c_str()); + uLongf compressedLength = compressBound(json.length()); + compressed.resize(4 + compressedLength); + *reinterpret_cast<uint32*>(compressed.data()) = json.length() + 1; - packet->Write(); + if (compress(compressed.data() + 4, &compressedLength, reinterpret_cast<uint8 const*>(json.c_str()), json.length() + 1) != Z_OK) + return ERROR_UTIL_SERVER_FAILED_TO_SERIALIZE_RESPONSE; - EncryptableBuffer* buffer = new EncryptableBuffer(); - buffer->Buffer.Write(packet->GetData(), packet->GetSize()); - buffer->Encrypt = _crypt.IsInitialized(); - delete packet; - - _bufferQueue.Enqueue(buffer); + attribute = response->add_attribute(); + attribute->set_name("Param_CharacterCountList"); + attribute->mutable_value()->set_blob_value(compressed.data(), compressedLength + 4); + return ERROR_OK; } -inline void ReplaceResponse(Battlenet::ServerPacket** oldResponse, Battlenet::ServerPacket* newResponse) +uint32 Battlenet::Session::JoinRealm(std::unordered_map<std::string, Variant const*> const& params, game_utilities::v1::ClientResponse* response) { - if (*oldResponse) - delete *oldResponse; + if (Variant const* realmAddress = GetParam(params, "Param_RealmAddress")) + return sRealmList->JoinRealm(realmAddress->uint_value(), _build, GetRemoteIpAddress(), _clientSecret, GetLocaleByName(_locale), _os, _gameAccountInfo->Name, response); - *oldResponse = newResponse; + return ERROR_WOW_SERVICES_INVALID_JOIN_TICKET; } -bool Battlenet::Session::HandlePasswordModule(BitStream* dataStream, ServerPacket** response) +uint32 Battlenet::Session::HandleGetAllValuesForAttribute(game_utilities::v1::GetAllValuesForAttributeRequest const* request, game_utilities::v1::GetAllValuesForAttributeResponse* response) { - if (dataStream->GetSize() != 1 + 128 + 32 + 128) - { - Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); - logonResponse->SetAuthResult(AUTH_CORRUPTED_MODULE); - ReplaceResponse(response, logonResponse); - return false; - } + if (!_authed) + return ERROR_DENIED; - if (dataStream->Read<uint8>(8) != 2) // State + if (request->attribute_key() == "Command_RealmListRequest_v1_b9") { - Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); - logonResponse->SetAuthResult(AUTH_CORRUPTED_MODULE); - ReplaceResponse(response, logonResponse); - return false; + sRealmList->WriteSubRegions(response); + return ERROR_OK; } - BigNumber A, clientM1, clientChallenge; - A.SetBinary(dataStream->ReadBytes(128).get(), 128); - clientM1.SetBinary(dataStream->ReadBytes(32).get(), 32); - clientChallenge.SetBinary(dataStream->ReadBytes(128).get(), 128); + return ERROR_RPC_NOT_IMPLEMENTED; +} - if (A.IsZero()) +void Battlenet::Session::HandshakeHandler(boost::system::error_code const& error) +{ + if (error) { - Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); - logonResponse->SetAuthResult(AUTH_CORRUPTED_MODULE); - ReplaceResponse(response, logonResponse); - return false; + TC_LOG_ERROR("session", "%s SSL Handshake failed %s", GetClientInfo().c_str(), error.message().c_str()); + CloseSocket(); + return; } - SHA256Hash sha; - sha.UpdateBigNumbers(&A, &B, NULL); - sha.Finalize(); - - BigNumber u; - u.SetBinary(sha.GetDigest(), sha.GetLength()); - - BigNumber S = ((A * v.ModExp(u, N)) % N).ModExp(b, N); - - uint8 S_bytes[128]; - memcpy(S_bytes, S.AsByteArray(128).get(), 128); + AsyncRead(); +} - uint8 part1[64]; - uint8 part2[64]; +template<bool(Battlenet::Session::*processMethod)(), MessageBuffer Battlenet::Session::*outputBuffer> +inline bool PartialProcessPacket(Battlenet::Session* session, MessageBuffer& inputBuffer) +{ + MessageBuffer& buffer = session->*outputBuffer; - for (int i = 0; i < 64; ++i) + // We have full read header, now check the data payload + if (buffer.GetRemainingSpace() > 0) { - part1[i] = S_bytes[i * 2]; - part2[i] = S_bytes[i * 2 + 1]; + // need more data in the payload + std::size_t readDataSize = std::min(inputBuffer.GetActiveSize(), buffer.GetRemainingSpace()); + buffer.Write(inputBuffer.GetReadPointer(), readDataSize); + inputBuffer.ReadCompleted(readDataSize); } - SHA256Hash part1sha, part2sha; - part1sha.UpdateData(part1, 64); - part1sha.Finalize(); - part2sha.UpdateData(part2, 64); - part2sha.Finalize(); - - uint8 sessionKey[SHA256_DIGEST_LENGTH * 2]; - for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i) + if (buffer.GetRemainingSpace() > 0) { - sessionKey[i * 2] = part1sha.GetDigest()[i]; - sessionKey[i * 2 + 1] = part2sha.GetDigest()[i]; - } - - K.SetBinary(sessionKey, SHA256_DIGEST_LENGTH * 2); - - BigNumber M1; - - uint8 hash[SHA256_DIGEST_LENGTH]; - sha.Initialize(); - sha.UpdateBigNumbers(&N, NULL); - sha.Finalize(); - memcpy(hash, sha.GetDigest(), sha.GetLength()); - - sha.Initialize(); - sha.UpdateBigNumbers(&g, NULL); - sha.Finalize(); - - for (int i = 0; i < sha.GetLength(); ++i) - hash[i] ^= sha.GetDigest()[i]; - - SHA256Hash shaI; - shaI.UpdateData(ByteArrayToHexStr(I.AsByteArray().get(), 32)); - shaI.Finalize(); - - // Concat all variables for M1 hash - sha.Initialize(); - sha.UpdateData(hash, SHA256_DIGEST_LENGTH); - sha.UpdateData(shaI.GetDigest(), shaI.GetLength()); - sha.UpdateBigNumbers(&s, &A, &B, &K, NULL); - sha.Finalize(); - - M1.SetBinary(sha.GetDigest(), sha.GetLength()); - - if (memcmp(M1.AsByteArray().get(), clientM1.AsByteArray().get(), 32)) - { - PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_FAILED_LOGINS); - stmt->setString(0, _accountInfo->Login); - LoginDatabase.Execute(stmt); - - Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); - logonResponse->SetAuthResult(AUTH_UNKNOWN_ACCOUNT); - ReplaceResponse(response, logonResponse); - TC_LOG_DEBUG("session", "[Battlenet::Password] %s attempted to log in with invalid password!", GetClientInfo().c_str()); + // Couldn't receive the whole data this time. + ASSERT(inputBuffer.GetActiveSize() == 0); return false; } - if (_gameAccounts.empty()) + // just received fresh new payload + if (!(session->*processMethod)()) { - Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); - logonResponse->SetAuthResult(LOGIN_NO_GAME_ACCOUNT); - ReplaceResponse(response, logonResponse); - TC_LOG_DEBUG("session", "[Battlenet::Password] %s does not have any linked game accounts!", GetClientInfo().c_str()); + session->CloseSocket(); return false; } - BigNumber M; - sha.Initialize(); - sha.UpdateBigNumbers(&A, &M1, &K, NULL); - sha.Finalize(); - M.SetBinary(sha.GetDigest(), sha.GetLength()); - - BigNumber serverProof; - serverProof.SetRand(128 * 8); // just send garbage, server signature check is patched out in client - - BitStream stream; - ModuleInfo* password = sModuleMgr->CreateModule(_os, "Password"); - uint8 state = 3; - - stream.WriteBytes(&state, 1); - stream.WriteBytes(M.AsByteArray(32).get(), 32); - stream.WriteBytes(serverProof.AsByteArray(128).get(), 128); - - password->DataSize = stream.GetSize(); - password->Data = new uint8[password->DataSize]; - memcpy(password->Data, stream.GetBuffer(), password->DataSize); - - Authentication::ProofRequest* proofRequest = new Authentication::ProofRequest(); - proofRequest->Modules.push_back(password); - if (_gameAccounts.size() > 1) - { - BitStream accounts; - state = 0; - accounts.WriteBytes(&state, 1); - accounts.Write(_gameAccounts.size(), 8); - for (GameAccountInfo const& gameAccount : _gameAccounts) - { - accounts.Write(2, 8); - accounts.WriteString(gameAccount.DisplayName, 8); - } - - ModuleInfo* selectGameAccount = sModuleMgr->CreateModule(_os, "SelectGameAccount"); - selectGameAccount->DataSize = accounts.GetSize(); - selectGameAccount->Data = new uint8[selectGameAccount->DataSize]; - memcpy(selectGameAccount->Data, accounts.GetBuffer(), selectGameAccount->DataSize); - proofRequest->Modules.push_back(selectGameAccount); - _modulesWaitingForData.push(MODULE_SELECT_GAME_ACCOUNT); - } - else - { - _gameAccountInfo = &_gameAccounts[0]; - - if (_gameAccountInfo->IsBanned) - { - delete proofRequest; - - Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); - if (_gameAccountInfo->IsPermanenetlyBanned) - { - logonResponse->SetAuthResult(LOGIN_BANNED); - TC_LOG_DEBUG("session", "'%s:%d' [Battlenet::Password] Banned account %s tried to login!", GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _accountInfo->Login.c_str()); - } - else - { - logonResponse->SetAuthResult(LOGIN_SUSPENDED); - TC_LOG_DEBUG("session", "'%s:%d' [Battlenet::Password] Temporarily banned account %s tried to login!", GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _accountInfo->Login.c_str()); - } - - ReplaceResponse(response, logonResponse); - return false; - } - - proofRequest->Modules.push_back(sModuleMgr->CreateModule(_os, "RiskFingerprint")); - _modulesWaitingForData.push(MODULE_RISK_FINGERPRINT); - } - - ReplaceResponse(response, proofRequest); return true; } -bool Battlenet::Session::HandleSelectGameAccountModule(BitStream* dataStream, ServerPacket** response) +void Battlenet::Session::ReadHandler() { - if (dataStream->Read<uint8>(8) != 1) - { - Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); - logonResponse->SetAuthResult(AUTH_CORRUPTED_MODULE); - ReplaceResponse(response, logonResponse); - return false; - } - - dataStream->Read<uint8>(8); - std::string account = dataStream->ReadString(8); - if (account.empty()) - { - Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); - logonResponse->SetAuthResult(LOGIN_NO_GAME_ACCOUNT); - ReplaceResponse(response, logonResponse); - return false; - } + if (!IsOpen()) + return; - for (std::size_t i = 0; i < _gameAccounts.size(); ++i) + MessageBuffer& packet = GetReadBuffer(); + while (packet.GetActiveSize() > 0) { - if (_gameAccounts[i].DisplayName == account) - { - _gameAccountInfo = &_gameAccounts[i]; + if (!PartialProcessPacket<&Battlenet::Session::ReadHeaderLengthHandler, &Battlenet::Session::_headerLengthBuffer>(this, packet)) break; - } - } - if (!_gameAccountInfo) - { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(LOGIN_NO_GAME_ACCOUNT); - ReplaceResponse(response, complete); - TC_LOG_DEBUG("session", "[Battlenet::SelectGameAccount] %s attempted to log in with invalid game account name %s!", GetClientInfo().c_str(), account.c_str()); - return false; - } + if (!PartialProcessPacket<&Battlenet::Session::ReadHeaderHandler, &Battlenet::Session::_headerBuffer>(this, packet)) + break; - if (_gameAccountInfo->IsBanned) - { - Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); - if (_gameAccountInfo->IsPermanenetlyBanned) - { - logonResponse->SetAuthResult(LOGIN_BANNED); - TC_LOG_DEBUG("session", "'%s:%d' [Battlenet::SelectGameAccount] Banned account %s tried to login!", GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _accountInfo->Login.c_str()); - } - else - { - logonResponse->SetAuthResult(LOGIN_SUSPENDED); - TC_LOG_DEBUG("session", "'%s:%d' [Battlenet::SelectGameAccount] Temporarily banned account %s tried to login!", GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _accountInfo->Login.c_str()); - } + if (!PartialProcessPacket<&Battlenet::Session::ReadDataHandler, &Battlenet::Session::_packetBuffer>(this, packet)) + break; - ReplaceResponse(response, logonResponse); - return false; + _headerLengthBuffer.Reset(); + _headerBuffer.Reset(); } - Authentication::ProofRequest* proofRequest = new Authentication::ProofRequest(); - proofRequest->Modules.push_back(sModuleMgr->CreateModule(_os, "RiskFingerprint")); - ReplaceResponse(response, proofRequest); - - _modulesWaitingForData.push(MODULE_RISK_FINGERPRINT); - return true; + AsyncRead(); } -bool Battlenet::Session::HandleRiskFingerprintModule(BitStream* dataStream, ServerPacket** response) +bool Battlenet::Session::ReadHeaderLengthHandler() { - Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); - if (dataStream->Read<uint8>(8) == 1 && _accountInfo && _gameAccountInfo) - { - logonResponse->Result.Success.AccountId = _accountInfo->Id; - logonResponse->Result.Success.GameAccountName = _gameAccountInfo->Name; - logonResponse->Result.Success.GameAccountFlags = GAMEACCOUNT_FLAG_PROPASS; - logonResponse->Result.Success.LogonFailures = _accountInfo->FailedLogins; - - SQLTransaction trans = LoginDatabase.BeginTransaction(); - - PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_LAST_LOGIN_INFO); - stmt->setString(0, GetRemoteIpAddress().to_string()); - stmt->setUInt8(1, GetLocaleByName(_locale)); - stmt->setString(2, _os); - stmt->setUInt32(3, _accountInfo->Id); - trans->Append(stmt); - - stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_SESSION_KEY); - stmt->setString(0, K.AsHexStr()); - stmt->setBool(1, true); - stmt->setUInt32(2, _accountInfo->Id); - trans->Append(stmt); - - LoginDatabase.CommitTransaction(trans); - - _authed = true; - sSessionMgr.AddSession(this); - } - else - logonResponse->SetAuthResult(AUTH_BAD_VERSION_HASH); - - ReplaceResponse(response, logonResponse); + uint16 len = *reinterpret_cast<uint16*>(_headerLengthBuffer.GetReadPointer()); + EndianConvertReverse(len); + _headerBuffer.Resize(len); return true; } -bool Battlenet::Session::HandleResumeModule(BitStream* dataStream, ServerPacket** response) +bool Battlenet::Session::ReadHeaderHandler() { - if (dataStream->Read<uint8>(8) != 1) - { - Authentication::ResumeResponse* resumeResponse = new Authentication::ResumeResponse(); - resumeResponse->SetAuthResult(AUTH_CORRUPTED_MODULE); - ReplaceResponse(response, resumeResponse); - return false; - } - - static uint8 const ResumeClient = 0; - static uint8 const ResumeServer = 1; - - std::unique_ptr<uint8[]> clientChallenge = dataStream->ReadBytes(16); - std::unique_ptr<uint8[]> clientProof = dataStream->ReadBytes(32); - std::unique_ptr<uint8[]> serverChallenge = _reconnectProof.AsByteArray(16); - std::unique_ptr<uint8[]> sessionKey = K.AsByteArray(64); - - HmacSha256 clientPart(64, sessionKey.get()); - clientPart.UpdateData(&ResumeClient, 1); - clientPart.UpdateData(clientChallenge.get(), 16); - clientPart.UpdateData(serverChallenge.get(), 16); - clientPart.Finalize(); - - HmacSha256 serverPart(64, sessionKey.get()); - serverPart.UpdateData(&ResumeServer, 1); - serverPart.UpdateData(serverChallenge.get(), 16); - serverPart.UpdateData(clientChallenge.get(), 16); - serverPart.Finalize(); - - uint8 newSessionKey[64]; - memcpy(&newSessionKey[0], clientPart.GetDigest(), clientPart.GetLength()); - memcpy(&newSessionKey[32], serverPart.GetDigest(), serverPart.GetLength()); - - K.SetBinary(newSessionKey, 64); + Header header; + if (!header.ParseFromArray(_headerBuffer.GetReadPointer(), _headerBuffer.GetActiveSize())) + return true; - HmacSha256 proof(64, newSessionKey); - proof.UpdateData(&ResumeClient, 1); - proof.UpdateData(clientChallenge.get(), 16); - proof.UpdateData(serverChallenge.get(), 16); - proof.Finalize(); - - if (memcmp(proof.GetDigest(), clientProof.get(), serverPart.GetLength())) - { - PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_FAILED_LOGINS); - stmt->setString(0, _accountInfo->Login); - LoginDatabase.Execute(stmt); - - TC_LOG_DEBUG("session", "[Battlenet::Resume] %s attempted to reconnect with invalid password!", GetClientInfo().c_str()); - Authentication::ResumeResponse* resumeResponse = new Authentication::ResumeResponse(); - resumeResponse->SetAuthResult(AUTH_UNKNOWN_ACCOUNT); - ReplaceResponse(response, resumeResponse); - return false; - } - - PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_SESSION_KEY); - stmt->setString(0, K.AsHexStr()); - stmt->setBool(1, true); - stmt->setUInt32(2, _accountInfo->Id); - LoginDatabase.Execute(stmt); - - HmacSha256 serverProof(64, newSessionKey); - serverProof.UpdateData(&ResumeServer, 1); - serverProof.UpdateData(serverChallenge.get(), 16); - serverProof.UpdateData(clientChallenge.get(), 16); - serverProof.Finalize(); - - ModuleInfo* resume = sModuleMgr->CreateModule(_os, "Resume"); - - BitStream resumeData; - uint8 state = 2; - resumeData.WriteBytes(&state, 1); - resumeData.WriteBytes(serverProof.GetDigest(), serverProof.GetLength()); - - resume->DataSize = resumeData.GetSize(); - resume->Data = new uint8[resume->DataSize]; - memcpy(resume->Data, resumeData.GetBuffer(), resume->DataSize); - - Authentication::ResumeResponse* resumeResponse = new Authentication::ResumeResponse(); - resumeResponse->Result.Success.FinalRequest.push_back(resume); - ReplaceResponse(response, resumeResponse); - _authed = true; - sSessionMgr.AddSession(this); + _packetBuffer.Resize(header.size()); return true; } -bool Battlenet::Session::UnhandledModule(BitStream* /*dataStream*/, ServerPacket** response) +bool Battlenet::Session::ReadDataHandler() { - TC_LOG_ERROR("session.packets", "Unhandled module."); - Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); - logonResponse->SetAuthResult(AUTH_CORRUPTED_MODULE); - ReplaceResponse(response, logonResponse); - return false; -} - -void Battlenet::Session::UpdateRealms(std::vector<Realm const*>& realms, std::vector<RealmHandle>& deletedRealms) -{ - for (Realm const* realm : realms) - AsyncWrite(BuildListUpdate(realm)); + Header header; + header.ParseFromArray(_headerBuffer.GetReadPointer(), _headerBuffer.GetActiveSize()); - for (RealmHandle& deleted : deletedRealms) + if (header.service_id() != 0xFE) { - WoWRealm::ListUpdate* listUpdate = new WoWRealm::ListUpdate(); - listUpdate->State.Type = WoWRealm::ListUpdate::StateType::DELETED; - listUpdate->Id = deleted; - AsyncWrite(listUpdate); + sServiceDispatcher.Dispatch(this, header.service_hash(), header.token(), header.method_id(), std::move(_packetBuffer)); } -} - -Battlenet::WoWRealm::ListUpdate* Battlenet::Session::BuildListUpdate(Realm const* realm) const -{ - uint32 flag = realm->Flags; - if (realm->Build != _build) - flag |= REALM_FLAG_VERSION_MISMATCH; - - WoWRealm::ListUpdate* listUpdate = new WoWRealm::ListUpdate(); - listUpdate->State.Update.Category = realm->Timezone; - listUpdate->State.Update.Population = realm->PopulationLevel; - listUpdate->State.Update.StateFlags = (realm->AllowedSecurityLevel > _gameAccountInfo->SecurityLevel) ? 1 : 0; - listUpdate->State.Update.Type = realm->Type; - listUpdate->State.Update.Name = realm->Name; - - if (_gameAccountInfo->SecurityLevel > SEC_PLAYER) + else { - listUpdate->State.Update.PrivilegedData = boost::in_place(); - std::ostringstream version; - if (RealmBuildInfo const* buildInfo = AuthHelper::GetBuildInfo(realm->Build)) - version << buildInfo->MajorVersion << '.' << buildInfo->MinorVersion << '.' << buildInfo->BugfixVersion << '.' << buildInfo->Build; + auto itr = _responseCallbacks.find(header.token()); + if (itr != _responseCallbacks.end()) + { + itr->second(std::move(_packetBuffer)); + _responseCallbacks.erase(header.token()); + } else - version << "x.x.x." << realm->Build; - - listUpdate->State.Update.PrivilegedData->Version = version.str(); - listUpdate->State.Update.PrivilegedData->ConfigId = realm->GetConfigId(); - listUpdate->State.Update.PrivilegedData->Address = realm->GetAddressForClient(GetRemoteIpAddress()); + _packetBuffer.Reset(); } - listUpdate->State.Update.InfoFlags = flag; - listUpdate->Id = realm->Id; - return listUpdate; + return true; } std::string Battlenet::Session::GetClientInfo() const diff --git a/src/server/bnetserver/Server/Session.h b/src/server/bnetserver/Server/Session.h index 2443d694a80..4170cbc7826 100644 --- a/src/server/bnetserver/Server/Session.h +++ b/src/server/bnetserver/Server/Session.h @@ -18,140 +18,165 @@ #ifndef Session_h__ #define Session_h__ -#include "Packets.h" -#include "BattlenetPacketCrypt.h" +#include "Realm.h" +#include "SslContext.h" +#include "SslSocket.h" #include "Socket.h" #include "BigNumber.h" #include "Callback.h" -#include "MPSCQueue.h" -#include <memory> #include <boost/asio/ip/tcp.hpp> +#include <boost/asio/ssl.hpp> +#include <google/protobuf/message.h> +#include <memory> -struct Realm; using boost::asio::ip::tcp; -namespace Battlenet -{ - struct PacketHeader; - class BitStream; - - enum ModuleType - { - MODULE_PASSWORD, - MODULE_TOKEN, - MODULE_THUMBPRINT, - MODULE_SELECT_GAME_ACCOUNT, - MODULE_RISK_FINGERPRINT, - MODULE_RESUME, - - MODULE_COUNT - }; +namespace pb = google::protobuf; - enum class BufferSizes : uint32 +namespace bgs +{ + namespace protocol { - SRP_6_V = 0x80, - SRP_6_S = 0x20, - Read = 0x4000 - }; + class Variant; - struct AccountInfo - { - void LoadResult(Field* fields); - - uint32 Id; - std::string Login; - bool IsLockedToIP; - std::string LockCountry; - std::string LastIP; - uint32 FailedLogins; - bool IsBanned; - bool IsPermanenetlyBanned; - }; + namespace account + { + namespace v1 + { + class GetAccountStateRequest; + class GetAccountStateResponse; + class GetGameAccountStateRequest; + class GetGameAccountStateResponse; + } + } + + namespace authentication + { + namespace v1 + { + class LogonRequest; + class VerifyWebCredentialsRequest; + } + } + + namespace game_utilities + { + namespace v1 + { + class ClientRequest; + class ClientResponse; + class GetAllValuesForAttributeRequest; + class GetAllValuesForAttributeResponse; + } + } + } +} - struct GameAccountInfo - { - void LoadResult(Field* fields); - - uint32 Id; - std::string Name; - std::string DisplayName; - bool IsBanned; - bool IsPermanenetlyBanned; - AccountTypes SecurityLevel; - }; +using namespace bgs::protocol; - class Session : public Socket<Session> +namespace Battlenet +{ + class Session : public Socket<Session, SslSocket<SslContext>> { - typedef Socket<Session> BattlenetSocket; + typedef Socket<Session, SslSocket<SslContext>> BattlenetSocket; public: - explicit Session(tcp::socket&& socket); - ~Session(); - - void LogUnhandledPacket(PacketHeader const& header); + struct LastPlayedCharacterInfo + { + Battlenet::RealmHandle RealmId; + std::string CharacterName; + uint64 CharacterGUID; + uint32 LastPlayedTime; + }; - // Authentication - void HandleLogonRequest(Authentication::LogonRequest3 const& logonRequest); - void HandleResumeRequest(Authentication::ResumeRequest const& resumeRequest); - void HandleProofResponse(Authentication::ProofResponse const& proofResponse); + struct GameAccountInfo + { + void LoadResult(Field* fields); - // Connection - void HandlePing(Connection::Ping const& ping); - void HandleEnableEncryption(Connection::EnableEncryption& enableEncryption); - void HandleLogoutRequest(Connection::LogoutRequest const& logoutRequest); - void HandleConnectionClosing(Connection::ConnectionClosing const& connectionClosing); + uint32 Id; + std::string Name; + std::string DisplayName; + bool IsBanned; + bool IsPermanenetlyBanned; + AccountTypes SecurityLevel; - // WoWRealm - void HandleListSubscribeRequest(WoWRealm::ListSubscribeRequest const& listSubscribeRequest); - void HandleListUnsubscribe(WoWRealm::ListUnsubscribe const& listUnsubscribe); - void HandleJoinRequestV2(WoWRealm::JoinRequestV2 const& joinRequest); + std::unordered_map<uint32 /*realmAddress*/, uint8> CharacterCounts; + std::unordered_map<std::string /*subRegion*/, LastPlayedCharacterInfo> LastPlayedCharacters; + }; - // Friends + struct AccountInfo + { + void LoadResult(PreparedQueryResult result); + + uint32 Id; + std::string Login; + bool IsLockedToIP; + std::string LockCountry; + std::string LastIP; + uint32 FailedLogins; + bool IsBanned; + bool IsPermanenetlyBanned; + + std::unordered_map<uint32, GameAccountInfo> GameAccounts; + }; - // Cache - void HandleGetStreamItemsRequest(Cache::GetStreamItemsRequest const& getStreamItemsRequest); + explicit Session(tcp::socket&& socket); + ~Session(); void Start() override; bool Update() override; - void UpdateRealms(std::vector<Realm const*>& realms, std::vector<RealmHandle>& deletedRealms); - uint32 GetAccountId() const { return _accountInfo->Id; } uint32 GetGameAccountId() const { return _gameAccountInfo->Id; } - bool IsToonOnline() const { return _toonOnline; } - void SetToonOnline(bool online) { _toonOnline = online; } + void SendResponse(uint32 token, pb::Message const* response); + void SendResponse(uint32 token, uint32 status); + + void SendRequest(uint32 serviceHash, uint32 methodId, pb::Message const* request, std::function<void(MessageBuffer)> callback) + { + _responseCallbacks[_requestToken] = std::move(callback); + SendRequest(serviceHash, methodId, request); + } + + void SendRequest(uint32 serviceHash, uint32 methodId, pb::Message const* request); - bool IsSubscribedToRealmListUpdates() const { return _subscribedToRealmListUpdates; } + uint32 HandleLogon(authentication::v1::LogonRequest const* logonRequest); + uint32 HandleVerifyWebCredentials(authentication::v1::VerifyWebCredentialsRequest const* verifyWebCredentialsRequest); + uint32 HandleGetAccountState(account::v1::GetAccountStateRequest const* request, account::v1::GetAccountStateResponse* response); + uint32 HandleGetGameAccountState(account::v1::GetGameAccountStateRequest const* request, account::v1::GetGameAccountStateResponse* response); + uint32 HandleProcessClientRequest(game_utilities::v1::ClientRequest const* request, game_utilities::v1::ClientResponse* response); + uint32 HandleGetAllValuesForAttribute(game_utilities::v1::GetAllValuesForAttributeRequest const* request, game_utilities::v1::GetAllValuesForAttributeResponse* response); - void AsyncWrite(ServerPacket* packet); + std::string GetClientInfo() const; protected: + void HandshakeHandler(boost::system::error_code const& error); void ReadHandler() override; + bool ReadHeaderLengthHandler(); + bool ReadHeaderHandler(); + bool ReadDataHandler(); private: - void _SetVSFields(std::string const& rI); + void AsyncWrite(MessageBuffer* packet); - typedef bool(Session::*ModuleHandler)(BitStream* dataStream, ServerPacket** response); - static ModuleHandler const ModuleHandlers[MODULE_COUNT]; + void AsyncHandshake(); void CheckIpCallback(PreparedQueryResult result); - void HandleLogonRequestCallback(PreparedQueryResult result); - void HandleResumeRequestCallback(PreparedQueryResult result); - void HandleListSubscribeRequestCallback(PreparedQueryResult result); - bool HandlePasswordModule(BitStream* dataStream, ServerPacket** response); - bool HandleSelectGameAccountModule(BitStream* dataStream, ServerPacket** response); - bool HandleRiskFingerprintModule(BitStream* dataStream, ServerPacket** response); - bool HandleResumeModule(BitStream* dataStream, ServerPacket** response); - bool UnhandledModule(BitStream* dataStream, ServerPacket** response); + typedef uint32(Session::*ClientRequestHandler)(std::unordered_map<std::string, Variant const*> const&, game_utilities::v1::ClientResponse*); + static std::unordered_map<std::string, ClientRequestHandler> const ClientRequestHandlers; - WoWRealm::ListUpdate* BuildListUpdate(Realm const* realm) const; - std::string GetClientInfo() const; + uint32 GetRealmListTicket(std::unordered_map<std::string, Variant const*> const& params, game_utilities::v1::ClientResponse* response); + uint32 GetLastCharPlayed(std::unordered_map<std::string, Variant const*> const& params, game_utilities::v1::ClientResponse* response); + uint32 GetRealmList(std::unordered_map<std::string, Variant const*> const& params, game_utilities::v1::ClientResponse* response); + uint32 JoinRealm(std::unordered_map<std::string, Variant const*> const& params, game_utilities::v1::ClientResponse* response); + + MessageBuffer _headerLengthBuffer; + MessageBuffer _headerBuffer; + MessageBuffer _packetBuffer; - AccountInfo* _accountInfo; + std::unique_ptr<AccountInfo> _accountInfo; GameAccountInfo* _gameAccountInfo; // Points at selected game account (inside _gameAccounts) - std::vector<GameAccountInfo> _gameAccounts; std::string _locale; std::string _os; @@ -159,38 +184,16 @@ namespace Battlenet std::string _ipCountry; - BigNumber N; - BigNumber g; - BigNumber k; - - BigNumber I; - BigNumber s; - BigNumber v; - - BigNumber b; - BigNumber B; - BigNumber K; // session key - - BigNumber _reconnectProof; - - std::queue<ModuleType> _modulesWaitingForData; + std::array<uint8, 32> _clientSecret; - struct EncryptableBuffer - { - MessageBuffer Buffer; - bool Encrypt; - }; - - MPSCQueue<EncryptableBuffer> _bufferQueue; - PacketCrypt _crypt; bool _authed; - bool _subscribedToRealmListUpdates; - bool _toonOnline; PreparedQueryResultFuture _queryFuture; std::function<void(PreparedQueryResult)> _queryCallback; - }; + std::unordered_map<uint32, std::function<void(MessageBuffer)>> _responseCallbacks; + uint32 _requestToken; + }; } #endif // Session_h__ diff --git a/src/server/bnetserver/Server/SessionManager.cpp b/src/server/bnetserver/Server/SessionManager.cpp index ed36a3630e1..1920496ffff 100644 --- a/src/server/bnetserver/Server/SessionManager.cpp +++ b/src/server/bnetserver/Server/SessionManager.cpp @@ -37,41 +37,8 @@ void Battlenet::SessionManager::OnSocketAccept(tcp::socket&& sock, uint32 thread sSessionMgr.OnSocketOpen(std::forward<tcp::socket>(sock), threadIndex); } -void Battlenet::SessionManager::AddSession(Session* session) +Battlenet::SessionManager& Battlenet::SessionManager::Instance() { - std::unique_lock<boost::shared_mutex> lock(_sessionMutex); - _sessions[{ session->GetAccountId(), session->GetGameAccountId() }] = session; - _sessionsByAccountId[session->GetAccountId()].push_back(session); -} - -void Battlenet::SessionManager::RemoveSession(Session* session) -{ - std::unique_lock<boost::shared_mutex> lock(_sessionMutex); - auto itr = _sessions.find({ session->GetAccountId(), session->GetGameAccountId() }); - // Remove old session only if it was not overwritten by reconnecting - if (itr != _sessions.end() && itr->second == session) - _sessions.erase(itr); - - _sessionsByAccountId[session->GetAccountId()].remove(session); -} - -Battlenet::Session* Battlenet::SessionManager::GetSession(uint32 accountId, uint32 gameAccountId) const -{ - boost::shared_lock<boost::shared_mutex> lock(_sessionMutex); - auto itr = _sessions.find({ accountId, gameAccountId }); - if (itr != _sessions.end()) - return itr->second; - - return nullptr; -} - -std::list<Battlenet::Session*> Battlenet::SessionManager::GetSessions(uint32 accountId) const -{ - boost::shared_lock<boost::shared_mutex> lock(_sessionMutex); - std::list<Session*> sessions; - auto itr = _sessionsByAccountId.find(accountId); - if (itr != _sessionsByAccountId.end()) - sessions = itr->second; - - return sessions; + static SessionManager instance; + return instance; } diff --git a/src/server/bnetserver/Server/SessionManager.h b/src/server/bnetserver/Server/SessionManager.h index 701802056da..c1aa955812c 100644 --- a/src/server/bnetserver/Server/SessionManager.h +++ b/src/server/bnetserver/Server/SessionManager.h @@ -18,68 +18,25 @@ #ifndef SessionManager_h__ #define SessionManager_h__ -#include "Session.h" #include "SocketMgr.h" -#include <boost/thread/locks.hpp> -#include <boost/thread/shared_mutex.hpp> +#include "Session.h" namespace Battlenet { -#pragma pack(push, 1) - - struct SessionInfo - { - uint32 AccountId; - uint32 GameAccountId; - - bool operator<(SessionInfo const& right) const - { - return memcmp(this, &right, sizeof(SessionInfo)) < 0; - } - }; - -#pragma pack(pop) - class SessionManager : public SocketMgr<Session> { typedef SocketMgr<Session> BaseSocketMgr; - typedef std::map<SessionInfo, Session*> SessionMap; - typedef std::map<uint32, std::list<Session*>> SessionByAccountMap; public: - static SessionManager& Instance() - { - static SessionManager instance; - return instance; - } + static SessionManager& Instance(); bool StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port, int threadCount = 1) override; - // noop for now, will be needed later to broadcast realmlist updates for example - void AddSession(Session* /*session*/); - - void RemoveSession(Session* /*session*/); - - Session* GetSession(uint32 accountId, uint32 gameAccountId) const; - std::list<Session*> GetSessions(uint32 accountId) const; - - template<typename Iterator> - void LockedForEach(Iterator iterator) const - { - boost::shared_lock<boost::shared_mutex> lock(_sessionMutex); - for (SessionMap::value_type const& pair : _sessions) - iterator(pair.second); - } - protected: NetworkThread<Session>* CreateThreads() const override; private: static void OnSocketAccept(tcp::socket&& sock, uint32 threadIndex); - - SessionMap _sessions; - SessionByAccountMap _sessionsByAccountId; - mutable boost::shared_mutex _sessionMutex; }; } diff --git a/src/server/bnetserver/Server/SslContext.cpp b/src/server/bnetserver/Server/SslContext.cpp new file mode 100644 index 00000000000..f1b2a185563 --- /dev/null +++ b/src/server/bnetserver/Server/SslContext.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "SslContext.h" +#include "Log.h" + +bool Battlenet::SslContext::Initialize() +{ + boost::system::error_code err; + +#define LOAD_CHECK(fn) do { fn; \ + if (err) \ + { \ + TC_LOG_ERROR("server.ssl", #fn ## "failed: %s", err.message().c_str()); \ + return false; \ + } } while (0) + + LOAD_CHECK(instance().set_options(boost::asio::ssl::context::no_sslv3, err)); + LOAD_CHECK(instance().use_certificate_chain_file("bnetserver.cert.pem", err)); + LOAD_CHECK(instance().use_private_key_file("bnetserver.key.pem", boost::asio::ssl::context::pem, err)); + +#undef LOAD_CHECK + + return true; +} + +boost::asio::ssl::context& Battlenet::SslContext::instance() +{ + static boost::asio::ssl::context context(boost::asio::ssl::context::sslv23); + return context; +} diff --git a/src/server/bnetserver/Packets/BitStream.cpp b/src/server/bnetserver/Server/SslContext.h index 1aeac731d28..5425ab46231 100644 --- a/src/server/bnetserver/Packets/BitStream.cpp +++ b/src/server/bnetserver/Server/SslContext.h @@ -15,16 +15,20 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "BitStream.h" +#ifndef SslContext_h__ +#define SslContext_h__ -template<> -bool Battlenet::BitStream::Read<bool>(uint32 /*bitCount*/) -{ - return Read<uint8>(1) != 0; -} +#include <boost/asio/ssl/context.hpp> -template<> -void Battlenet::BitStream::Write<bool>(bool value, uint32 /*bitCount*/) +namespace Battlenet { - Write<uint8>(value ? 1 : 0, 1); + class SslContext + { + public: + static bool Initialize(); + + static boost::asio::ssl::context& instance(); + }; } + +#endif // SslContext_h__ diff --git a/src/server/bnetserver/Packets/SupportPackets.h b/src/server/bnetserver/Services/AccountService.cpp index c84c96607f0..c4b6da289b8 100644 --- a/src/server/bnetserver/Packets/SupportPackets.h +++ b/src/server/bnetserver/Services/AccountService.cpp @@ -15,21 +15,19 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef SupportPackets_h__ -#define SupportPackets_h__ +#include "AccountService.h" +#include "Session.h" -#include "PacketsBase.h" +Battlenet::Services::Account::Account(Session* session) : AccountService(session) +{ +} -namespace Battlenet +uint32 Battlenet::Services::Account::HandleGetAccountState(account::v1::GetAccountStateRequest const* request, account::v1::GetAccountStateResponse* response) { - namespace Support - { - enum Opcode - { - CMSG_COMPLAINT_REQUEST = 0x0, // Deprecated in client - CMSG_COMPLAINT_REQUEST_2 = 0x1 // Not implemented - }; - } + return _session->HandleGetAccountState(request, response); } -#endif // SupportPackets_h__ +uint32 Battlenet::Services::Account::HandleGetGameAccountState(account::v1::GetGameAccountStateRequest const* request, account::v1::GetGameAccountStateResponse* response) +{ + return _session->HandleGetGameAccountState(request, response); +} diff --git a/src/server/bnetserver/Packets/AchievementPackets.h b/src/server/bnetserver/Services/AccountService.h index 3773e8475b7..8f950961a90 100644 --- a/src/server/bnetserver/Packets/AchievementPackets.h +++ b/src/server/bnetserver/Services/AccountService.h @@ -15,28 +15,30 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef AchievementPackets_h__ -#define AchievementPackets_h__ +#ifndef AccountService_h__ +#define AccountService_h__ -#include "PacketsBase.h" +#include "Common.h" +#include "Service.h" +#include "account_service.pb.h" namespace Battlenet { - namespace Achievement + class Session; + + namespace Services { - enum Opcode + class Account : public Service<account::v1::AccountService> { - CMSG_LISTEN_REQUEST = 0x0, // Not implemented - CMSG_CRITERIA_FLUSH_REQUEST = 0x3, // Not implemented - CMSG_CHANGE_TROPHY_CASE_REQUEST = 0x5, // Not implemented + typedef Service<account::v1::AccountService> AccountService; + + public: + Account(Session* session); - SMSG_DATA = 0x2, // Not implemented - SMSG_CRITERIA_FLUSH_RESPONSE = 0x3, // Not implemented - SMSG_ACHIEVEMENT_HANDLE_UPDATE = 0x4, // Not implemented - SMSG_CHANGE_TROPHY_CASE_RESULT = 0x6 // Not implemented + uint32 HandleGetAccountState(account::v1::GetAccountStateRequest const* request, account::v1::GetAccountStateResponse* response) override; + uint32 HandleGetGameAccountState(account::v1::GetGameAccountStateRequest const* request, account::v1::GetGameAccountStateResponse* response) override; }; } } -#endif // AchievementPackets_h__ - +#endif // AccountService_h__ diff --git a/src/server/bnetserver/Packets/PresencePackets.h b/src/server/bnetserver/Services/AuthenticationService.cpp index e098d6e9053..fd703ad22ac 100644 --- a/src/server/bnetserver/Packets/PresencePackets.h +++ b/src/server/bnetserver/Services/AuthenticationService.cpp @@ -15,25 +15,19 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef PresencePackets_h__ -#define PresencePackets_h__ +#include "AuthenticationService.h" +#include "Session.h" -#include "PacketsBase.h" - -namespace Battlenet +Battlenet::Services::Authentication::Authentication(Session* session) : AuthenticationService(session) { - namespace Presence - { - enum Opcode - { - CMSG_UPDATE_REQUEST = 0x0, // Not implemented - CMSG_STATISTIC_SUBSCRIBE = 0x2, // Not implemented +} - SMSG_UPDATE_NOTIFY = 0x0, // Not implemented - SMSG_FIELD_SPEC_ANNOUNCE = 0x1, // Not implemented - SMSG_STATISTICS_UPDATE = 0x3 // Not implemented - }; - } +uint32 Battlenet::Services::Authentication::HandleLogon(authentication::v1::LogonRequest const* request, NoData* /*respons*/) +{ + return _session->HandleLogon(request); } -#endif // PresencePackets_h__ +uint32 Battlenet::Services::Authentication::HandleVerifyWebCredentials(authentication::v1::VerifyWebCredentialsRequest const* request, NoData* /*respons*/) +{ + return _session->HandleVerifyWebCredentials(request); +} diff --git a/src/server/bnetserver/Authentication/BattlenetPacketCrypt.h b/src/server/bnetserver/Services/AuthenticationService.h index 8344391d523..e5a2726b110 100644 --- a/src/server/bnetserver/Authentication/BattlenetPacketCrypt.h +++ b/src/server/bnetserver/Services/AuthenticationService.h @@ -15,22 +15,30 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef BattlenetPacketCrypt_h__ -#define BattlenetPacketCrypt_h__ +#ifndef AuthenticationService_h__ +#define AuthenticationService_h__ -#include "PacketCrypt.h" - -class BigNumber; +#include "Common.h" +#include "Service.h" +#include "authentication_service.pb.h" namespace Battlenet { - class PacketCrypt : public ::PacketCrypt + class Session; + + namespace Services { + class Authentication : public Service<authentication::v1::AuthenticationService> + { + typedef Service<authentication::v1::AuthenticationService> AuthenticationService; + public: - PacketCrypt(); + Authentication(Session* session); - void Init(BigNumber* K) override; - }; + uint32 HandleLogon(authentication::v1::LogonRequest const* request, NoData* respons) override; + uint32 HandleVerifyWebCredentials(authentication::v1::VerifyWebCredentialsRequest const* request, NoData* respons) override; + }; + } } -#endif // BattlenetPacketCrypt_h__ +#endif // AuthenticationService_h__ diff --git a/src/server/bnetserver/Services/ConnectionService.cpp b/src/server/bnetserver/Services/ConnectionService.cpp new file mode 100644 index 00000000000..78ead03b7e6 --- /dev/null +++ b/src/server/bnetserver/Services/ConnectionService.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "ConnectionService.h" +#include "Duration.h" +#include "Log.h" +#include "Session.h" +#include "Util.h" +#include "BattlenetRpcErrorCodes.h" + +Battlenet::Services::Connection::Connection(Session* session) : ConnectionService(session) +{ +} + +uint32 Battlenet::Services::Connection::HandleConnect(connection::v1::ConnectRequest const* request, connection::v1::ConnectResponse* response) +{ + if (request->has_client_id()) + response->mutable_client_id()->CopyFrom(request->client_id()); + + std::chrono::system_clock::duration now = std::chrono::system_clock::now().time_since_epoch(); + + response->mutable_server_id()->set_label(GetPID()); + response->mutable_server_id()->set_epoch(std::chrono::duration_cast<Seconds>(now).count()); + response->set_server_time(std::chrono::duration_cast<Milliseconds>(now).count()); + + response->set_use_bindless_rpc(request->use_bindless_rpc()); + return ERROR_OK; +} + +uint32 Battlenet::Services::Connection::HandleKeepAlive(NoData const* /*request*/) +{ + return ERROR_OK; +} + +uint32 Battlenet::Services::Connection::HandleRequestDisconnect(connection::v1::DisconnectRequest const* request) +{ + connection::v1::DisconnectNotification disconnectNotification; + disconnectNotification.set_error_code(request->error_code()); + ForceDisconnect(&disconnectNotification); + + _session->DelayedCloseSocket(); + return ERROR_OK; +} diff --git a/src/server/bnetserver/Services/ConnectionService.h b/src/server/bnetserver/Services/ConnectionService.h new file mode 100644 index 00000000000..48b726eb2ba --- /dev/null +++ b/src/server/bnetserver/Services/ConnectionService.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef ConnectionService_h__ +#define ConnectionService_h__ + +#include "Common.h" +#include "Service.h" +#include "connection_service.pb.h" + +namespace Battlenet +{ + class Session; + + namespace Services + { + class Connection : public Service<connection::v1::ConnectionService> + { + typedef Service<connection::v1::ConnectionService> ConnectionService; + + public: + Connection(Session* session); + + uint32 HandleConnect(connection::v1::ConnectRequest const* request, connection::v1::ConnectResponse* respons) override; + uint32 HandleKeepAlive(NoData const* request) override; + uint32 HandleRequestDisconnect(connection::v1::DisconnectRequest const* request) override; + + }; + } +} + +#endif // ConnectionService_h__ diff --git a/src/server/bnetserver/Packets/PacketsBase.cpp b/src/server/bnetserver/Services/GameUtilitiesService.cpp index 61301307954..e9e7b36724d 100644 --- a/src/server/bnetserver/Packets/PacketsBase.cpp +++ b/src/server/bnetserver/Services/GameUtilitiesService.cpp @@ -15,32 +15,19 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "Packets.h" +#include "GameUtilitiesService.h" #include "Session.h" -#include <sstream> -std::string Battlenet::PacketHeader::ToString() const +Battlenet::Services::GameUtilities::GameUtilities(Session* session) : GameUtilitiesService(session) { - std::ostringstream stream; - stream << "Battlenet::PacketHeader" << std::endl; - APPEND_FIELD(stream, Command); - APPEND_FIELD(stream, Channel); - return stream.str(); } -Battlenet::ServerPacket::ServerPacket(PacketHeader const& header) : Packet(header, *new BitStream()) +uint32 Battlenet::Services::GameUtilities::HandleProcessClientRequest(game_utilities::v1::ClientRequest const* request, game_utilities::v1::ClientResponse* response) { - _stream.Write(header.Command, 6); - _stream.Write(1, 1); - _stream.Write(header.Channel, 4); + return _session->HandleProcessClientRequest(request, response); } -Battlenet::ServerPacket::~ServerPacket() +uint32 Battlenet::Services::GameUtilities::HandleGetAllValuesForAttribute(game_utilities::v1::GetAllValuesForAttributeRequest const* request, game_utilities::v1::GetAllValuesForAttributeResponse* response) { - delete &_stream; -} - -void Battlenet::ClientPacket::CallHandler(Session* session) -{ - session->LogUnhandledPacket(GetHeader()); + return _session->HandleGetAllValuesForAttribute(request, response); } diff --git a/src/server/bnetserver/Services/GameUtilitiesService.h b/src/server/bnetserver/Services/GameUtilitiesService.h new file mode 100644 index 00000000000..37f56e03566 --- /dev/null +++ b/src/server/bnetserver/Services/GameUtilitiesService.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GameUtilitiesServiceService_h__ +#define GameUtilitiesServiceService_h__ + +#include "Common.h" +#include "Service.h" +#include "game_utilities_service.pb.h" + +namespace Battlenet +{ + class Session; + + namespace Services + { + class GameUtilities : public Service<game_utilities::v1::GameUtilitiesService> + { + typedef Service<game_utilities::v1::GameUtilitiesService> GameUtilitiesService; + + public: + GameUtilities(Session* session); + + uint32 HandleProcessClientRequest(game_utilities::v1::ClientRequest const* request, game_utilities::v1::ClientResponse* response) override; + uint32 HandleGetAllValuesForAttribute(game_utilities::v1::GetAllValuesForAttributeRequest const* request, game_utilities::v1::GetAllValuesForAttributeResponse* response) override; + }; + } +} + +#endif // GameUtilitiesServiceService_h__ diff --git a/src/server/bnetserver/Services/Service.h b/src/server/bnetserver/Services/Service.h new file mode 100644 index 00000000000..f2f4ee76c3f --- /dev/null +++ b/src/server/bnetserver/Services/Service.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef Service_h__ +#define Service_h__ + +#include "Session.h" + +namespace bgs { namespace protocol { } } +using namespace bgs::protocol; + +namespace Battlenet +{ + template<class T> + class Service : public T + { + public: + Service(Session* session) : T(true), _session(session) { } + + protected: + void SendRequest(uint32 serviceHash, uint32 methodId, google::protobuf::Message const* request, std::function<void(MessageBuffer)> callback) override { _session->SendRequest(serviceHash, methodId, request, std::move(callback)); } + void SendRequest(uint32 serviceHash, uint32 methodId, google::protobuf::Message const* request) override { _session->SendRequest(serviceHash, methodId, request); } + void SendResponse(uint32 /*serviceHash*/, uint32 /*methodId*/, uint32 token, uint32 status) override { _session->SendResponse(token, status); } + void SendResponse(uint32 /*serviceHash*/, uint32 /*methodId*/, uint32 token, google::protobuf::Message const* response) override { _session->SendResponse(token, response); } + std::string GetCallerInfo() const override { return _session->GetClientInfo(); } + + Session* _session; + }; +} + +#endif // Service_h__ diff --git a/src/server/bnetserver/Services/ServiceDispatcher.cpp b/src/server/bnetserver/Services/ServiceDispatcher.cpp new file mode 100644 index 00000000000..ded1c2d3765 --- /dev/null +++ b/src/server/bnetserver/Services/ServiceDispatcher.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "ServiceDispatcher.h" + +Battlenet::ServiceDispatcher::ServiceDispatcher() +{ + AddService<Services::Account>(); + AddService<Services::Authentication>(); + AddService<Service<challenge::v1::ChallengeService>>(); + AddService<Service<channel::v1::ChannelService>>(); + AddService<Services::Connection>(); + AddService<Service<friends::v1::FriendsService>>(); + AddService<Services::GameUtilities>(); + AddService<Service<presence::v1::PresenceService>>(); + AddService<Service<report::v1::ReportService>>(); + AddService<Service<resources::v1::ResourcesService>>(); + AddService<Service<user_manager::v1::UserManagerService>>(); +} + +void Battlenet::ServiceDispatcher::Dispatch(Session* session, uint32 serviceHash, uint32 token, uint32 methodId, MessageBuffer buffer) +{ + auto itr = _dispatchers.find(serviceHash); + if (itr != _dispatchers.end()) + itr->second(session, token, methodId, std::forward<MessageBuffer>(buffer)); + else + TC_LOG_DEBUG("session.rpc", "%s tried to call invalid service 0x%X", session->GetClientInfo().c_str(), serviceHash); +} + +Battlenet::ServiceDispatcher& Battlenet::ServiceDispatcher::Instance() +{ + static ServiceDispatcher instance; + return instance; +} diff --git a/src/server/bnetserver/Services/ServiceDispatcher.h b/src/server/bnetserver/Services/ServiceDispatcher.h new file mode 100644 index 00000000000..03f67070ef5 --- /dev/null +++ b/src/server/bnetserver/Services/ServiceDispatcher.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef ServiceRegistry_h__ +#define ServiceRegistry_h__ + +#include "MessageBuffer.h" +#include "Log.h" +#include "Common.h" +#include "AccountService.h" +#include "AuthenticationService.h" +#include "challenge_service.pb.h" +#include "channel_service.pb.h" +#include "ConnectionService.h" +#include "friends_service.pb.h" +#include "GameUtilitiesService.h" +#include "presence_service.pb.h" +#include "report_service.pb.h" +#include "resource_service.pb.h" +#include "user_manager_service.pb.h" + +namespace Battlenet +{ + class Session; + + class ServiceDispatcher + { + public: + void Dispatch(Session* session, uint32 serviceHash, uint32 token, uint32 methodId, MessageBuffer buffer); + + static ServiceDispatcher& Instance(); + + private: + ServiceDispatcher(); + + template<class Service> + void AddService() + { + _dispatchers[Service::OriginalHash::value] = &ServiceDispatcher::Dispatch<Service>; + } + + template<class Service> + static void Dispatch(Session* session, uint32 token, uint32 methodId, MessageBuffer buffer) + { + Service(session).CallServerMethod(token, methodId, std::forward<MessageBuffer>(buffer)); + } + + std::unordered_map<uint32, std::function<void(Session*, uint32, uint32, MessageBuffer)>> _dispatchers; + }; +} + +#define sServiceDispatcher ServiceDispatcher::Instance() + +#endif // ServiceRegistry_h__ diff --git a/src/server/bnetserver/bnetserver.cert.pem b/src/server/bnetserver/bnetserver.cert.pem new file mode 100644 index 00000000000..f556bcf80b8 --- /dev/null +++ b/src/server/bnetserver/bnetserver.cert.pem @@ -0,0 +1,100 @@ +-----BEGIN CERTIFICATE----- +MIIFhjCCA26gAwIBAgIBATANBgkqhkiG9w0BAQsFADB6MQswCQYDVQQGEwJVUzEU +MBIGA1UECgwLVHJpbml0eUNvcmUxKjAoBgNVBAsMIVRyaW5pdHlDb3JlIENlcnRp +ZmljYXRlIEF1dGhvcml0eTEpMCcGA1UEAwwgVHJpbml0eUNvcmUgQmF0dGxlLm5l +dCBBdXJvcmEgQ0EwHhcNMTYwMjI4MTMxMTI4WhcNMzYwMjIzMTMxMTI4WjBGMQsw +CQYDVQQGEwJVUzEUMBIGA1UECgwLVHJpbml0eUNvcmUxEzARBgNVBAsMCkRldmVs +b3BlcnMxDDAKBgNVBAMMAyouKjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAMDdxGJioQxmsBq4etsAII4d8K+AnFepaetRL9/Y805IHrVwwRdklgvbP6c0 +v4ddB0MC/T9HGJam2R4/3WqzqYXKqZStOVrCQvO+pVAEknlVlT4h7Jn6Us48eual +dj35nDRNUlBIszjn6WqMby31aoecuDJLksV8Tlwl0vQp0AcEKPH/+LlenMx2YIoI +uwkiA++VSt1Yar5U2i2BaBIjqY1jQEO8f9fLL/laElbl/mpWHs9jw8FPoZdAqcxC +KrWmr57XHvbEN7hHd3l2BgCael/mzlSLUZlIW91l6CF5hzGi3uaEnHCDWte2S+x9 +iEjqq/9T36vOApP1UrW8xHyXU2cCAwEAAaOCAUkwggFFMAkGA1UdEwQCMAAwEQYJ +YIZIAYb4QgEBBAQDAgZAMDMGCWCGSAGG+EIBDQQmFiRPcGVuU1NMIEdlbmVyYXRl +ZCBTZXJ2ZXIgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFL5TLPbXOTB9xRBJ8pUFw7+2 +6nlqMIGrBgNVHSMEgaMwgaCAFI7XCpyCprztwOvx8+S7g+SXQuFZoYGEpIGBMH8x +CzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtUcmluaXR5Q29yZTEqMCgGA1UECwwhVHJp +bml0eUNvcmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MS4wLAYDVQQDDCVUcmluaXR5 +Q29yZSBCYXR0bGUubmV0IEF1cm9yYSBSb290IENBggEBMA4GA1UdDwEB/wQEAwIF +oDATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0BAQsFAAOCAgEACt0tfSaR +8wu4GPpqDD69Ch7o2tN6K4Wr8S2xkdmVMKTp6DXvpeWVlIiK30q8yxQdrzupyaTJ +CVmWmA+IAHlaHYy5EsWI3CW2q47y6HugZoGEYL7oVZEcgCy3F1c2q100T/fdYXoO +Se6PM87hC9iE9kvmL8WxN8o98zRYcrSgzen/xJjESSR1gdyVBiFiT0RE4qr+tFkq +JW6PUZiYoFXXerqR5QrsUkIkIYBp9f2BCOR9ZMlrlKe/ojUaRaW/3fFwyV22g+jQ +MRkzkxeg6ynfTcsMiiIHSpX3ajy+m03mfbp1fIaHr/F6YbxqpzylfUOu0VOp3cUo +5/so4JESWMpDaArmlNdfrfvLAjn0jKQZwNg/rI5SNGF55r2Dc8KXc6rZ7wJo0bvl +ZQIQMWES1ZLxBa/r5yF8kPnxUrNLIQ8HdPxonPeU5L2CpEv8k3Fii//8N6h0Orpv +I+FUGpYOcdBLITb/jVn5WkXW0q3Qjlb5MQjLyRweBVfP6WOUbyI3rV+BvbrgkJSI +DqN2duvVLJgJa6ebmYRs1NfkTaX/TY3MB4B+Eo0nM6f9qSbptDo2oXAt6mhJDyRQ +m9T7wdl98+cv5QlCZUBPbOEGv8ZM2I/hUZeW+svcWhd1ONyLVByCAFLsGWpAylML +DgH8o+NLrjzNhQxllkENFN0mVnfc42Yo+T8= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIF2jCCA8KgAwIBAgIBATANBgkqhkiG9w0BAQsFADB/MQswCQYDVQQGEwJVUzEU +MBIGA1UECgwLVHJpbml0eUNvcmUxKjAoBgNVBAsMIVRyaW5pdHlDb3JlIENlcnRp +ZmljYXRlIEF1dGhvcml0eTEuMCwGA1UEAwwlVHJpbml0eUNvcmUgQmF0dGxlLm5l +dCBBdXJvcmEgUm9vdCBDQTAeFw0xNjAyMjgxMzAxMjJaFw0zNjAyMjMxMzAxMjJa +MHoxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtUcmluaXR5Q29yZTEqMCgGA1UECwwh +VHJpbml0eUNvcmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MSkwJwYDVQQDDCBUcmlu +aXR5Q29yZSBCYXR0bGUubmV0IEF1cm9yYSBDQTCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBAMOim0oMJ8hed2ZO0n4FSWCK+AqTKqOKEwkZzmv+f0jd5dH9 +F9DmlkqGJXb1FWsd+5rp6GbDHorMsJDIKBfWuNxoVHvgSQUnBXosY/TTXn6DbLCN +hZWnfxARzAp8T/FXL/rlwhR1cYkN+WugAq58/Aa+khaG2JNvSb/e1y5KiJ7wKN2N +bFLZ/dIslBE5gJzgO5hU19WM0vSXRl2Pw0gWBNvvZUa4FH4tW95zdARtAxJPgg1d +21qtXnfbE8xTCLKE5GAIlOK+r9+3elt6y+EZiZ8cq/b/Jfp+1GNBAlVLlpPzS7LQ +f+DtVKJ4FTtADWmRWEEy4vaUhblDfo2nokNdmcnTy93bmOHwJlKkRZVT/vwhKlMS +INtBEXJfZS+UM+CvhIAhSwRwSa97Nz8WEpNvWJwl/eUT3D+JOF+bklTvR7Vwwwtu +PgJks8+aLCjEC/T5n7KotxTV1tW5OD3Dy3urJ01INe0SEHMMPVPj2ejqHg2ndGRF +dC0QlmIxNpaSGqs5H12rxbmwyOpv2P0+ESwlWCJn87WUJhbs9ez3lr8OyXByMpvU +5wqJxzrTMkJ2xHQp8XVIJclKHt/irExru/v7wS05usvr5fC4uCICAqQO5Ed6OvP+ +/krW3YNR/5UgzUpFz+2md4AIXur8uU6qVEc31fKufiTWnVS2h3v1tccGsKg/AgMB +AAGjZjBkMB0GA1UdDgQWBBSO1wqcgqa87cDr8fPku4Pkl0LhWTAfBgNVHSMEGDAW +gBQS3qDGF+YcRzusE6ockR82TMa/czASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1Ud +DwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAvxnyXNtRosLnrG4BCgr3zwHx +H0T4h2yllCsqcM9DE3dBzyjtIooHLIEtuK5JtZKQawh95Hg9Y/e+aiXPgiIZtsob +mJn8GovjB6JpUsiA5I7NqNfOfcsZu39/PZC2F0C8t7M1FHmQpSEnL5m9pGnJ4Kzi +y/Zz4woAeT+tipJISDPJnWjvItQOS8Wv/mScbHa/8Z7o21ZITZMGRG8LIo8Fpc+p +8VT9ysJ1WvP/Cc1g703ojperADspKpA/yAWSI0WBrlNUUP3zN/RNKJq+pwKSad+3 +o30tYGDkfTUMDFfsJ68UwalZHPuwCuG5g4ZIhMQwqzeOhX8nW40Pcsc9dQPIF2Jz +FHfSRtAUj0JCb5dS08AH7z2wQRELkzeR5x/5GB6b9fg96xjcHWTsfbH7K63e6Lv4 ++ZEggfBip5VCL9xAyNK22p1TvXLY73V2zyqJ9dH/8lGWfm+OvQ1hzQbwPJ7J8BPI +u+fJJaOze557QKTmeHYPvoj/q3X2xLyMXW236fu5EBXK1RhDgrRXxf4aHB0Bzn7n +quyUU8spdLG97OljvGEiESLj9oWYbXKLnWqz6TWOnAmTtRLaK2iau3iP+7lwkaoe +Q6DZHDkgLtiTx7VwsSJZTU5o+TPj4wfjS9Jl3j8PMVPpfG5IFF3ErOEsz/KPu9Nz +j7x/l+OtqHw4Pithuig= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIF5DCCA8ygAwIBAgIJAIgLslwk40XzMA0GCSqGSIb3DQEBCwUAMH8xCzAJBgNV +BAYTAlVTMRQwEgYDVQQKDAtUcmluaXR5Q29yZTEqMCgGA1UECwwhVHJpbml0eUNv +cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MS4wLAYDVQQDDCVUcmluaXR5Q29yZSBC +YXR0bGUubmV0IEF1cm9yYSBSb290IENBMB4XDTE2MDIyODEyNDkwOFoXDTM2MDIy +MzEyNDkwOFowfzELMAkGA1UEBhMCVVMxFDASBgNVBAoMC1RyaW5pdHlDb3JlMSow +KAYDVQQLDCFUcmluaXR5Q29yZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxLjAsBgNV +BAMMJVRyaW5pdHlDb3JlIEJhdHRsZS5uZXQgQXVyb3JhIFJvb3QgQ0EwggIiMA0G +CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDGrYWvS0mVParJd96E4z/qjCvW6eR0 +buQ++VNEqVgeG14k4V41wkEzakB4nr2oGH10z9J/aqLlWnxaOl+yJ7BaomUAAOgJ +aCyqAJ8HaEU+7BbDO4MZXmtw1A3YcHsBkVx5wGm3tcH5IEXfVhvNZDqwAmYIcm7g +KFgnds6RFJmRxF4WznWiRr2MQkSOr/kc2eQ2VUg5afTlTxZva/mXEVpShinvbhaM +SgFBW+QahCwBJVQaLhEn+Wc6YNuHFmZ/i716xGb3cuYu89TF46iKQ/9Bm8yEFGg8 +QA28IZQ1sXgVpzJI9eowFtqAwhl65ipjGw4xH33of+WcwJQNjF7HXymRqk0WAa2j +tXOEiShI3XDloblX7vKbAe9RFpfVIqT8UfKSOJGQDVzvl4wSihINshO7YgIqp97M +GnWtnlWCDb2mcSj8JjnzRjG2kZZCNR/2lgfCG/1VF+QLh/3vD2+N5YkJZqBK1JTF +Fx+p66lVQWfdh2MXPlGjat343HZGm0YR7nRjngO2j3YtTojdJxRfLgztQv94jMtW +PHE38ysUK7mS6KKqYXqyB19IOHL2QB8fjmON1hCd0wDW42ZB23ywNkASw6uJDR02 +xXN2wiynIIb3cz6zouXd60wC7utMTveq8+rhFFgmFDdI2o9gwWQPA/43OYIlAdKV +g2NRhXb/6bzFkwIDAQABo2MwYTAdBgNVHQ4EFgQUEt6gxhfmHEc7rBOqHJEfNkzG +v3MwHwYDVR0jBBgwFoAUEt6gxhfmHEc7rBOqHJEfNkzGv3MwDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBAFzCJkcDCPVM +al+Thlip26LPkszZ4zWTsNsbUYmSe7h0kmMWt4x3mmZITfwb/eysYCnHThBVTjXj +9VWBGfbECZ/xdyXC2ur+qp0Mm7xH2Wuswf7yfPC+USNO6+/tFS282FO/nM0quaKV +knOC8ioCoASsBICB9lwRoYRKNBwRn3pkJplHepGahaJez4eedujO3dzxDdD32zy2 +/AfdeFXTxhWY8PTjMBKC2zpUQD7Kdvl+D8SfIsq73b8a9XmhdNX7qTc6MjecCD7W +HAP2rrK7epjTaVJp4+PYlw7qfix/NT1fNkq2Mb2E77h2eToUG1mjs/mvG/4WfVCf +MaBHOKaw6fyZULf366Jbx02r8K05P5ouvS1Z0De1mZJuUEUYhTRSs2POIdrmVrn9 +R83Y4l7TKNPJelq2uyEc4r+/fRrerIlT4HVlLPTC3SdW8ytYSUZXx+1NfJfQimie +veIyIaTOV3SfC4EfeXtPtUpcVJvmFXqVbnXOO7bQU63bfFuuVSeU6OXWjoFRVkdH +NYTGUGb5xg4hgWqlLWvWg0WPgLLabMbetrP6c5/Qhml/l07nJHeLoVxlFuwsL8HG +eu0JWqnmwamp4/mmblRC9UfyrIQeDS8gsx8q/t2zdzT4bBph0nqYkZSyiIoQzlMr +YdrWxeJm3sReR0G3FluL+03TGJypGfhr +-----END CERTIFICATE----- diff --git a/src/server/bnetserver/bnetserver.conf.dist b/src/server/bnetserver/bnetserver.conf.dist index 252a29440b5..211e63cfdb9 100644 --- a/src/server/bnetserver/bnetserver.conf.dist +++ b/src/server/bnetserver/bnetserver.conf.dist @@ -55,6 +55,22 @@ MaxPingTime = 30 BattlenetPort = 1119 # +# LoginREST.Port +# Description: TCP port to reach the REST login method. +# Default: 8081 +# +# LoginREST.ExternalAddress +# Description: IP address sent to clients connecting from outside the network where bnetserver runs +# +# LoginREST.LocalAddress +# Description: IP address sent to clients connecting from inside the network where bnetserver runs +# + +LoginREST.Port = 8081 +LoginREST.ExternalAddress=127.0.0.1 +LoginREST.LocalAddress=127.0.0.1 + +# # # BindIP # Description: Bind auth server to IP/hostname diff --git a/src/server/bnetserver/bnetserver.key.pem b/src/server/bnetserver/bnetserver.key.pem new file mode 100644 index 00000000000..bec4bcd1e4b --- /dev/null +++ b/src/server/bnetserver/bnetserver.key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAwN3EYmKhDGawGrh62wAgjh3wr4CcV6lp61Ev39jzTkgetXDB +F2SWC9s/pzS/h10HQwL9P0cYlqbZHj/darOphcqplK05WsJC876lUASSeVWVPiHs +mfpSzjx65qV2PfmcNE1SUEizOOfpaoxvLfVqh5y4MkuSxXxOXCXS9CnQBwQo8f/4 +uV6czHZgigi7CSID75VK3VhqvlTaLYFoEiOpjWNAQ7x/18sv+VoSVuX+alYez2PD +wU+hl0CpzEIqtaavntce9sQ3uEd3eXYGAJp6X+bOVItRmUhb3WXoIXmHMaLe5oSc +cINa17ZL7H2ISOqr/1Pfq84Ck/VStbzEfJdTZwIDAQABAoIBAHcu1DQERQd30a3B +gNIi4vtPzzN1I6gcXgL3+cC3vasLcEapdflxxDNxeoVmWFFbEKi9iSf4VF6MnrFN +wBM3ETRHh8IDxeSrFVqw3lFzcdyfIYnyxtZkVZVy1HQBne8wd/HuMkbAllg9IAYi +4HWjKgDBvSX/g6Sca4QQL6uIxy/9s3Z4K2vU8KbvUpwo+ON4HMt61fgrIrbEUVCl +TMCVEf8UphwHctmQJb/Pr0+BCTdiv04ga1dkt+ZyR2o0VN6T/zKDqk4m1sSl0GZz +8sn63GbuTlwHcm9GgkaxoeeZJK1/sdOSIZN8W3PpnyHrAZJlNOY7G684F1mBaWV1 +PGCcVtkCgYEA8jCDTGub7ZyMk48x+8L3Devja3TQz7YNIGkVEbQBpNw4gDV8j1m6 +EgqFdzowkY+gbA76ylNfm6Aa66RDR/LbTbXlsNd8YkXcbU3xDQ96F6cS51VBkled +hq+iAuGJB9VYN5yP1P/Oswg/AFMjOnsfBL/1zFo26364z9x8zazw0wsCgYEAy907 +mpkk59AQ4YIDSR9wK2YpXv6HoBPFld6m7PAnBWFO0uNtQ0YppbYbrhmDqrxUoFud +ZiEHIa0gLlp9lHr+UdUAMPDlJ6gbMnJW3U5qiVuuZA13tiZFlv11qUeU1tQUzTUv +ZoIISN15Im0PQzUFbTxSFbS+vTYjsedv1C9UOpUCgYEAkTaTUzvmV3cZNtSSFLFW +ros0Zda56QDwJ/G5x06V+cJtQjpPwCf9kBms4ssKGgzzFDd7GdsZpVc/LPDlwnsU +ESkyWnEpzEa1HvivwrP38bykcf5Ffbh45CvkyTNvlTnPVjDScNUcm24jUE+I/OSb +uZ5bg7bH3TWzHDbIwg2iq/cCgYB+DPqvqoVhOAtYBBWX/vJSQ0bNT7/4QIFpG1RH +KG5YK0SbrLeAYz+ZELKowWniBbSluj/mSAGq1usQ/i6rwijB3FvT5v8puA2o8X24 +NKY27BM2FgWxAJUCuREpa/Mhqdx6zanTTg9lTlt558kKGxyR4Dw445sUTwdfFuTU +Y7dGyQKBgAG0vyOdfku9TlPX2a3LasM5jkbxljeTlCJUlahW7LSoQEmLoEhOM4Ja +6CA5PADhA16pOUweKjOtSkNEcVEorFNjlH34PpnsysF+NsDBP5HEy0eYyHSYwg1Y +7BGwQxUOoBaUKMu7jVQcffrKiWOGEXzBDSEZ3A30t7+JIS7qy1d1 +-----END RSA PRIVATE KEY----- |
