From a04393f5542cc02b1af0e4259d98cc40080972d1 Mon Sep 17 00:00:00 2001 From: Shauren Date: Fri, 10 Oct 2014 23:19:40 +0200 Subject: Core/Auth: Moved battle.net handling to separate project --- src/server/CMakeLists.txt | 1 + src/server/authserver/CMakeLists.txt | 1 - src/server/authserver/Main.cpp | 13 - src/server/authserver/PrecompiledHeaders/authPCH.h | 3 - src/server/authserver/Realms/RealmList.cpp | 14 - src/server/authserver/Realms/RealmList.h | 6 - .../authserver/Server/BattlenetBitStream.cpp | 30 - src/server/authserver/Server/BattlenetBitStream.h | 243 ----- src/server/authserver/Server/BattlenetManager.cpp | 96 -- src/server/authserver/Server/BattlenetManager.h | 116 --- .../authserver/Server/BattlenetPacketCrypt.cpp | 42 - .../authserver/Server/BattlenetPacketCrypt.h | 36 - .../authserver/Server/BattlenetPacketFactory.h | 83 -- .../Server/BattlenetPackets/AchievementPackets.h | 42 - .../BattlenetPackets/AuthenticationPackets.h | 196 ---- .../Server/BattlenetPackets/BattlenetPackets.h | 32 - .../BattlenetPackets/BattlenetPacketsBase.cpp | 38 - .../Server/BattlenetPackets/BattlenetPacketsBase.h | 121 --- .../Server/BattlenetPackets/CachePackets.h | 43 - .../Server/BattlenetPackets/ChatPackets.h | 63 -- .../Server/BattlenetPackets/ConnectionPackets.cpp | 54 -- .../Server/BattlenetPackets/ConnectionPackets.h | 94 -- .../Server/BattlenetPackets/FriendsPackets.cpp | 180 ---- .../Server/BattlenetPackets/FriendsPackets.h | 162 ---- .../Server/BattlenetPackets/PresencePackets.cpp | 50 - .../Server/BattlenetPackets/PresencePackets.h | 65 -- .../Server/BattlenetPackets/ProfilePackets.h | 44 - .../Server/BattlenetPackets/SupportPackets.h | 34 - .../Server/BattlenetPackets/WoWRealmPackets.cpp | 202 ---- .../Server/BattlenetPackets/WoWRealmPackets.h | 172 ---- src/server/authserver/Server/BattlenetSession.cpp | 1004 -------------------- src/server/authserver/Server/BattlenetSession.h | 128 --- .../authserver/Server/BattlenetSessionManager.cpp | 37 - .../authserver/Server/BattlenetSessionManager.h | 71 -- src/server/bnetserver/Authentication/AuthCodes.cpp | 55 ++ src/server/bnetserver/Authentication/AuthCodes.h | 128 +++ .../Authentication/BattlenetPacketCrypt.cpp | 42 + .../Authentication/BattlenetPacketCrypt.h | 36 + src/server/bnetserver/CMakeLists.txt | 115 +++ src/server/bnetserver/Main.cpp | 238 +++++ src/server/bnetserver/Packets/AchievementPackets.h | 42 + .../bnetserver/Packets/AuthenticationPackets.cpp | 319 +++++++ .../bnetserver/Packets/AuthenticationPackets.h | 196 ++++ src/server/bnetserver/Packets/BitStream.cpp | 30 + src/server/bnetserver/Packets/BitStream.h | 243 +++++ src/server/bnetserver/Packets/CachePackets.h | 43 + src/server/bnetserver/Packets/ChatPackets.h | 63 ++ .../bnetserver/Packets/ConnectionPackets.cpp | 54 ++ src/server/bnetserver/Packets/ConnectionPackets.h | 94 ++ src/server/bnetserver/Packets/FriendsPackets.cpp | 179 ++++ src/server/bnetserver/Packets/FriendsPackets.h | 162 ++++ src/server/bnetserver/Packets/PacketFactory.h | 83 ++ src/server/bnetserver/Packets/Packets.h | 32 + src/server/bnetserver/Packets/PacketsBase.cpp | 38 + src/server/bnetserver/Packets/PacketsBase.h | 120 +++ src/server/bnetserver/Packets/PresencePackets.cpp | 48 + src/server/bnetserver/Packets/PresencePackets.h | 65 ++ src/server/bnetserver/Packets/ProfilePackets.h | 44 + src/server/bnetserver/Packets/SupportPackets.h | 34 + src/server/bnetserver/Packets/WoWRealmPackets.cpp | 202 ++++ src/server/bnetserver/Packets/WoWRealmPackets.h | 173 ++++ .../bnetserver/PrecompiledHeaders/bnetPCH.cpp | 1 + src/server/bnetserver/PrecompiledHeaders/bnetPCH.h | 10 + src/server/bnetserver/Realms/RealmList.cpp | 207 ++++ src/server/bnetserver/Realms/RealmList.h | 113 +++ src/server/bnetserver/Server/ComponentManager.cpp | 55 ++ src/server/bnetserver/Server/ComponentManager.h | 61 ++ src/server/bnetserver/Server/ModuleManager.cpp | 57 ++ src/server/bnetserver/Server/ModuleManager.h | 94 ++ src/server/bnetserver/Server/Session.cpp | 1000 +++++++++++++++++++ src/server/bnetserver/Server/Session.h | 128 +++ src/server/bnetserver/Server/SessionManager.cpp | 37 + src/server/bnetserver/Server/SessionManager.h | 71 ++ src/server/bnetserver/bnetserver.conf.dist | 257 +++++ src/server/bnetserver/bnetserver.ico | Bin 0 -> 136606 bytes src/server/bnetserver/bnetserver.rc | 94 ++ src/server/bnetserver/resource.h | 15 + 77 files changed, 5079 insertions(+), 3515 deletions(-) delete mode 100644 src/server/authserver/Server/BattlenetBitStream.cpp delete mode 100644 src/server/authserver/Server/BattlenetBitStream.h delete mode 100644 src/server/authserver/Server/BattlenetManager.cpp delete mode 100644 src/server/authserver/Server/BattlenetManager.h delete mode 100644 src/server/authserver/Server/BattlenetPacketCrypt.cpp delete mode 100644 src/server/authserver/Server/BattlenetPacketCrypt.h delete mode 100644 src/server/authserver/Server/BattlenetPacketFactory.h delete mode 100644 src/server/authserver/Server/BattlenetPackets/AchievementPackets.h delete mode 100644 src/server/authserver/Server/BattlenetPackets/AuthenticationPackets.h delete mode 100644 src/server/authserver/Server/BattlenetPackets/BattlenetPackets.h delete mode 100644 src/server/authserver/Server/BattlenetPackets/BattlenetPacketsBase.cpp delete mode 100644 src/server/authserver/Server/BattlenetPackets/BattlenetPacketsBase.h delete mode 100644 src/server/authserver/Server/BattlenetPackets/CachePackets.h delete mode 100644 src/server/authserver/Server/BattlenetPackets/ChatPackets.h delete mode 100644 src/server/authserver/Server/BattlenetPackets/ConnectionPackets.cpp delete mode 100644 src/server/authserver/Server/BattlenetPackets/ConnectionPackets.h delete mode 100644 src/server/authserver/Server/BattlenetPackets/FriendsPackets.cpp delete mode 100644 src/server/authserver/Server/BattlenetPackets/FriendsPackets.h delete mode 100644 src/server/authserver/Server/BattlenetPackets/PresencePackets.cpp delete mode 100644 src/server/authserver/Server/BattlenetPackets/PresencePackets.h delete mode 100644 src/server/authserver/Server/BattlenetPackets/ProfilePackets.h delete mode 100644 src/server/authserver/Server/BattlenetPackets/SupportPackets.h delete mode 100644 src/server/authserver/Server/BattlenetPackets/WoWRealmPackets.cpp delete mode 100644 src/server/authserver/Server/BattlenetPackets/WoWRealmPackets.h delete mode 100644 src/server/authserver/Server/BattlenetSession.cpp delete mode 100644 src/server/authserver/Server/BattlenetSession.h delete mode 100644 src/server/authserver/Server/BattlenetSessionManager.cpp delete mode 100644 src/server/authserver/Server/BattlenetSessionManager.h create mode 100644 src/server/bnetserver/Authentication/AuthCodes.cpp create mode 100644 src/server/bnetserver/Authentication/AuthCodes.h create mode 100644 src/server/bnetserver/Authentication/BattlenetPacketCrypt.cpp create mode 100644 src/server/bnetserver/Authentication/BattlenetPacketCrypt.h create mode 100644 src/server/bnetserver/CMakeLists.txt create mode 100644 src/server/bnetserver/Main.cpp create mode 100644 src/server/bnetserver/Packets/AchievementPackets.h create mode 100644 src/server/bnetserver/Packets/AuthenticationPackets.cpp create mode 100644 src/server/bnetserver/Packets/AuthenticationPackets.h create mode 100644 src/server/bnetserver/Packets/BitStream.cpp create mode 100644 src/server/bnetserver/Packets/BitStream.h create mode 100644 src/server/bnetserver/Packets/CachePackets.h create mode 100644 src/server/bnetserver/Packets/ChatPackets.h create mode 100644 src/server/bnetserver/Packets/ConnectionPackets.cpp create mode 100644 src/server/bnetserver/Packets/ConnectionPackets.h create mode 100644 src/server/bnetserver/Packets/FriendsPackets.cpp create mode 100644 src/server/bnetserver/Packets/FriendsPackets.h create mode 100644 src/server/bnetserver/Packets/PacketFactory.h create mode 100644 src/server/bnetserver/Packets/Packets.h create mode 100644 src/server/bnetserver/Packets/PacketsBase.cpp create mode 100644 src/server/bnetserver/Packets/PacketsBase.h create mode 100644 src/server/bnetserver/Packets/PresencePackets.cpp create mode 100644 src/server/bnetserver/Packets/PresencePackets.h create mode 100644 src/server/bnetserver/Packets/ProfilePackets.h create mode 100644 src/server/bnetserver/Packets/SupportPackets.h create mode 100644 src/server/bnetserver/Packets/WoWRealmPackets.cpp create mode 100644 src/server/bnetserver/Packets/WoWRealmPackets.h create mode 100644 src/server/bnetserver/PrecompiledHeaders/bnetPCH.cpp create mode 100644 src/server/bnetserver/PrecompiledHeaders/bnetPCH.h create mode 100644 src/server/bnetserver/Realms/RealmList.cpp create mode 100644 src/server/bnetserver/Realms/RealmList.h create mode 100644 src/server/bnetserver/Server/ComponentManager.cpp create mode 100644 src/server/bnetserver/Server/ComponentManager.h create mode 100644 src/server/bnetserver/Server/ModuleManager.cpp create mode 100644 src/server/bnetserver/Server/ModuleManager.h create mode 100644 src/server/bnetserver/Server/Session.cpp create mode 100644 src/server/bnetserver/Server/Session.h create mode 100644 src/server/bnetserver/Server/SessionManager.cpp create mode 100644 src/server/bnetserver/Server/SessionManager.h create mode 100644 src/server/bnetserver/bnetserver.conf.dist create mode 100644 src/server/bnetserver/bnetserver.ico create mode 100644 src/server/bnetserver/bnetserver.rc create mode 100644 src/server/bnetserver/resource.h (limited to 'src') diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt index 05cbe51b15d..ea2ad3abac7 100644 --- a/src/server/CMakeLists.txt +++ b/src/server/CMakeLists.txt @@ -25,6 +25,7 @@ if( SERVERS ) add_subdirectory(game) add_subdirectory(collision) add_subdirectory(authserver) + add_subdirectory(bnetserver) add_subdirectory(scripts) add_subdirectory(worldserver) else() diff --git a/src/server/authserver/CMakeLists.txt b/src/server/authserver/CMakeLists.txt index ae706973ff7..b40b8c906f4 100644 --- a/src/server/authserver/CMakeLists.txt +++ b/src/server/authserver/CMakeLists.txt @@ -58,7 +58,6 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/Authentication ${CMAKE_CURRENT_SOURCE_DIR}/Realms ${CMAKE_CURRENT_SOURCE_DIR}/Server - ${CMAKE_CURRENT_SOURCE_DIR}/Server/BattlenetPackets ${MYSQL_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR} ${VALGRIND_INCLUDE_DIR} diff --git a/src/server/authserver/Main.cpp b/src/server/authserver/Main.cpp index e614b2b79fa..5f08ebe3127 100644 --- a/src/server/authserver/Main.cpp +++ b/src/server/authserver/Main.cpp @@ -25,8 +25,6 @@ */ #include "AuthSocketMgr.h" -#include "BattlenetManager.h" -#include "BattlenetSessionManager.h" #include "Common.h" #include "Config.h" #include "DatabaseEnv.h" @@ -117,18 +115,9 @@ int main(int argc, char** argv) return 1; } - int32 bnport = sConfigMgr->GetIntDefault("BattlenetPort", 1119); - if (bnport < 0 || bnport > 0xFFFF) - { - TC_LOG_ERROR("server.authserver", "Specified battle.net port (%d) out of allowed range (1-65535)", bnport); - StopDB(); - return 1; - } - std::string bindIp = sConfigMgr->GetStringDefault("BindIP", "0.0.0.0"); sAuthSocketMgr.StartNetwork(_ioService, bindIp, port); - sBattlenetSessionMgr.StartNetwork(_ioService, bindIp, bnport); // Set signal handlers boost::asio::signal_set signals(_ioService, SIGINT, SIGTERM); @@ -145,8 +134,6 @@ int main(int argc, char** argv) _dbPingTimer.expires_from_now(boost::posix_time::minutes(_dbPingInterval)); _dbPingTimer.async_wait(KeepDatabaseAliveHandler); - sBattlenetMgr->Load(); - // Start the io service worker loop _ioService.run(); diff --git a/src/server/authserver/PrecompiledHeaders/authPCH.h b/src/server/authserver/PrecompiledHeaders/authPCH.h index b509f8caaa0..90424161344 100644 --- a/src/server/authserver/PrecompiledHeaders/authPCH.h +++ b/src/server/authserver/PrecompiledHeaders/authPCH.h @@ -2,9 +2,6 @@ #include "Configuration/Config.h" #include "Database/DatabaseEnv.h" #include "Log.h" -#include "BattlenetManager.h" #include "RealmList.h" #include "ByteBuffer.h" -#include "BattlenetPackets.h" #include "AuthSession.h" -#include "BattlenetSession.h" diff --git a/src/server/authserver/Realms/RealmList.cpp b/src/server/authserver/Realms/RealmList.cpp index 2110dc1fecc..662a015dc65 100644 --- a/src/server/authserver/Realms/RealmList.cpp +++ b/src/server/authserver/Realms/RealmList.cpp @@ -19,7 +19,6 @@ #include #include "Common.h" #include "RealmList.h" -#include "BattlenetManager.h" #include "Database/DatabaseEnv.h" #include "Util.h" @@ -193,16 +192,3 @@ void RealmList::UpdateRealms(bool init) while (result->NextRow()); } } - -Realm const* RealmList::GetRealm(Battlenet::RealmId const& id) const -{ - auto itr = std::find_if(m_realms.begin(), m_realms.end(), [id](RealmMap::value_type const& pair) - { - return pair.second.Region == id.Region && pair.second.Battlegroup == id.Battlegroup && pair.second.m_ID == id.Index; - }); - - if (itr != m_realms.end()) - return &itr->second; - - return NULL; -} diff --git a/src/server/authserver/Realms/RealmList.h b/src/server/authserver/Realms/RealmList.h index 0063b1a60c8..f7a98cda686 100644 --- a/src/server/authserver/Realms/RealmList.h +++ b/src/server/authserver/Realms/RealmList.h @@ -60,11 +60,6 @@ struct Realm ip::tcp::endpoint GetAddressForClient(ip::address const& clientAddr) const; }; -namespace Battlenet -{ - struct RealmId; -} - /// Storage object for the list of realms on the server class RealmList { @@ -88,7 +83,6 @@ public: RealmMap::const_iterator begin() const { return m_realms.begin(); } RealmMap::const_iterator end() const { return m_realms.end(); } uint32 size() const { return m_realms.size(); } - Realm const* GetRealm(Battlenet::RealmId const& id) const; private: RealmList(); diff --git a/src/server/authserver/Server/BattlenetBitStream.cpp b/src/server/authserver/Server/BattlenetBitStream.cpp deleted file mode 100644 index 712c9e58f08..00000000000 --- a/src/server/authserver/Server/BattlenetBitStream.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * - * 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 . - */ - -#include "BattlenetBitStream.h" - -template<> -bool Battlenet::BitStream::Read(uint32 /*bitCount*/) -{ - return Read(1) != 0; -} - -template<> -void Battlenet::BitStream::Write(bool value, uint32 /*bitCount*/) -{ - Write(value ? 1 : 0, 1); -} diff --git a/src/server/authserver/Server/BattlenetBitStream.h b/src/server/authserver/Server/BattlenetBitStream.h deleted file mode 100644 index 3601c3b0b0c..00000000000 --- a/src/server/authserver/Server/BattlenetBitStream.h +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * - * 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 . - */ - -#ifndef __BATTLENETBITSTREAM_H__ -#define __BATTLENETBITSTREAM_H__ - -#include "Common.h" -#include "ByteConverter.h" -#include "MessageBuffer.h" -#include -#include -#include -#include - -namespace Battlenet -{ - 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(buffer.GetActiveSize() * 8), _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(bitCount) + baseLength; - AlignToNextByte(); - std::string str(reinterpret_cast(&_buffer[_readPos >> 3]), len); - _readPos += len * 8; - return str; - } - - std::unique_ptr ReadBytes(uint32 count) - { - AlignToNextByte(); - if (_readPos + count * 8 > _writePos) - throw BitStreamPositionException(true, count * 8, _readPos, _writePos); - - std::unique_ptr buf(new uint8[count]); - memcpy(buf.get(), &_buffer[_readPos >> 3], count); - _readPos += count * 8; - return buf; - } - - float ReadFloat() - { - uint32 val = Read(32); - return *reinterpret_cast(&val); - } - - std::string ReadFourCC() - { - uint32 fcc = Read(32); - EndianConvertReverse(fcc); - size_t len = 4; - while (!(fcc & 0xFF)) - { - fcc >>= 8; - --len; - } - - return std::string(reinterpret_cast(&fcc), len); - } - - template - T Read(uint32 bitCount) - { - static_assert(std::is_integral::value || std::is_enum::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(ret); - } - - void WriteString(std::string const& str, uint32 bitCount, int32 baseLength = 0) - { - Write(str.length() + baseLength, bitCount); - WriteBytes(str.c_str(), str.length()); - } - - template - 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) - { - uint32 intVal = *reinterpret_cast(&value); - Write(intVal, 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 - void Write(T value, uint32 bitCount) - { - static_assert(std::is_integral::value || std::is_enum::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; - } - } - - void SetReadPos(uint32 bits) - { - if (bits > _writePos) - throw BitStreamPositionException(true, bits, 0, _writePos); - - _readPos = bits; - } - - bool IsRead() const { return _readPos >= _writePos; } - - uint8* GetBuffer() { return _buffer.data(); } - uint8 const* GetBuffer() const { return _buffer.data(); } - - size_t GetSize() const { return ((_writePos + 7) & ~7) / 8; } - - private: - uint32 _writePos; - uint32 _readPos; - std::vector _buffer; - }; - - template<> - bool BitStream::Read(uint32 bitCount); - - template<> - void BitStream::Write(bool value, uint32 bitCount); -} - -#endif // __BATTLENETBITSTREAM_H__ diff --git a/src/server/authserver/Server/BattlenetManager.cpp b/src/server/authserver/Server/BattlenetManager.cpp deleted file mode 100644 index f470c365b56..00000000000 --- a/src/server/authserver/Server/BattlenetManager.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * - * 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 . - */ - -#include "BattlenetManager.h" -#include "DatabaseEnv.h" - -BattlenetMgr::~BattlenetMgr() -{ - for (Battlenet::Component* component : _components) - delete component; - - for (auto const& m : _modules) - delete m.second; -} - -void BattlenetMgr::Load() -{ - LoadComponents(); - LoadModules(); -} - -void BattlenetMgr::LoadComponents() -{ - QueryResult result = LoginDatabase.Query("SELECT Program, Platform, Build FROM battlenet_components"); - if (result) - { - do - { - Field* fields = result->Fetch(); - Battlenet::Component* component = new Battlenet::Component(); - component->Program = fields[0].GetString(); - component->Platform = fields[1].GetString(); - component->Build = fields[2].GetUInt32(); - - _components.insert(component); - _programs.insert(component->Program); - _platforms.insert(component->Platform); - - } while (result->NextRow()); - } -} - -void BattlenetMgr::LoadModules() -{ - QueryResult result = LoginDatabase.Query("SELECT `Hash`, `Name`, `Type`, `System`, `Data` FROM battlenet_modules"); - if (result) - { - do - { - Field* fields = result->Fetch(); - Battlenet::ModuleInfo* module = new Battlenet::ModuleInfo(); - module->Type = fields[2].GetString(); - HexStrToByteArray(fields[0].GetString(), module->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()); - } -} - -bool BattlenetMgr::HasComponent(Battlenet::Component const* component) const -{ - for (Battlenet::Component const* c : _components) - if (component->Program == c->Program && component->Platform == c->Platform && component->Build == c->Build) - return true; - - return false; -} - -Battlenet::ModuleInfo* BattlenetMgr::CreateModule(std::string const& os, std::string const& name) const -{ - Battlenet::ModuleKey key { os, name }; - ASSERT(_modules.count(key)); - - return new Battlenet::ModuleInfo(*_modules.at(key)); -} diff --git a/src/server/authserver/Server/BattlenetManager.h b/src/server/authserver/Server/BattlenetManager.h deleted file mode 100644 index bd01619ef06..00000000000 --- a/src/server/authserver/Server/BattlenetManager.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * - * 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 . - */ - -#ifndef __BATTLENETMANAGER_H__ -#define __BATTLENETMANAGER_H__ - -#include "Define.h" -#include -#include -#include -#include - -namespace Battlenet -{ - struct Component - { - std::string Program; - std::string Platform; - uint32 Build; - }; - - 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 - { - ModuleInfo() : Region("EU"), DataSize(0), Data(nullptr) { } - ModuleInfo(ModuleInfo const& right) : Type(right.Type), Region(right.Region), DataSize(right.DataSize), Data(nullptr) - { - memcpy(ModuleId, right.ModuleId, 32); - if (DataSize) - { - Data = new uint8[DataSize]; - memcpy(Data, right.Data, DataSize); - } - } - ~ModuleInfo() - { - delete Data; - } - - std::string Type; - std::string Region; - uint8 ModuleId[32]; - uint32 DataSize; - uint8* Data; - }; - - struct RealmId - { - uint8 Region; - uint8 Battlegroup; - uint32 Index; - uint32 Build; - }; -} - -class BattlenetMgr -{ - BattlenetMgr() { } - ~BattlenetMgr(); - -public: - void Load(); - bool HasComponent(Battlenet::Component 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; } - Battlenet::ModuleInfo* CreateModule(std::string const& os, std::string const& name) const; - - static BattlenetMgr* instance() - { - static BattlenetMgr instance; - return &instance; - } - -private: - void LoadComponents(); - void LoadModules(); - - std::set _components; - std::set _programs; - std::set _platforms; - std::map _modules; -}; - -#define sBattlenetMgr BattlenetMgr::instance() - -#endif // __BATTLENETMANAGER_H__ diff --git a/src/server/authserver/Server/BattlenetPacketCrypt.cpp b/src/server/authserver/Server/BattlenetPacketCrypt.cpp deleted file mode 100644 index de4cf73f71c..00000000000 --- a/src/server/authserver/Server/BattlenetPacketCrypt.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * - * 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 . - */ - -#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/authserver/Server/BattlenetPacketCrypt.h b/src/server/authserver/Server/BattlenetPacketCrypt.h deleted file mode 100644 index dde687651d3..00000000000 --- a/src/server/authserver/Server/BattlenetPacketCrypt.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * - * 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 . - */ - -#ifndef __BATTLENETPACKETCRYPT_H__ -#define __BATTLENETPACKETCRYPT_H__ - -#include "PacketCrypt.h" - -class BigNumber; - -namespace Battlenet -{ - class PacketCrypt : public ::PacketCrypt - { - public: - PacketCrypt(); - - void Init(BigNumber* K) override; - }; -} - -#endif // __BATTLENETPACKETCRYPT_H__ diff --git a/src/server/authserver/Server/BattlenetPacketFactory.h b/src/server/authserver/Server/BattlenetPacketFactory.h deleted file mode 100644 index a0cbd8f5913..00000000000 --- a/src/server/authserver/Server/BattlenetPacketFactory.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * - * 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 . - */ - -#ifndef BattlenetPacketFactory_h__ -#define BattlenetPacketFactory_h__ - -#include "BattlenetPackets.h" -#include - -namespace Battlenet -{ - class PacketFactory - { - typedef ClientPacket*(*PacketCreateFn)(PacketHeader const& header, BitStream& stream); - - public: - ClientPacket* Create(PacketHeader const& header, BitStream& stream) - { - auto creator = _creators.find(header); - if (creator == _creators.end()) - return nullptr; - - ClientPacket* packet = creator->second(header, stream); - packet->Read(); - return packet; - } - - static PacketFactory& Instance() - { - static PacketFactory instance; - return instance; - } - - private: - PacketFactory() - { - _creators[PacketHeader(Authentication::CMSG_LOGON_REQUEST, AUTHENTICATION)] = &New; - _creators[PacketHeader(Authentication::CMSG_RESUME_REQUEST, AUTHENTICATION)] = &New; - _creators[PacketHeader(Authentication::CMSG_PROOF_RESPONSE, AUTHENTICATION)] = &New; - - _creators[PacketHeader(Connection::CMSG_PING, CONNECTION)] = &New; - _creators[PacketHeader(Connection::CMSG_ENABLE_ENCRYPTION, CONNECTION)] = &New; - _creators[PacketHeader(Connection::CMSG_LOGOUT_REQUEST, CONNECTION)] = &New; - - _creators[PacketHeader(WoWRealm::CMSG_LIST_SUBSCRIBE_REQUEST, WOWREALM)] = &New; - _creators[PacketHeader(WoWRealm::CMSG_JOIN_REQUEST_V2, WOWREALM)] = &New; - - _creators[PacketHeader(Friends::CMSG_SOCIAL_NETWORK_CHECK_CONNECTED, FRIENDS)] = &New; - // _creators[PacketHeader(Friends::CMSG_SOCIAL_NETWORK_CONNECT, FRIENDS)] = &New; - // _creators[PacketHeader(Friends::CMSG_GET_FRIENDS_OF_FRIEND, FRIENDS)] = &New; - _creators[PacketHeader(Friends::CMSG_REALID_FRIEND_INVITE, FRIENDS)] = &New; - - // _creators[PacketHeader(Presence::CMSG_UPDATE_REQUEST, PRESENCE)] = &New; - // _creators[PacketHeader(Presence::CMSG_STATISTIC_SUBSCRIBE, PRESENCE)] = &New; - } - - template - static ClientPacket* New(PacketHeader const& header, BitStream& stream) - { - return new PacketType(header, stream); - } - - std::map _creators; - }; -} - -#define sBattlenetPacketFactory Battlenet::PacketFactory::Instance() - -#endif // BattlenetPacketFactory_h__ diff --git a/src/server/authserver/Server/BattlenetPackets/AchievementPackets.h b/src/server/authserver/Server/BattlenetPackets/AchievementPackets.h deleted file mode 100644 index 69a03c7e16d..00000000000 --- a/src/server/authserver/Server/BattlenetPackets/AchievementPackets.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * - * 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 . - */ - -#ifndef AchievementPackets_h__ -#define AchievementPackets_h__ - -#include "BattlenetPacketsBase.h" - -namespace Battlenet -{ - namespace Achievement - { - enum Opcode - { - CMSG_LISTEN_REQUEST = 0x0, // Not implemented - CMSG_CRITERIA_FLUSH_REQUEST = 0x3, // Not implemented - CMSG_CHANGE_TROPHY_CASE_REQUEST = 0x5, // Not implemented - - 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 - }; - } -} - -#endif // AchievementPackets_h__ - diff --git a/src/server/authserver/Server/BattlenetPackets/AuthenticationPackets.h b/src/server/authserver/Server/BattlenetPackets/AuthenticationPackets.h deleted file mode 100644 index 90dd4a35b1c..00000000000 --- a/src/server/authserver/Server/BattlenetPackets/AuthenticationPackets.h +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * - * 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 . - */ - -#ifndef AuthenticationPackets_h__ -#define AuthenticationPackets_h__ - -#include "BattlenetPacketsBase.h" - -namespace Battlenet -{ - namespace Authentication - { - enum Opcode - { - CMSG_LOGON_REQUEST = 0x0, - CMSG_RESUME_REQUEST = 0x1, - CMSG_PROOF_RESPONSE = 0x2, - - SMSG_LOGON_RESPONSE = 0x0, - SMSG_RESUME_RESPONSE = 0x1, - SMSG_PROOF_REQUEST = 0x2, - SMSG_PATCH = 0x3, // Not implemented - SMSG_AUTHORIZED_LICENSES = 0x4 // Not implemented - }; - - class LogonRequest final : public ClientPacket - { - public: - LogonRequest(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) - { - ASSERT(header == PacketHeader(CMSG_LOGON_REQUEST, AUTHENTICATION) && "Invalid packet header for LogonRequest"); - } - - void Read() override; - std::string ToString() const override; - void CallHandler(Session* session) const override; - - std::string Program; - std::string Platform; - std::string Locale; - std::vector Components; - std::string Login; - }; - - 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) const override; - - std::string Program; - std::string Platform; - std::string Locale; - std::vector Components; - std::string Login; - uint8 Region; - 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) const override; - - std::vector Modules; - }; - - class ProofRequest final : public ServerPacket - { - public: - ProofRequest() : ServerPacket(PacketHeader(SMSG_PROOF_REQUEST, AUTHENTICATION)) { } - ~ProofRequest(); - - void Write() override; - std::string ToString() const override; - - std::vector Modules; - }; - - class ResponseFailure - { - public: - enum Result - { - UPDATE = 0, - FAILURE = 1, - VERSION_CHECK_DISCONNECT = 2 - }; - - ResponseFailure() : ResultValue(UPDATE), Error(AUTH_OK), Wait(0) { } - - Result ResultValue; - AuthResult Error; - int32 Wait; - }; - - class Regulator - { - public: - enum Info - { - NONE = 0, - LEAKY_BUCKET = 1 - }; - - Regulator() : Type(LEAKY_BUCKET), Threshold(25000000), Rate(1000) { } - - Info Type; - uint32 Threshold; - uint32 Rate; - }; - - class LogonResponse final : public ServerPacket - { - public: - LogonResponse() : ServerPacket(PacketHeader(SMSG_LOGON_RESPONSE, AUTHENTICATION)), - PingTimeout(120000), FirstName(""), LastName(""), AccountId(0), Region(2), Flags(0), - GameAccountRegion(2), GameAccountName(""), FailedLogins(0) - { - } - - ~LogonResponse(); - - void Write() override; - std::string ToString() const override; - - std::vector Modules; - void SetAuthResult(AuthResult result); - ResponseFailure Result; - - int32 PingTimeout; - Regulator RegulatorRules; - std::string FirstName; - std::string LastName; - uint32 AccountId; - uint8 Region; - uint64 Flags; - uint8 GameAccountRegion; - std::string GameAccountName; - uint64 GameAccountFlags; - - uint32 FailedLogins; - }; - - class ResumeResponse final : public ServerPacket - { - public: - ResumeResponse() : ServerPacket(PacketHeader(SMSG_RESUME_RESPONSE, AUTHENTICATION)), PingTimeout(120000) - { - } - - ~ResumeResponse(); - - void Write() override; - std::string ToString() const override; - - std::vector Modules; - void SetAuthResult(AuthResult result); - ResponseFailure Result; - - int32 PingTimeout; - Regulator RegulatorRules; - }; - } -} - -#endif // AuthenticationPackets_h__ diff --git a/src/server/authserver/Server/BattlenetPackets/BattlenetPackets.h b/src/server/authserver/Server/BattlenetPackets/BattlenetPackets.h deleted file mode 100644 index d4cd8600266..00000000000 --- a/src/server/authserver/Server/BattlenetPackets/BattlenetPackets.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * - * 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 . - */ - -#ifndef BattlenetPackets_h__ -#define BattlenetPackets_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 // BattlenetPackets_h__ diff --git a/src/server/authserver/Server/BattlenetPackets/BattlenetPacketsBase.cpp b/src/server/authserver/Server/BattlenetPackets/BattlenetPacketsBase.cpp deleted file mode 100644 index 034bb8ba0a4..00000000000 --- a/src/server/authserver/Server/BattlenetPackets/BattlenetPacketsBase.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * - * 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 . - */ - -#include "BattlenetPackets.h" -#include - -std::string Battlenet::PacketHeader::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::PacketHeader opcode: " << Opcode << ", channel: " << Channel; - return stream.str(); -} - -Battlenet::ServerPacket::ServerPacket(PacketHeader const& header) : Packet(header, *new BitStream()) -{ - _stream.Write(header.Opcode, 6); - _stream.Write(1, 1); - _stream.Write(header.Channel, 4); -} - -Battlenet::ServerPacket::~ServerPacket() -{ - delete &_stream; -} diff --git a/src/server/authserver/Server/BattlenetPackets/BattlenetPacketsBase.h b/src/server/authserver/Server/BattlenetPackets/BattlenetPacketsBase.h deleted file mode 100644 index 2aa07314771..00000000000 --- a/src/server/authserver/Server/BattlenetPackets/BattlenetPacketsBase.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * - * 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 . - */ - -#ifndef BattlenetPacketsBase_h__ -#define BattlenetPacketsBase_h__ - -#include "AuthCodes.h" -#include "BattlenetBitStream.h" -#include "BattlenetManager.h" -#include "Define.h" -#include "Errors.h" -#include -#include - -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 - { - PacketHeader(uint32 opcode, uint32 channel) : Opcode(opcode), Channel(channel) { } - PacketHeader() : Opcode(0), Channel(AUTHENTICATION) { } - - uint32 Opcode; - int32 Channel; - - bool operator<(PacketHeader const& right) const - { - if (Opcode < right.Opcode) - return true; - if (Opcode > right.Opcode) - return false; - - return Channel < right.Channel; - } - - bool operator==(PacketHeader const& right) const - { - return Opcode == right.Opcode && Channel == right.Channel; - } - - std::string ToString() const; - }; - - class Packet - { - 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; - - virtual std::string ToString() const = 0; - - protected: - PacketHeader _header; - BitStream& _stream; - - private: - Packet(Packet const& right); - Packet& operator=(Packet const& right); - }; - - class ClientPacket : public Packet - { - public: - ClientPacket(PacketHeader const& header, BitStream& stream) : Packet(header, stream) { } - - void Write() override final { ASSERT(!"Write not implemented for this packet."); } - virtual void CallHandler(Session* session) const = 0; - }; - - 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 // BattlenetPacketsBase_h__ diff --git a/src/server/authserver/Server/BattlenetPackets/CachePackets.h b/src/server/authserver/Server/BattlenetPackets/CachePackets.h deleted file mode 100644 index 6354201dc4c..00000000000 --- a/src/server/authserver/Server/BattlenetPackets/CachePackets.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * - * 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 . - */ - -#ifndef CachePackets_h__ -#define CachePackets_h__ - -#include "BattlenetPacketsBase.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 - SMSG_GET_STREAM_ITEMS_REQUEST = 0x9, // Not implemented - - 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 // Not implemented - }; - } -} - -#endif // CachePackets_h__ diff --git a/src/server/authserver/Server/BattlenetPackets/ChatPackets.h b/src/server/authserver/Server/BattlenetPackets/ChatPackets.h deleted file mode 100644 index ee11a1b732e..00000000000 --- a/src/server/authserver/Server/BattlenetPackets/ChatPackets.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * - * 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 . - */ - -#ifndef ChatPackets_h__ -#define ChatPackets_h__ - -#include "BattlenetPacketsBase.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, // 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, // Not implemented - SMSG_CONFIG_CHANGED = 0x1D // Not implemented - }; - } -} - -#endif // ChatPackets_h__ diff --git a/src/server/authserver/Server/BattlenetPackets/ConnectionPackets.cpp b/src/server/authserver/Server/BattlenetPackets/ConnectionPackets.cpp deleted file mode 100644 index f0c3f3ea5e6..00000000000 --- a/src/server/authserver/Server/BattlenetPackets/ConnectionPackets.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * - * 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 . - */ - -#include "BattlenetSession.h" -#include "ConnectionPackets.h" - -std::string Battlenet::Connection::Ping::ToString() const -{ - return "Battlenet::Connection::Ping"; -} - -void Battlenet::Connection::Ping::CallHandler(Session* session) const -{ - session->HandlePing(*this); -} - -std::string Battlenet::Connection::EnableEncryption::ToString() const -{ - return "Battlenet::Connection::EnableEncryption"; -} - -void Battlenet::Connection::EnableEncryption::CallHandler(Session* session) const -{ - session->HandleEnableEncryption(*this); -} - -std::string Battlenet::Connection::LogoutRequest::ToString() const -{ - return "Battlenet::Connection::LogoutRequest"; -} - -void Battlenet::Connection::LogoutRequest::CallHandler(Session* session) const -{ - session->HandleLogoutRequest(*this); -} - -std::string Battlenet::Connection::Pong::ToString() const -{ - return "Battlenet::Connection::Pong"; -} diff --git a/src/server/authserver/Server/BattlenetPackets/ConnectionPackets.h b/src/server/authserver/Server/BattlenetPackets/ConnectionPackets.h deleted file mode 100644 index cc25f73f810..00000000000 --- a/src/server/authserver/Server/BattlenetPackets/ConnectionPackets.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * - * 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 . - */ - -#ifndef ConnectionPackets_h__ -#define ConnectionPackets_h__ - -#include "BattlenetPacketsBase.h" - -namespace Battlenet -{ - namespace Connection - { - enum Opcode - { - CMSG_PING = 0x0, - CMSG_ENABLE_ENCRYPTION = 0x5, - CMSG_LOGOUT_REQUEST = 0x6, - CMSG_DISCONNECT_REQUEST = 0x7, // Not implemented - CMSG_CONNECTION_CLOSING = 0x9, // Not implemented - - 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) const 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) const override; - }; - - 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) const override; - }; - - 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/authserver/Server/BattlenetPackets/FriendsPackets.cpp b/src/server/authserver/Server/BattlenetPackets/FriendsPackets.cpp deleted file mode 100644 index 336755acd4c..00000000000 --- a/src/server/authserver/Server/BattlenetPackets/FriendsPackets.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * - * 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 . - */ - -#include "BattlenetSession.h" -#include "FriendsPackets.h" - -void Battlenet::Friends::SocialnetworkCheckConnected::Read() -{ - SocialNetworkId = _stream.Read(32); -} - -std::string Battlenet::Friends::SocialnetworkCheckConnected::ToString() const -{ - return "Battlenet::Friends::SocialnetworkCheckConnected SocialNetworkId " + std::to_string(SocialNetworkId); -} - -void Battlenet::Friends::SocialnetworkCheckConnected::CallHandler(Session* session) const -{ - SocialNetworkCheckConnectedResult* result = new SocialNetworkCheckConnectedResult(SocialNetworkId); - session->AsyncWrite(result); -} - -void Battlenet::Friends::SocialnetworkConnect::Read() -{ - int32 unk1 = _stream.Read(32); - uint32 size1 = _stream.Read(9); - auto data1 = _stream.ReadBytes(size1); - uint32 size2 = _stream.Read(7); - auto data2 = _stream.ReadBytes(size2); -} - -std::string Battlenet::Friends::SocialnetworkConnect::ToString() const -{ - return "Battlenet::Friends::SocialnetworkConnect"; -} - -void Battlenet::Friends::SocialnetworkConnect::CallHandler(Session* session) const -{ - -} - -std::string Battlenet::Friends::SocialNetworkConnectResult::ToString() const -{ - return "Battlenet::Friends::SocialNetworkConnectResult"; -} - -void Battlenet::Friends::SocialNetworkConnectResult::Write() -{ - -} - -std::string Battlenet::Friends::SocialNetworkCheckConnectedResult::ToString() const -{ - return "Battlenet::Friends::SocialNetworkCheckConnectedResult"; -} - -void Battlenet::Friends::SocialNetworkCheckConnectedResult::Write() -{ - _stream.Write(0, 23); // Ignored - volatile uint16 res = 0; - _stream.Write(res, 16); // Unknown - _stream.Write(SocialNetworkId, 32); -} - -void Battlenet::Friends::GetFriendsOfFriend::Read() -{ - uint8 unk = _stream.Read(2); - uint32 unk1 = _stream.Read(32); -} - -std::string Battlenet::Friends::GetFriendsOfFriend::ToString() const -{ - return "Battlenet::Friends::GetFriendsOfFriend"; -} - -void Battlenet::Friends::GetFriendsOfFriend::CallHandler(Session* session) const -{ - -} - -void Battlenet::Friends::RealIdFriendInvite::Read() -{ - _stream.Read(32); - uint8 type = _stream.Read(3); - - switch (type) - { - case 0: - { - _stream.Read(32); // Presence Id? - break; - } - case 1: // GameAccount? - { - _stream.Read(8); - _stream.Read(32); - _stream.Read(32); - uint8 size = _stream.Read(7); // Only if *(a1 + 16) <= 0x64 - _stream.ReadBytes(size); - break; - } - case 2: - Email = _stream.ReadString(9, 3); - break; - case 3: - { - _stream.Read(32); - break; - } - case 4: - { - _stream.Read(64); - _stream.Read(32); - break; - } - } - - _stream.Read(1); - - if (_stream.Read(1)) - Message = _stream.ReadString(9); - - _stream.Read(32); -} - -std::string Battlenet::Friends::RealIdFriendInvite::ToString() const -{ - return "Battlenet::Friends::RealIdFriendInvite Mail: " + Email + " Message: " + Message; -} - -void Battlenet::Friends::RealIdFriendInvite::CallHandler(Session* session) const -{ - FriendInviteResult* result = new FriendInviteResult(); - session->AsyncWrite(result); -} - -std::string Battlenet::Friends::FriendInviteResult::ToString() const -{ - return "Battlenet::Friends::RealIdFriendInviteResult"; -} - -void Battlenet::Friends::FriendInviteResult::Write() -{ - bool hasNames = false; - _stream.Write(hasNames, 1); - if (hasNames) - { - _stream.WriteString("Testing1", 8); - _stream.WriteString("Testing2", 8); - } - _stream.Write(5, 32); - - _stream.Write(0, 0xC); // Ignored - - _stream.Write(1, 16); - - bool moreInfo = true; - _stream.Write(moreInfo, 1); - if (moreInfo) - { - _stream.Write(0, 8); - _stream.Write(4, 32); - _stream.Write(3, 32); - _stream.WriteString("Testing3", 7, 2); - } -} diff --git a/src/server/authserver/Server/BattlenetPackets/FriendsPackets.h b/src/server/authserver/Server/BattlenetPackets/FriendsPackets.h deleted file mode 100644 index e58fbdff180..00000000000 --- a/src/server/authserver/Server/BattlenetPackets/FriendsPackets.h +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * - * 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 . - */ - -#ifndef FriendsPackets_h__ -#define FriendsPackets_h__ - -#include "BattlenetPacketsBase.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, // Not implemented - CMSG_SOCIAL_NETWORK_CONNECT = 0x0F, // Not implemented - CMSG_SOCIAL_NETWORK_DISCONNECT = 0x11, // Not implemented - CMSG_SOCIAL_NETWORK_CHECK_CONNECTED = 0x13, - CMSG_REALID_FRIEND_INVITE = 0x16, // 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, // Not implemented - SMSG_BLOCK_ADD_FAILURE = 0x09, // Not implemented - SMSG_FRIENDS_OF_FRIEND = 0x0C, // Not implemented - SMSG_SOCIAL_NETWORK_FRIENDS = 0x0E, // Not implemented - SMSG_SOCIAL_NETWORK_CONNECT_RESULT = 0x10, // Not implemented - SMSG_SOCIAL_NETWORK_DISCONNECT_RESULT = 0x12, // Not implemented - SMSG_SOCIAL_NETWORK_CHECK_CONNECTED_RESULT = 0x14, - SMSG_MAX_FRIENDS_NOTIFY = 0x15, // Not implemented - SMSG_FRIENDS_LIST_NOTIFY_3 = 0x18 // Not implemented - }; - - class SocialnetworkConnect final : public ClientPacket - { - public: - SocialnetworkConnect(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) - { - ASSERT(header == PacketHeader(CMSG_SOCIAL_NETWORK_CONNECT, FRIENDS) && "Invalid packet header for SocialnetworkConnect"); - } - - void Read() override; - std::string ToString() const override; - void CallHandler(Session* session) const override; - }; - - class SocialNetworkConnectResult final : public ServerPacket - { - public: - SocialNetworkConnectResult() : ServerPacket(PacketHeader(SMSG_SOCIAL_NETWORK_CONNECT_RESULT, FRIENDS)) - { - } - - void Write() override; - std::string ToString() const override; - }; - - class SocialnetworkCheckConnected final : public ClientPacket - { - public: - SocialnetworkCheckConnected(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) - { - ASSERT(header == PacketHeader(CMSG_SOCIAL_NETWORK_CHECK_CONNECTED, FRIENDS) && "Invalid packet header for SocialNetworkCheckConnected"); - } - - void Read() override; - std::string ToString() const override; - void CallHandler(Session* session) const override; - - uint32 SocialNetworkId; - }; - - class SocialNetworkCheckConnectedResult final : public ServerPacket - { - public: - SocialNetworkCheckConnectedResult(uint32 socialNetworkId) : ServerPacket(PacketHeader(SMSG_SOCIAL_NETWORK_CHECK_CONNECTED_RESULT, FRIENDS)), SocialNetworkId(socialNetworkId) - { - } - - void Write() override; - std::string ToString() const override; - - uint32 SocialNetworkId; - }; - - class GetFriendsOfFriend final : public ClientPacket - { - public: - GetFriendsOfFriend(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) - { - ASSERT(header == PacketHeader(CMSG_GET_FRIENDS_OF_FRIEND, FRIENDS) && "Invalid packet header for GetFriendsOfFriend"); - } - - void Read() override; - std::string ToString() const override; - void CallHandler(Session* session) const override; - }; - - class FriendsOfFriend final : public ServerPacket - { - public: - FriendsOfFriend() : ServerPacket(PacketHeader(SMSG_FRIENDS_OF_FRIEND, FRIENDS)) - { - } - - void Write() override; - std::string ToString() const override; - }; - - class RealIdFriendInvite final : public ClientPacket - { - public: - RealIdFriendInvite(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) - { - ASSERT(header == PacketHeader(CMSG_REALID_FRIEND_INVITE, FRIENDS) && "Invalid packet header for RealIdFriendInvite"); - } - - void Read() override; - std::string ToString() const override; - void CallHandler(Session* session) const override; - - std::string Email; - std::string Message; - }; - - class FriendInviteResult final : public ServerPacket - { - public: - FriendInviteResult() : ServerPacket(PacketHeader(SMSG_FRIEND_INVITE_RESULT, FRIENDS)) - { - } - - void Write() override; - std::string ToString() const override; - }; - } -} - -#endif // FriendsPackets_h__ diff --git a/src/server/authserver/Server/BattlenetPackets/PresencePackets.cpp b/src/server/authserver/Server/BattlenetPackets/PresencePackets.cpp deleted file mode 100644 index 46ce7fa1b36..00000000000 --- a/src/server/authserver/Server/BattlenetPackets/PresencePackets.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * - * 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 . - */ - -#include "BattlenetSession.h" -#include "PresencePackets.h" - - -void Battlenet::Presence::UpdateRequest::Read() -{ - -} - -std::string Battlenet::Presence::UpdateRequest::ToString() const -{ - return "Battlenet::Presence::UpdateRequest"; -} - -void Battlenet::Presence::UpdateRequest::CallHandler(Session* session) const -{ - -} - -void Battlenet::Presence::StatisticSubscribe::Read() -{ - -} - -std::string Battlenet::Presence::StatisticSubscribe::ToString() const -{ - return "Battlenet::Presence::StatisticSubscribe"; -} - -void Battlenet::Presence::StatisticSubscribe::CallHandler(Session* session) const -{ - -} diff --git a/src/server/authserver/Server/BattlenetPackets/PresencePackets.h b/src/server/authserver/Server/BattlenetPackets/PresencePackets.h deleted file mode 100644 index 0a934f2c2ca..00000000000 --- a/src/server/authserver/Server/BattlenetPackets/PresencePackets.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * - * 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 . - */ - -#ifndef PresencePackets_h__ -#define PresencePackets_h__ - -#include "BattlenetPacketsBase.h" - -namespace Battlenet -{ - 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 - }; - - class UpdateRequest final : public ClientPacket - { - public: - UpdateRequest(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) - { - ASSERT(header == PacketHeader(CMSG_UPDATE_REQUEST, PRESENCE) && "Invalid packet header for UpdateRequest"); - } - - void Read() override; - std::string ToString() const override; - void CallHandler(Session* session) const override; - }; - - class StatisticSubscribe final : public ClientPacket - { - public: - StatisticSubscribe(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) - { - ASSERT(header == PacketHeader(CMSG_STATISTIC_SUBSCRIBE, PRESENCE) && "Invalid packet header for StatisticSubscribe"); - } - - void Read() override; - std::string ToString() const override; - void CallHandler(Session* session) const override; - }; - } -} - -#endif // PresencePackets_h__ diff --git a/src/server/authserver/Server/BattlenetPackets/ProfilePackets.h b/src/server/authserver/Server/BattlenetPackets/ProfilePackets.h deleted file mode 100644 index d08fa4883c5..00000000000 --- a/src/server/authserver/Server/BattlenetPackets/ProfilePackets.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * - * 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 . - */ - -#ifndef ProfilePackets_h__ -#define ProfilePackets_h__ - -#include "BattlenetPacketsBase.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/authserver/Server/BattlenetPackets/SupportPackets.h b/src/server/authserver/Server/BattlenetPackets/SupportPackets.h deleted file mode 100644 index 4821ce7caa0..00000000000 --- a/src/server/authserver/Server/BattlenetPackets/SupportPackets.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * - * 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 . - */ - -#ifndef SupportPackets_h__ -#define SupportPackets_h__ - -#include "BattlenetPacketsBase.h" - -namespace Battlenet -{ - namespace Support - { - enum Opcode - { - CMSG_COMPLAINT_REQUEST = 0x0 // Not implemented - }; - } -} - -#endif // SupportPackets_h__ diff --git a/src/server/authserver/Server/BattlenetPackets/WoWRealmPackets.cpp b/src/server/authserver/Server/BattlenetPackets/WoWRealmPackets.cpp deleted file mode 100644 index 1b20a3a7f85..00000000000 --- a/src/server/authserver/Server/BattlenetPackets/WoWRealmPackets.cpp +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * - * 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 . - */ - -#include "WoWRealmPackets.h" -#include "BattlenetSession.h" -#include -#include - -std::string Battlenet::WoWRealm::ListSubscribeRequest::ToString() const -{ - return "Battlenet::WoWRealm::ListSubscribeRequest"; -} - -void Battlenet::WoWRealm::ListSubscribeRequest::CallHandler(Session* session) const -{ - session->HandleListSubscribeRequest(*this); -} - -Battlenet::WoWRealm::ListSubscribeResponse::~ListSubscribeResponse() -{ - for (ServerPacket* realmData : RealmData) - delete realmData; -} - -void Battlenet::WoWRealm::ListSubscribeResponse::Write() -{ - _stream.Write(Response, 1); - if (Response == SUCCESS) - { - _stream.Write(CharacterCounts.size(), 7); - for (CharacterCountEntry const& entry : CharacterCounts) - { - _stream.Write(entry.Realm.Battlegroup, 8); - _stream.Write(entry.Realm.Index, 32); - _stream.Write(entry.Realm.Region, 8); - _stream.Write(entry.CharacterCount, 16); - } - - for (ServerPacket* realmData : RealmData) - { - realmData->Write(); - _stream.WriteBytes(realmData->GetData(), realmData->GetSize()); - } - } - else - _stream.Write(ResponseCode, 8); -} - -std::string Battlenet::WoWRealm::ListSubscribeResponse::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::WoWRealm::ListSubscribeResponse"; - - if (Response == SUCCESS) - { - stream << " Realms " << CharacterCounts.size(); - - for (CharacterCountEntry const& entry : CharacterCounts) - stream << std::endl << "Region " << uint32(entry.Realm.Region) << " Battlegroup " << uint32(entry.Realm.Region) << " Index " << entry.Realm.Index << " Characters " << entry.CharacterCount; - - for (ServerPacket* realmData : RealmData) - stream << std::endl << realmData->ToString(); - } - else - stream << " Failure"; - - return stream.str().c_str(); -} - -void Battlenet::WoWRealm::ListUpdate::Write() -{ - _stream.Write(UpdateState, 1); - if (UpdateState == UPDATE) - { - _stream.Write(Type + -std::numeric_limits::min(), 32); - _stream.WriteFloat(Population); - _stream.Write(Flags, 8); - _stream.Write(Lock, 8); - _stream.Write(Timezone, 32); - _stream.Write(!Version.empty(), 1); - if (!Version.empty()) - { - _stream.WriteString(Version, 5); - _stream.Write(Build, 32); - - boost::asio::ip::address_v4::bytes_type ip = Address.address().to_v4().to_bytes(); - uint16 port = Address.port(); - - EndianConvertReverse(ip); - EndianConvertReverse(port); - - _stream.WriteBytes(ip.data(), 4); - _stream.WriteBytes(&port, 2); - } - - _stream.WriteString(Name, 10); - } - - _stream.Write(Battlegroup, 8); - _stream.Write(Index, 32); - _stream.Write(Region, 8); -} - -std::string Battlenet::WoWRealm::ListUpdate::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::WoWRealm::ListUpdate Timezone " << Timezone << " Population " << Population << " Lock " << uint32(Lock) << " Type " << Type << " Name " << Name - << " Flags " << uint32(Flags) << " Region " << uint32(Region) << " Battlegroup " << uint32(Battlegroup) << " Index " << Index; - - if (!Version.empty()) - stream << " Version " << Version; - - return stream.str().c_str(); -} - -void Battlenet::WoWRealm::JoinRequestV2::Read() -{ - Realm.Battlegroup = _stream.Read(8); - Realm.Index = _stream.Read(32); - Realm.Region = _stream.Read(8); - ClientSeed = _stream.Read(32); -} - -std::string Battlenet::WoWRealm::JoinRequestV2::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::WoWRealm::JoinRequestV2 ClientSeed " << ClientSeed << " Region " << uint32(Realm.Region) << " Battlegroup " << uint32(Realm.Battlegroup) << " Index " << Realm.Index; - return stream.str().c_str(); -} - -void Battlenet::WoWRealm::JoinRequestV2::CallHandler(Session* session) const -{ - session->HandleJoinRequestV2(*this); -} - -void Battlenet::WoWRealm::JoinResponseV2::Write() -{ - _stream.Write(0, 27); - _stream.Write(Response, 1); - if (Response == SUCCESS) - { - _stream.Write(ServerSeed, 32); - _stream.Write(IPv6.size(), 5); - for (tcp::endpoint const& addr : 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); - } - - _stream.Write(IPv4.size(), 5); - for (tcp::endpoint const& addr : 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); - } - } - else - _stream.Write(ResponseCode, 8); -} - -std::string Battlenet::WoWRealm::JoinResponseV2::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::WoWRealm::JoinResponseV2"; - if (Response == SUCCESS) - { - stream << " ServerSeed " << ServerSeed << " IPv4 Addresses " << IPv4.size() << " IPv6 Addresses " << IPv6.size(); - for (tcp::endpoint const& addr : IPv4) - stream << std::endl << "Battlenet::WoWRealm::JoinResponseV2::Address " << boost::lexical_cast(addr); - - for (tcp::endpoint const& addr : IPv6) - stream << std::endl << "Battlenet::WoWRealm::JoinResponseV2::Address " << boost::lexical_cast(addr); - } - else - stream << " Failure"; - - return stream.str().c_str(); -} diff --git a/src/server/authserver/Server/BattlenetPackets/WoWRealmPackets.h b/src/server/authserver/Server/BattlenetPackets/WoWRealmPackets.h deleted file mode 100644 index 1e4228cb26a..00000000000 --- a/src/server/authserver/Server/BattlenetPackets/WoWRealmPackets.h +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * - * 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 . - */ - -#ifndef WoWRealmPackets_h__ -#define WoWRealmPackets_h__ - -#include "BattlenetPacketsBase.h" - -namespace Battlenet -{ - namespace WoWRealm - { - enum Opcode - { - CMSG_LIST_SUBSCRIBE_REQUEST = 0x0, - CMSG_LIST_UNSUBSCRIBE = 0x1, // Not implemented - 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; - void CallHandler(Session* session) const 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) const override; - - uint32 ClientSeed; - RealmId Realm; - }; - - class ListSubscribeResponse final : public ServerPacket - { - public: - enum Result - { - SUCCESS = 0, - FAILURE = 1 - }; - - ListSubscribeResponse() : ServerPacket(PacketHeader(SMSG_LIST_SUBSCRIBE_RESPONSE, WOWREALM)), - Response(SUCCESS), ResponseCode(26) - { - } - - ~ListSubscribeResponse(); - - struct CharacterCountEntry - { - RealmId Realm; - uint32 CharacterCount; - }; - - void Write() override; - std::string ToString() const override; - - Result Response; - uint8 ResponseCode; - std::vector CharacterCounts; - std::vector RealmData; - }; - - class ListUpdate final : public ServerPacket - { - public: - enum State - { - DELETED = 0, - UPDATE = 1 - }; - - ListUpdate() : ServerPacket(PacketHeader(SMSG_LIST_UPDATE, WOWREALM)), UpdateState(UPDATE), - Timezone(0), Population(0.0f), Lock(0), Type(0), Name(""), Version(""), - Flags(0), Region(0), Battlegroup(0), Index(0), Build(0) - { - } - - void Write() override; - std::string ToString() const override; - - int UpdateState; - uint32 Timezone; - float Population; - uint8 Lock; - uint32 Type; - std::string Name; - std::string Version; - tcp::endpoint Address; - uint8 Flags; - uint8 Region; - uint8 Battlegroup; - uint32 Index; - uint32 Build; - }; - - 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 JoinResponseV2 final : public ServerPacket - { - public: - enum Result - { - SUCCESS = 0, - FAILURE = 1 - }; - - JoinResponseV2() : ServerPacket(PacketHeader(SMSG_JOIN_RESPONSE_V2, WOWREALM)), - ServerSeed(0), Response(SUCCESS), ResponseCode(26) - { - } - - void Write() override; - std::string ToString() const override; - - Result Response; - uint8 ResponseCode; - uint32 ServerSeed; - std::vector IPv4; - std::vector IPv6; - }; - } -} - -#endif // WoWRealmPackets_h__ diff --git a/src/server/authserver/Server/BattlenetSession.cpp b/src/server/authserver/Server/BattlenetSession.cpp deleted file mode 100644 index 865e51c1a07..00000000000 --- a/src/server/authserver/Server/BattlenetSession.cpp +++ /dev/null @@ -1,1004 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * - * 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 . - */ - -#include "AuthCodes.h" -#include "BattlenetBitStream.h" -#include "BattlenetPacketFactory.h" -#include "BattlenetSessionManager.h" -#include "Database/DatabaseEnv.h" -#include "HmacHash.h" -#include "Log.h" -#include "RealmList.h" -#include "SHA256.h" -#include - -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, -}; - -Battlenet::Session::Session(tcp::socket&& socket) : Socket(std::move(socket)), _accountId(0), _accountName(), _locale(), - _os(), _build(0), _gameAccountId(0), _gameAccountName(), _accountSecurityLevel(SEC_PLAYER), I(), s(), v(), b(), B(), K(), - _reconnectProof(), _crypt(), _authed(false) -{ - 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()); -} - -Battlenet::Session::~Session() -{ - sBattlenetSessionMgr.RemoveSession(this); - TC_LOG_TRACE("server.battlenet", "Battlenet::Session::OnClose"); -} - -void Battlenet::Session::_SetVSFields(std::string const& pstr) -{ - s.SetRand(uint32(BufferSizes::SRP_6_S) * 8); - - BigNumber p; - p.SetHexStr(pstr.c_str()); - - SHA256Hash sha; - sha.UpdateBigNumbers(&s, &p, NULL); - sha.Finalize(); - BigNumber x; - x.SetBinary(sha.GetDigest(), sha.GetLength()); - v = g.ModExp(x, N); - - PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_VS_FIELDS); - stmt->setString(0, v.AsHexStr()); - stmt->setString(1, s.AsHexStr()); - stmt->setString(2, _accountName); - - LoginDatabase.Execute(stmt); -} - -void Battlenet::Session::LogUnhandledPacket(ClientPacket const& packet) -{ - TC_LOG_DEBUG("server.battlenet", "Battlenet::Session::LogUnhandledPacket %s", packet.ToString().c_str()); -} - -void Battlenet::Session::HandleLogonRequest(Authentication::LogonRequest const& info) -{ - // Verify that this IP is not in the ip_banned table - LoginDatabase.Execute(LoginDatabase.GetPreparedStatement(LOGIN_DEL_EXPIRED_IP_BANS)); - - std::string ip_address = GetRemoteIpAddress().to_string(); - PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_IP_BANNED); - stmt->setString(0, ip_address); - if (PreparedQueryResult result = LoginDatabase.Query(stmt)) - { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(LOGIN_BANNED); - AsyncWrite(complete); - TC_LOG_DEBUG("server.battlenet", "[Battlenet::AuthChallenge] Banned ip '%s:%d' tries to login!", ip_address.c_str(), GetRemotePort()); - return; - } - - if (info.Program != "WoW") - { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(AUTH_INVALID_PROGRAM); - AsyncWrite(complete); - return; - } - - if (!sBattlenetMgr->HasPlatform(info.Platform)) - { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(AUTH_INVALID_OS); - AsyncWrite(complete); - return; - } - - if (!sBattlenetMgr->HasPlatform(info.Locale)) - { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(AUTH_UNSUPPORTED_LANGUAGE); - AsyncWrite(complete); - return; - } - - for (Component const& component : info.Components) - { - if (!sBattlenetMgr->HasComponent(&component)) - { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - if (!sBattlenetMgr->HasProgram(component.Program)) - complete->SetAuthResult(AUTH_INVALID_PROGRAM); - else if (!sBattlenetMgr->HasPlatform(component.Platform)) - complete->SetAuthResult(AUTH_INVALID_OS); - else - { - if (component.Program != "WoW" || AuthHelper::IsBuildSupportingBattlenet(component.Build)) - complete->SetAuthResult(AUTH_REGION_BAD_VERSION); - else - complete->SetAuthResult(AUTH_USE_GRUNT_LOGON); - } - - AsyncWrite(complete); - return; - } - - if (component.Platform == "base") - _build = component.Build; - } - - _accountName = info.Login; - _locale = info.Locale; - _os = info.Platform; - - Utf8ToUpperOnlyLatin(_accountName); - stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_ACCOUNT_INFO); - stmt->setString(0, _accountName); - - PreparedQueryResult result = LoginDatabase.Query(stmt); - if (!result) - { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(AUTH_UNKNOWN_ACCOUNT); - AsyncWrite(complete); - return; - } - - Field* fields = result->Fetch(); - - _accountId = fields[1].GetUInt32(); - - // If the IP is 'locked', check that the player comes indeed from the correct IP address - if (fields[2].GetUInt8() == 1) // if ip is locked - { - TC_LOG_DEBUG("server.battlenet", "[Battlenet::AuthChallenge] Account '%s' is locked to IP - '%s' is logging in from '%s'", _accountName.c_str(), fields[4].GetCString(), ip_address.c_str()); - - if (strcmp(fields[4].GetCString(), ip_address.c_str()) != 0) - { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(AUTH_ACCOUNT_LOCKED); - AsyncWrite(complete); - return; - } - } - else - { - TC_LOG_DEBUG("server.battlenet", "[Battlenet::AuthChallenge] Account '%s' is not locked to ip", _accountName.c_str()); - std::string accountCountry = fields[3].GetString(); - if (accountCountry.empty() || accountCountry == "00") - TC_LOG_DEBUG("server.battlenet", "[Battlenet::AuthChallenge] Account '%s' is not locked to country", _accountName.c_str()); - else if (!accountCountry.empty()) - { - uint32 ip = inet_addr(ip_address.c_str()); - EndianConvertReverse(ip); - - stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_LOGON_COUNTRY); - stmt->setUInt32(0, ip); - if (PreparedQueryResult sessionCountryQuery = LoginDatabase.Query(stmt)) - { - std::string loginCountry = (*sessionCountryQuery)[0].GetString(); - TC_LOG_DEBUG("server.battlenet", "[Battlenet::AuthChallenge] Account '%s' is locked to country: '%s' Player country is '%s'", _accountName.c_str(), accountCountry.c_str(), loginCountry.c_str()); - if (loginCountry != accountCountry) - { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(AUTH_ACCOUNT_LOCKED); - AsyncWrite(complete); - return; - } - } - } - } - - //set expired bans to inactive - LoginDatabase.DirectExecute(LoginDatabase.GetPreparedStatement(LOGIN_DEL_BNET_EXPIRED_BANS)); - - // If the account is banned, reject the logon attempt - stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_ACTIVE_ACCOUNT_BAN); - stmt->setUInt32(0, _accountId); - PreparedQueryResult banresult = LoginDatabase.Query(stmt); - if (banresult) - { - Field* fields = banresult->Fetch(); - if (fields[0].GetUInt32() == fields[1].GetUInt32()) - { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(LOGIN_BANNED); - AsyncWrite(complete); - TC_LOG_DEBUG("server.battlenet", "'%s:%d' [Battlenet::AuthChallenge] Banned account %s tried to login!", ip_address.c_str(), GetRemotePort(), _accountName.c_str()); - return; - } - else - { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(LOGIN_SUSPENDED); - AsyncWrite(complete); - TC_LOG_DEBUG("server.battlenet", "'%s:%d' [Battlenet::AuthChallenge] Temporarily banned account %s tried to login!", ip_address.c_str(), GetRemotePort(), _accountName.c_str()); - return; - } - } - - SHA256Hash sha; - sha.UpdateData(_accountName); - sha.Finalize(); - - I.SetBinary(sha.GetDigest(), sha.GetLength()); - - ModuleInfo* password = sBattlenetMgr->CreateModule(_os, "Password"); - ModuleInfo* thumbprint = sBattlenetMgr->CreateModule(_os, "Thumbprint"); - - std::string pStr = fields[0].GetString(); - - std::string databaseV = fields[5].GetString(); - std::string databaseS = fields[6].GetString(); - - if (databaseV.size() != size_t(BufferSizes::SRP_6_V) * 2 || databaseS.size() != size_t(BufferSizes::SRP_6_S) * 2) - _SetVSFields(pStr); - else - { - s.SetHexStr(databaseS.c_str()); - v.SetHexStr(databaseV.c_str()); - } - - 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* request = new Authentication::ProofRequest(); - request->Modules.push_back(password); - // if has authenticator, send Token module - request->Modules.push_back(thumbprint); - AsyncWrite(request); -} - -void Battlenet::Session::HandleResumeRequest(Authentication::ResumeRequest const& reconnect) -{ - _accountName = reconnect.Login; - _locale = reconnect.Locale; - _os = reconnect.Platform; - auto baseComponent = std::find_if(reconnect.Components.begin(), reconnect.Components.end(), [](Component const& c) { return c.Program == "base"; }); - if (baseComponent != reconnect.Components.end()) - _build = baseComponent->Build; - - Utf8ToUpperOnlyLatin(_accountName); - PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_RECONNECT_INFO); - stmt->setString(0, _accountName); - stmt->setString(1, reconnect.GameAccountName); - PreparedQueryResult result = LoginDatabase.Query(stmt); - if (!result) - { - Authentication::ResumeResponse* resume = new Authentication::ResumeResponse(); - resume->SetAuthResult(AUTH_UNKNOWN_ACCOUNT); - AsyncWrite(resume); - return; - } - - Field* fields = result->Fetch(); - - _accountId = fields[0].GetUInt32(); - K.SetHexStr(fields[1].GetString().c_str()); - _gameAccountId = fields[2].GetUInt32(); - _gameAccountName = reconnect.GameAccountName; - - ModuleInfo* thumbprint = sBattlenetMgr->CreateModule(_os, "Thumbprint"); - ModuleInfo* resume = sBattlenetMgr->CreateModule(_os, "Resume"); - BitStream resumeData; - uint8 state = 0; - _reconnectProof.SetRand(16 * 8); - - 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); - - _modulesWaitingForData.push(MODULE_RESUME); - - Authentication::ProofRequest* request = new Authentication::ProofRequest(); - request->Modules.push_back(thumbprint); - request->Modules.push_back(resume); - AsyncWrite(request); -} - -void Battlenet::Session::HandleProofResponse(Authentication::ProofResponse const& proof) -{ - if (_modulesWaitingForData.size() < proof.Modules.size()) - { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(AUTH_CORRUPTED_MODULE); - AsyncWrite(complete); - return; - } - - ServerPacket* response = nullptr; - for (size_t i = 0; i < proof.Modules.size(); ++i) - { - if (!(this->*(ModuleHandlers[_modulesWaitingForData.front()]))(proof.Modules[i], &response)) - break; - - _modulesWaitingForData.pop(); - } - - if (!response) - { - response = new Authentication::LogonResponse(); - static_cast(response)->SetAuthResult(AUTH_INTERNAL_ERROR); - } - - AsyncWrite(response); - return; -} - -void Battlenet::Session::HandlePing(Connection::Ping const& /*ping*/) -{ - AsyncWrite(new Connection::Pong()); -} - -void Battlenet::Session::HandleEnableEncryption(Connection::EnableEncryption const& /*enableEncryption*/) -{ - _crypt.Init(&K); -} - -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, _accountId); - LoginDatabase.Execute(stmt); -} - -void Battlenet::Session::HandleListSubscribeRequest(WoWRealm::ListSubscribeRequest const& /*listSubscribeRequest*/) -{ - sRealmList->UpdateIfNeed(); - - WoWRealm::ListSubscribeResponse* counts = new WoWRealm::ListSubscribeResponse(); - - PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_CHARACTER_COUNTS); - stmt->setUInt32(0, _gameAccountId); - - if (PreparedQueryResult countResult = LoginDatabase.Query(stmt)) - { - do - { - Field* fields = countResult->Fetch(); - uint32 build = fields[4].GetUInt32(); - counts->CharacterCounts.push_back({ { fields[2].GetUInt8(), fields[3].GetUInt8(), fields[1].GetUInt32(), (_build != build ? build : 0) }, fields[0].GetUInt8() }); - } while (countResult->NextRow()); - } - - for (RealmList::RealmMap::const_iterator i = sRealmList->begin(); i != sRealmList->end(); ++i) - { - Realm const& realm = i->second; - - uint32 flag = realm.flag; - RealmBuildInfo const* buildInfo = AuthHelper::GetBuildInfo(realm.gamebuild); - if (realm.gamebuild != _build) - { - if (!buildInfo) - continue; - - flag |= REALM_FLAG_OFFLINE | REALM_FLAG_SPECIFYBUILD; // tell the client what build the realm is for - } - - if (!buildInfo) - flag &= ~REALM_FLAG_SPECIFYBUILD; - - WoWRealm::ListUpdate* update = new WoWRealm::ListUpdate(); - update->Timezone = realm.timezone; - update->Population = realm.populationLevel; - update->Lock = (realm.allowedSecurityLevel > _accountSecurityLevel) ? 1 : 0; - update->Type = realm.icon; - update->Name = realm.name; - - if (flag & REALM_FLAG_SPECIFYBUILD) - { - std::ostringstream version; - version << buildInfo->MajorVersion << '.' << buildInfo->MinorVersion << '.' << buildInfo->BugfixVersion << '.' << buildInfo->Build; - - update->Version = version.str(); - update->Address = realm.GetAddressForClient(GetRemoteIpAddress()); - update->Build = buildInfo->Build; - } - - update->Flags = flag; - update->Region = realm.Region; - update->Battlegroup = realm.Battlegroup; - update->Index = realm.m_ID; - - counts->RealmData.push_back(update); - } - - counts->RealmData.push_back(new WoWRealm::ListComplete()); - - AsyncWrite(counts); -} - -void Battlenet::Session::HandleJoinRequestV2(WoWRealm::JoinRequestV2 const& join) -{ - WoWRealm::JoinResponseV2* result = new WoWRealm::JoinResponseV2(); - Realm const* realm = sRealmList->GetRealm(join.Realm); - if (!realm || realm->flag & (REALM_FLAG_INVALID | REALM_FLAG_OFFLINE)) - { - result->Response = WoWRealm::JoinResponseV2::FAILURE; - AsyncWrite(result); - return; - } - - result->ServerSeed = uint32(rand32()); - - uint8 sessionKey[40]; - HmacSha1 hmac(K.GetNumBytes(), K.AsByteArray().get()); - hmac.UpdateData((uint8*)"WoW\0", 4); - hmac.UpdateData((uint8*)&join.ClientSeed, 4); - hmac.UpdateData((uint8*)&result->ServerSeed, 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*)&result->ServerSeed, 4); - hmac2.UpdateData((uint8*)&join.ClientSeed, 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(), _gameAccountId); - - result->IPv4.emplace_back(realm->ExternalAddress, realm->port); - if (realm->ExternalAddress != realm->LocalAddress) - result->IPv4.emplace_back(realm->LocalAddress, realm->port); - - AsyncWrite(result); -} - -void Battlenet::Session::ReadHandler() -{ - BitStream stream(std::move(GetReadBuffer())); - _crypt.DecryptRecv(stream.GetBuffer(), stream.GetSize()); - - while (!stream.IsRead()) - { - try - { - PacketHeader header; - header.Opcode = stream.Read(6); - if (stream.Read(1)) - header.Channel = stream.Read(4); - - if (header.Channel != AUTHENTICATION && !_authed) - { - TC_LOG_DEBUG("server.battlenet", "Battlenet::Session::ReadDataHandler Received not allowed packet %s", header.ToString().c_str()); - CloseSocket(); - return; - } - - if (ClientPacket* packet = sBattlenetPacketFactory.Create(header, stream)) - { - TC_LOG_TRACE("server.battlenet", "Battlenet::Session::ReadDataHandler %s", packet->ToString().c_str()); - packet->CallHandler(this); - delete packet; - } - else - { - TC_LOG_DEBUG("server.battlenet", "Battlenet::Session::ReadDataHandler Unhandled opcode %s", header.ToString().c_str()); - break; - } - - stream.AlignToNextByte(); - } - catch (BitStreamPositionException const& e) - { - TC_LOG_ERROR("server.battlenet", "Battlenet::Session::ReadDataHandler Exception: %s", e.what()); - CloseSocket(); - return; - } - } - - GetReadBuffer().Resize(size_t(BufferSizes::Read)); - AsyncRead(); -} - -void Battlenet::Session::Start() -{ - TC_LOG_TRACE("server.battlenet", "Battlenet::Session::Start"); - AsyncRead(); -} - -void Battlenet::Session::AsyncWrite(ServerPacket* packet) -{ - if (!IsOpen()) - { - delete packet; - return; - } - - TC_LOG_TRACE("server.battlenet", "Battlenet::Session::AsyncWrite %s", packet->ToString().c_str()); - - packet->Write(); - - MessageBuffer buffer; - buffer.Write(packet->GetData(), packet->GetSize()); - delete packet; - - std::unique_lock guard(_writeLock); - - _crypt.EncryptSend(buffer.GetReadPointer(), buffer.GetActiveSize()); - - QueuePacket(std::move(buffer), guard); -} - -inline void ReplaceResponse(Battlenet::ServerPacket** oldResponse, Battlenet::ServerPacket* newResponse) -{ - if (*oldResponse) - delete *oldResponse; - - *oldResponse = newResponse; -} - -bool Battlenet::Session::HandlePasswordModule(BitStream* dataStream, ServerPacket** response) -{ - if (dataStream->GetSize() != 1 + 128 + 32 + 128) - { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(AUTH_CORRUPTED_MODULE); - ReplaceResponse(response, complete); - return false; - } - - if (dataStream->Read(8) != 2) // State - { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(AUTH_CORRUPTED_MODULE); - ReplaceResponse(response, complete); - return false; - } - - - 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); - - if (A.isZero()) - { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(AUTH_CORRUPTED_MODULE); - ReplaceResponse(response, complete); - return false; - } - - 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); - - uint8 part1[64]; - uint8 part2[64]; - - for (int i = 0; i < 64; ++i) - { - part1[i] = S_bytes[i * 2]; - part2[i] = S_bytes[i * 2 + 1]; - } - - 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) - { - 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, _accountName); - LoginDatabase.Execute(stmt); - - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(AUTH_UNKNOWN_ACCOUNT); - ReplaceResponse(response, complete); - return false; - } - - uint64 numAccounts = 0; - PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_GAME_ACCOUNTS); - stmt->setUInt32(0, _accountId); - PreparedQueryResult result = LoginDatabase.Query(stmt); - if (result) - numAccounts = result->GetRowCount(); - - if (!numAccounts) - { - Authentication::LogonResponse* noAccounts = new Authentication::LogonResponse(); - noAccounts->SetAuthResult(LOGIN_NO_GAME_ACCOUNT); - ReplaceResponse(response, noAccounts); - return false; - } - - Field* fields = result->Fetch(); - - //set expired game account bans to inactive - LoginDatabase.DirectExecute(LoginDatabase.GetPreparedStatement(LOGIN_UPD_EXPIRED_ACCOUNT_BANS)); - - 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 = sBattlenetMgr->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* request = new Authentication::ProofRequest(); - request->Modules.push_back(password); - if (numAccounts > 1) - { - BitStream accounts; - state = 0; - accounts.WriteBytes(&state, 1); - accounts.Write(numAccounts, 8); - do - { - fields = result->Fetch(); - std::ostringstream name; - std::string originalName = fields[1].GetString(); - if (originalName.find('#') != std::string::npos) - name << "WoW" << uint32(fields[0].GetUInt8()); - else - name << originalName; - - accounts.Write(2, 8); - accounts.WriteString(name.str(), 8); - } while (result->NextRow()); - - ModuleInfo* selectGameAccount = sBattlenetMgr->CreateModule(_os, "SelectGameAccount"); - selectGameAccount->DataSize = accounts.GetSize(); - selectGameAccount->Data = new uint8[selectGameAccount->DataSize]; - memcpy(selectGameAccount->Data, accounts.GetBuffer(), selectGameAccount->DataSize); - request->Modules.push_back(selectGameAccount); - _modulesWaitingForData.push(MODULE_SELECT_GAME_ACCOUNT); - } - else - { - if (fields[4].GetBool()) - { - delete request; - - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - if (fields[2].GetUInt32() == fields[3].GetUInt32()) - { - complete->SetAuthResult(LOGIN_BANNED); - TC_LOG_DEBUG("server.battlenet", "'%s:%d' [Battlenet::AuthChallenge] Banned account %s tried to login!", GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _accountName.c_str()); - } - else - { - complete->SetAuthResult(LOGIN_SUSPENDED); - TC_LOG_DEBUG("server.battlenet", "'%s:%d' [Battlenet::AuthChallenge] Temporarily banned account %s tried to login!", GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _accountName.c_str()); - } - - ReplaceResponse(response, complete); - return false; - } - - _gameAccountId = fields[0].GetUInt32(); - _gameAccountName = fields[1].GetString(); - - request->Modules.push_back(sBattlenetMgr->CreateModule(_os, "RiskFingerprint")); - _modulesWaitingForData.push(MODULE_RISK_FINGERPRINT); - } - - ReplaceResponse(response, request); - return true; -} - -bool Battlenet::Session::HandleSelectGameAccountModule(BitStream* dataStream, ServerPacket** response) -{ - if (dataStream->Read(8) != 1) - { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(AUTH_CORRUPTED_MODULE); - ReplaceResponse(response, complete); - return false; - } - - dataStream->Read(8); - std::string account = dataStream->ReadString(8); - if (account.empty()) - { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(LOGIN_NO_GAME_ACCOUNT); - ReplaceResponse(response, complete); - return false; - } - - PreparedStatement* stmt; - if (account.substr(0, 3) != "WoW") - { - stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_GAME_ACCOUNT); - stmt->setString(0, account); - } - else - { - stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_GAME_ACCOUNT_UNNAMED); - stmt->setUInt8(0, atol(account.substr(3).c_str())); - } - - stmt->setUInt32(1, _accountId); - PreparedQueryResult result = LoginDatabase.Query(stmt); - if (!result) - { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(LOGIN_NO_GAME_ACCOUNT); - ReplaceResponse(response, complete); - return false; - } - - Field* fields = result->Fetch(); - if (fields[4].GetBool()) - { - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - if (fields[2].GetUInt32() == fields[3].GetUInt32()) - { - complete->SetAuthResult(LOGIN_BANNED); - TC_LOG_DEBUG("server.battlenet", "'%s:%d' [Battlenet::SelectGameAccount] Banned account %s tried to login!", GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _accountName.c_str()); - } - else - { - complete->SetAuthResult(LOGIN_SUSPENDED); - TC_LOG_DEBUG("server.battlenet", "'%s:%d' [Battlenet::SelectGameAccount] Temporarily banned account %s tried to login!", GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _accountName.c_str()); - } - - ReplaceResponse(response, complete); - return false; - } - - _gameAccountId = fields[0].GetUInt32(); - _gameAccountName = fields[1].GetString(); - - Authentication::ProofRequest* request = new Authentication::ProofRequest(); - request->Modules.push_back(sBattlenetMgr->CreateModule(_os, "RiskFingerprint")); - ReplaceResponse(response, request); - - _modulesWaitingForData.push(MODULE_RISK_FINGERPRINT); - return true; -} - -bool Battlenet::Session::HandleRiskFingerprintModule(BitStream* dataStream, ServerPacket** response) -{ - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - if (dataStream->Read(8) == 1) - { - complete->AccountId = _accountId; - complete->GameAccountName = _gameAccountName; - complete->GameAccountFlags = GAMEACCOUNT_FLAG_PROPASS_LOCK; - PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_FAILED_LOGINS); - stmt->setUInt32(0, _accountId); - if (PreparedQueryResult failedLoginsResult = LoginDatabase.Query(stmt)) - complete->FailedLogins = (*failedLoginsResult)[0].GetUInt32(); - - SQLTransaction trans = LoginDatabase.BeginTransaction(); - - 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, _accountId); - trans->Append(stmt); - - stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_SESSION_KEY); - stmt->setString(0, K.AsHexStr()); - stmt->setBool(1, true); - stmt->setUInt32(2, _accountId); - trans->Append(stmt); - - LoginDatabase.CommitTransaction(trans); - - _authed = true; - sBattlenetSessionMgr.AddSession(this); - } - else - complete->SetAuthResult(AUTH_BAD_VERSION_HASH); - - ReplaceResponse(response, complete); - return true; -} - -bool Battlenet::Session::HandleResumeModule(BitStream* dataStream, ServerPacket** response) -{ - if (dataStream->Read(8) != 1) - { - Authentication::ResumeResponse* complete = new Authentication::ResumeResponse(); - complete->SetAuthResult(AUTH_CORRUPTED_MODULE); - ReplaceResponse(response, complete); - return false; - } - - static uint8 const ResumeClient = 0; - static uint8 const ResumeServer = 1; - - std::unique_ptr clientChallenge = dataStream->ReadBytes(16); - std::unique_ptr clientProof = dataStream->ReadBytes(32); - std::unique_ptr serverChallenge = _reconnectProof.AsByteArray(16); - std::unique_ptr 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); - - 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, _accountName); - LoginDatabase.Execute(stmt); - - TC_LOG_DEBUG("server.battlenet", "[Battlenet::Resume] Invalid proof!"); - Authentication::ResumeResponse* result = new Authentication::ResumeResponse(); - result->SetAuthResult(AUTH_UNKNOWN_ACCOUNT); - ReplaceResponse(response, result); - return false; - } - - PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_SESSION_KEY); - stmt->setString(0, K.AsHexStr()); - stmt->setBool(1, true); - stmt->setUInt32(2, _accountId); - 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 = sBattlenetMgr->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* result = new Authentication::ResumeResponse(); - result->Modules.push_back(resume); - ReplaceResponse(response, result); - _authed = true; - sBattlenetSessionMgr.AddSession(this); - return true; -} - -bool Battlenet::Session::UnhandledModule(BitStream* /*dataStream*/, ServerPacket** response) -{ - Authentication::LogonResponse* complete = new Authentication::LogonResponse(); - complete->SetAuthResult(AUTH_CORRUPTED_MODULE); - ReplaceResponse(response, complete); - return false; -} diff --git a/src/server/authserver/Server/BattlenetSession.h b/src/server/authserver/Server/BattlenetSession.h deleted file mode 100644 index 2798949de1c..00000000000 --- a/src/server/authserver/Server/BattlenetSession.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * - * 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 . - */ - -#ifndef _BATTLENETSOCKET_H -#define _BATTLENETSOCKET_H - -#include "BattlenetPackets.h" -#include "BattlenetPacketCrypt.h" -#include "Socket.h" -#include "BigNumber.h" -#include -#include - -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 - }; - - enum class BufferSizes : uint32 - { - SRP_6_V = 0x80, - SRP_6_S = 0x20, - Read = 0x4000 - }; - - class Session : public Socket - { - typedef Socket BattlenetSocket; - - public: - explicit Session(tcp::socket&& socket); - ~Session(); - - void LogUnhandledPacket(ClientPacket const& packet); - - // Authentication - void HandleLogonRequest(Authentication::LogonRequest const& logonRequest); - void HandleResumeRequest(Authentication::ResumeRequest const& resumeRequest); - void HandleProofResponse(Authentication::ProofResponse const& proofResponse); - - // Connection - void HandlePing(Connection::Ping const& ping); - void HandleEnableEncryption(Connection::EnableEncryption const& enableEncryption); - void HandleLogoutRequest(Connection::LogoutRequest const& logoutRequest); - - // WoWRealm - void HandleListSubscribeRequest(WoWRealm::ListSubscribeRequest const& listSubscribeRequest); - void HandleJoinRequestV2(WoWRealm::JoinRequestV2 const& joinRequest); - - void Start() override; - - void AsyncWrite(ServerPacket* packet); - - protected: - void ReadHandler() override; - - private: - void _SetVSFields(std::string const& rI); - - typedef bool(Session::*ModuleHandler)(BitStream* dataStream, ServerPacket** response); - static ModuleHandler const ModuleHandlers[MODULE_COUNT]; - - 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); - - uint32 _accountId; - std::string _accountName; - std::string _locale; - std::string _os; - uint32 _build; - uint32 _gameAccountId; - std::string _gameAccountName; - AccountTypes _accountSecurityLevel; - - BigNumber N; - BigNumber g; - BigNumber k; - - BigNumber I; - BigNumber s; - BigNumber v; - - BigNumber b; - BigNumber B; - BigNumber K; // session key - - BigNumber _reconnectProof; - - std::queue _modulesWaitingForData; - - PacketCrypt _crypt; - bool _authed; - }; - -} - -#endif // _BATTLENETSOCKET_H diff --git a/src/server/authserver/Server/BattlenetSessionManager.cpp b/src/server/authserver/Server/BattlenetSessionManager.cpp deleted file mode 100644 index 91ba2b65094..00000000000 --- a/src/server/authserver/Server/BattlenetSessionManager.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * - * 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 . - */ - -#include "BattlenetSessionManager.h" - -bool Battlenet::SessionManager::StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port) -{ - if (!BaseSocketMgr::StartNetwork(service, bindIp, port)) - return false; - - _acceptor->AsyncAcceptManaged(&OnSocketAccept); - return true; -} - -NetworkThread* Battlenet::SessionManager::CreateThreads() const -{ - return new NetworkThread[GetNetworkThreadCount()]; -} - -void Battlenet::SessionManager::OnSocketAccept(tcp::socket&& sock) -{ - sBattlenetSessionMgr.OnSocketOpen(std::forward(sock)); -} diff --git a/src/server/authserver/Server/BattlenetSessionManager.h b/src/server/authserver/Server/BattlenetSessionManager.h deleted file mode 100644 index b5a54438ef1..00000000000 --- a/src/server/authserver/Server/BattlenetSessionManager.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * - * 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 . - */ - -#ifndef BattlenetSessionManager_h__ -#define BattlenetSessionManager_h__ - -#include "BattlenetSession.h" -#include "SocketMgr.h" - -namespace Battlenet -{ -#pragma pack(push, 1) - - struct SessionInfo - { - uint32 AccountId; - uint32 GameAccountIndex; - - bool operator<(SessionInfo const& right) const - { - return memcmp(this, &right, sizeof(SessionInfo)) < 0; - } - }; - -#pragma pack(pop) - - class SessionManager : SocketMgr - { - typedef SocketMgr BaseSocketMgr; - - public: - static SessionManager& Instance() - { - static SessionManager instance; - return instance; - } - - bool StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port) override; - - // noop for now, will be needed later to broadcast realmlist updates for example - void AddSession(Session* /*session*/) { } - - void RemoveSession(Session* /*session*/) { } - - protected: - NetworkThread* CreateThreads() const override; - - private: - static void OnSocketAccept(tcp::socket&& sock); - - std::map _sessions; - }; -} - -#define sBattlenetSessionMgr Battlenet::SessionManager::Instance() - -#endif // BattlenetSessionManager_h__ diff --git a/src/server/bnetserver/Authentication/AuthCodes.cpp b/src/server/bnetserver/Authentication/AuthCodes.cpp new file mode 100644 index 00000000000..908bc30b719 --- /dev/null +++ b/src/server/bnetserver/Authentication/AuthCodes.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * + * 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 . + */ + +#include "AuthCodes.h" +#include + +namespace AuthHelper +{ + static RealmBuildInfo const PostBcAcceptedClientBuilds[] = + { + {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, ' '}, + {0, 0, 0, 0, ' '} // terminator + }; + + RealmBuildInfo const* GetBuildInfo(int build) + { + for (int i = 0; PostBcAcceptedClientBuilds[i].Build; ++i) + if (PostBcAcceptedClientBuilds[i].Build == build) + return &PostBcAcceptedClientBuilds[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 new file mode 100644 index 00000000000..3c3b002551c --- /dev/null +++ b/src/server/bnetserver/Authentication/AuthCodes.h @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * Copyright (C) 2005-2009 MaNGOS + * + * 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 . + */ + +#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_REFERRAL = 0x00000800, + GAMEACCOUNT_FLAG_BLIZZARD = 0x00001000, + GAMEACCOUNT_FLAG_RECURRING_BILLING = 0x00002000, + GAMEACCOUNT_FLAG_NOELECTUP = 0x00004000, + GAMEACCOUNT_FLAG_KR_CERTIFICATE = 0x00008000, + GAMEACCOUNT_FLAG_EXPANSION_COLLECTOR = 0x00010000, + GAMEACCOUNT_FLAG_DISABLE_VOICE = 0x00020000, + GAMEACCOUNT_FLAG_DISABLE_VOICE_SPEAK = 0x00040000, + GAMEACCOUNT_FLAG_REFERRAL_RESURRECT = 0x00080000, + GAMEACCOUNT_FLAG_EU_FORBID_CC = 0x00100000, + GAMEACCOUNT_FLAG_OPENBETA_DELL = 0x00200000, + GAMEACCOUNT_FLAG_PROPASS = 0x00400000, + GAMEACCOUNT_FLAG_PROPASS_LOCK = 0x00800000, + GAMEACCOUNT_FLAG_PENDING_UPGRADE = 0x01000000, + GAMEACCOUNT_FLAG_RETAIL_FROM_TRIAL = 0x02000000, + GAMEACCOUNT_FLAG_EXPANSION2_COLLECTOR = 0x04000000, + GAMEACCOUNT_FLAG_OVERMIND_LINKED = 0x08000000, + GAMEACCOUNT_FLAG_DEMOS = 0x10000000, + GAMEACCOUNT_FLAG_DEATH_KNIGHT_OK = 0x20000000, +}; + +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 + }; +} + +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 new file mode 100644 index 00000000000..de4cf73f71c --- /dev/null +++ b/src/server/bnetserver/Authentication/BattlenetPacketCrypt.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * + * 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 . + */ + +#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/Authentication/BattlenetPacketCrypt.h b/src/server/bnetserver/Authentication/BattlenetPacketCrypt.h new file mode 100644 index 00000000000..a09d3417dfe --- /dev/null +++ b/src/server/bnetserver/Authentication/BattlenetPacketCrypt.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * + * 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 . + */ + +#ifndef BattlenetPacketCrypt_h__ +#define BattlenetPacketCrypt_h__ + +#include "PacketCrypt.h" + +class BigNumber; + +namespace Battlenet +{ + class PacketCrypt : public ::PacketCrypt + { + public: + PacketCrypt(); + + void Init(BigNumber* K) override; + }; +} +#endif // BattlenetPacketCrypt_h__ + diff --git a/src/server/bnetserver/CMakeLists.txt b/src/server/bnetserver/CMakeLists.txt new file mode 100644 index 00000000000..3fa4abf034a --- /dev/null +++ b/src/server/bnetserver/CMakeLists.txt @@ -0,0 +1,115 @@ +# Copyright (C) 2008-2014 TrinityCore +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +########### authserver ############### + +file(GLOB_RECURSE sources_authentication Authentication/*.cpp Authentication/*.h) +file(GLOB_RECURSE sources_realms Realms/*.cpp Realms/*.h) +file(GLOB_RECURSE sources_server Server/*.cpp Server/*.h) +file(GLOB_RECURSE sources_packets Packets/*.cpp Packets/*.h) +file(GLOB sources_localdir *.cpp *.h) + +if (USE_COREPCH) + set(bnetserver_PCH_HDR PrecompiledHeaders/bnetPCH.h) + set(bnetserver_PCH_SRC PrecompiledHeaders/bnetPCH.cpp) +endif() + +set(bnetserver_SRCS + ${bnetserver_SRCS} + ${sources_authentication} + ${sources_realms} + ${sources_server} + ${sources_packets} + ${sources_localdir} +) + +if( WIN32 ) + set(bnetserver_SRCS + ${bnetserver_SRCS} + ${sources_windows_Debugging} + ) + if ( MSVC ) + set(bnetserver_SRCS + ${bnetserver_SRCS} + bnetserver.rc + ) + endif () +endif() + +include_directories( + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/src/server/shared + ${CMAKE_SOURCE_DIR}/src/server/shared/Configuration + ${CMAKE_SOURCE_DIR}/src/server/shared/Database + ${CMAKE_SOURCE_DIR}/src/server/shared/Debugging + ${CMAKE_SOURCE_DIR}/src/server/shared/Packets + ${CMAKE_SOURCE_DIR}/src/server/shared/Cryptography + ${CMAKE_SOURCE_DIR}/src/server/shared/Cryptography/Authentication + ${CMAKE_SOURCE_DIR}/src/server/shared/Logging + ${CMAKE_SOURCE_DIR}/src/server/shared/Networking + ${CMAKE_SOURCE_DIR}/src/server/shared/Threading + ${CMAKE_SOURCE_DIR}/src/server/shared/Utilities + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/Authentication + ${CMAKE_CURRENT_SOURCE_DIR}/Realms + ${CMAKE_CURRENT_SOURCE_DIR}/Server + ${CMAKE_CURRENT_SOURCE_DIR}/Packets + ${MYSQL_INCLUDE_DIR} + ${OPENSSL_INCLUDE_DIR} + ${VALGRIND_INCLUDE_DIR} +) + +add_executable(bnetserver + ${bnetserver_SRCS} + ${bnetserver_PCH_SRC} +) + +add_dependencies(bnetserver revision.h) + +if( NOT WIN32 ) + set_target_properties(bnetserver PROPERTIES + COMPILE_DEFINITIONS _TRINITY_BNET_CONFIG="${CONF_DIR}/bnetserver.conf" + ) +endif() + +target_link_libraries(bnetserver + shared + ${MYSQL_LIBRARY} + ${OPENSSL_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} + ${Boost_LIBRARIES} +) + +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)/ + ) + 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/ + ) + endif() +endif() + +if( UNIX ) + install(TARGETS bnetserver DESTINATION bin) + install(FILES bnetserver.conf.dist DESTINATION ${CONF_DIR}) +elseif( WIN32 ) + install(TARGETS bnetserver DESTINATION "${CMAKE_INSTALL_PREFIX}") + install(FILES bnetserver.conf.dist DESTINATION "${CMAKE_INSTALL_PREFIX}") +endif() + +# Generate precompiled header +if (USE_COREPCH) + add_cxx_pch(bnetserver ${bnetserver_PCH_HDR} ${bnetserver_PCH_SRC}) +endif() diff --git a/src/server/bnetserver/Main.cpp b/src/server/bnetserver/Main.cpp new file mode 100644 index 00000000000..cb9bab97841 --- /dev/null +++ b/src/server/bnetserver/Main.cpp @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * Copyright (C) 2005-2009 MaNGOS + * + * 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 . + */ + +/** +* @file main.cpp +* @brief Authentication Server main program +* +* This file contains the main program for the +* authentication server +*/ + +#include "ComponentManager.h" +#include "ModuleManager.h" +#include "SessionManager.h" +#include "Common.h" +#include "Config.h" +#include "DatabaseEnv.h" +#include "Log.h" +#include "ProcessPriority.h" +#include "RealmList.h" +#include "SystemConfig.h" +#include "Util.h" +#include +#include +#include +#include +#include +#include + +using boost::asio::ip::tcp; +using namespace boost::program_options; + +#ifndef _TRINITY_BNET_CONFIG +# define _TRINITY_BNET_CONFIG "authserver.conf" +#endif + +bool StartDB(); +void StopDB(); +void SignalHandler(const boost::system::error_code& error, int signalNumber); +void KeepDatabaseAliveHandler(const boost::system::error_code& error); +variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile); + +boost::asio::io_service _ioService; +boost::asio::deadline_timer _dbPingTimer(_ioService); +uint32 _dbPingInterval; +LoginDatabaseWorkerPool LoginDatabase; + +int main(int argc, char** argv) +{ + std::string configFile = _TRINITY_BNET_CONFIG; + auto vm = GetConsoleArguments(argc, argv, configFile); + // exit if help is enabled + if (vm.count("help")) + return 0; + + std::string configError; + if (!sConfigMgr->LoadInitial(configFile, configError)) + { + printf("Error in config file: %s\n", configError.c_str()); + return 1; + } + + TC_LOG_INFO("server.bnetserver", "%s (bnetserver)", _FULLVERSION); + TC_LOG_INFO("server.bnetserver", " to stop.\n"); + TC_LOG_INFO("server.bnetserver", "Using configuration file %s.", configFile.c_str()); + TC_LOG_INFO("server.bnetserver", "Using SSL version: %s (library: %s)", OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION)); + TC_LOG_INFO("server.bnetserver", "Using Boost version: %i.%i.%i", BOOST_VERSION / 100000, BOOST_VERSION / 100 % 1000, BOOST_VERSION % 100); + + // authserver PID file creation + std::string pidFile = sConfigMgr->GetStringDefault("PidFile", ""); + if (!pidFile.empty()) + { + if (uint32 pid = CreatePIDFile(pidFile)) + TC_LOG_INFO("server.bnetserver", "Daemon PID: %u\n", pid); + else + { + TC_LOG_ERROR("server.bnetserver", "Cannot create PID file %s.\n", pidFile.c_str()); + return 1; + } + } + + // Initialize the database connection + if (!StartDB()) + return 1; + + // Get the list of realms for the server + sRealmList->Initialize(_ioService, sConfigMgr->GetIntDefault("RealmsStateUpdateDelay", 20)); + + if (sRealmList->size() == 0) + { + TC_LOG_ERROR("server.bnetserver", "No valid realms specified."); + StopDB(); + return 1; + } + + // Start the listening port (acceptor) for auth connections + int32 bnport = sConfigMgr->GetIntDefault("BattlenetPort", 1119); + if (bnport < 0 || bnport > 0xFFFF) + { + TC_LOG_ERROR("server.bnetserver", "Specified battle.net port (%d) out of allowed range (1-65535)", bnport); + StopDB(); + return 1; + } + + std::string bindIp = sConfigMgr->GetStringDefault("BindIP", "0.0.0.0"); + + sSessionMgr.StartNetwork(_ioService, bindIp, bnport); + + // Set signal handlers + boost::asio::signal_set signals(_ioService, SIGINT, SIGTERM); +#if PLATFORM == PLATFORM_WINDOWS + signals.add(SIGBREAK); +#endif + signals.async_wait(SignalHandler); + + // Set process priority according to configuration settings + SetProcessPriority("server.bnetserver"); + + // Enabled a timed callback for handling the database keep alive ping + _dbPingInterval = sConfigMgr->GetIntDefault("MaxPingTime", 30); + _dbPingTimer.expires_from_now(boost::posix_time::minutes(_dbPingInterval)); + _dbPingTimer.async_wait(KeepDatabaseAliveHandler); + + sComponentMgr->Load(); + sModuleMgr->Load(); + + // Start the io service worker loop + _ioService.run(); + + // Close the Database Pool and library + StopDB(); + + TC_LOG_INFO("server.bnetserver", "Halting process..."); + return 0; +} + + +/// Initialize connection to the database +bool StartDB() +{ + MySQL::Library_Init(); + + std::string dbstring = sConfigMgr->GetStringDefault("LoginDatabaseInfo", ""); + if (dbstring.empty()) + { + TC_LOG_ERROR("server.authserver", "Database not specified"); + return false; + } + + int32 worker_threads = sConfigMgr->GetIntDefault("LoginDatabase.WorkerThreads", 1); + if (worker_threads < 1 || worker_threads > 32) + { + TC_LOG_ERROR("server.authserver", "Improper value specified for LoginDatabase.WorkerThreads, defaulting to 1."); + worker_threads = 1; + } + + int32 synch_threads = sConfigMgr->GetIntDefault("LoginDatabase.SynchThreads", 1); + if (synch_threads < 1 || synch_threads > 32) + { + TC_LOG_ERROR("server.authserver", "Improper value specified for LoginDatabase.SynchThreads, defaulting to 1."); + synch_threads = 1; + } + + // NOTE: While authserver is singlethreaded you should keep synch_threads == 1. Increasing it is just silly since only 1 will be used ever. + if (!LoginDatabase.Open(dbstring, uint8(worker_threads), uint8(synch_threads))) + { + TC_LOG_ERROR("server.authserver", "Cannot connect to database"); + return false; + } + + TC_LOG_INFO("server.authserver", "Started auth database connection pool."); + sLog->SetRealmId(0); // Enables DB appenders when realm is set. + return true; +} + +/// Close the connection to the database +void StopDB() +{ + LoginDatabase.Close(); + MySQL::Library_End(); +} + +void SignalHandler(const boost::system::error_code& error, int /*signalNumber*/) +{ + if (!error) + _ioService.stop(); +} + +void KeepDatabaseAliveHandler(const boost::system::error_code& error) +{ + if (!error) + { + TC_LOG_INFO("server.authserver", "Ping MySQL to keep connection alive"); + LoginDatabase.KeepAlive(); + + _dbPingTimer.expires_from_now(boost::posix_time::minutes(_dbPingInterval)); + _dbPingTimer.async_wait(KeepDatabaseAliveHandler); + } +} + +variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile) +{ + options_description all("Allowed options"); + all.add_options() + ("help,h", "print usage message") + ("config,c", value(&configFile)->default_value(_TRINITY_BNET_CONFIG), "use as configuration file") + ; + variables_map variablesMap; + try + { + store(command_line_parser(argc, argv).options(all).allow_unregistered().run(), variablesMap); + notify(variablesMap); + } + catch (std::exception& e) { + std::cerr << e.what() << "\n"; + } + + if (variablesMap.count("help")) { + std::cout << all << "\n"; + } + + return variablesMap; +} diff --git a/src/server/bnetserver/Packets/AchievementPackets.h b/src/server/bnetserver/Packets/AchievementPackets.h new file mode 100644 index 00000000000..99a0f19d0a2 --- /dev/null +++ b/src/server/bnetserver/Packets/AchievementPackets.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * + * 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 . + */ + +#ifndef AchievementPackets_h__ +#define AchievementPackets_h__ + +#include "PacketsBase.h" + +namespace Battlenet +{ + namespace Achievement + { + enum Opcode + { + CMSG_LISTEN_REQUEST = 0x0, // Not implemented + CMSG_CRITERIA_FLUSH_REQUEST = 0x3, // Not implemented + CMSG_CHANGE_TROPHY_CASE_REQUEST = 0x5, // Not implemented + + 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 + }; + } +} + +#endif // AchievementPackets_h__ + diff --git a/src/server/bnetserver/Packets/AuthenticationPackets.cpp b/src/server/bnetserver/Packets/AuthenticationPackets.cpp new file mode 100644 index 00000000000..ae2db016972 --- /dev/null +++ b/src/server/bnetserver/Packets/AuthenticationPackets.cpp @@ -0,0 +1,319 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * + * 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 . + */ + +#include "AuthenticationPackets.h" +#include "Util.h" + +void Battlenet::Authentication::LogonRequest::Read() +{ + Program = _stream.ReadFourCC(); + Platform = _stream.ReadFourCC(); + Locale = _stream.ReadFourCC(); + + Components.resize(_stream.Read(6)); + for (size_t i = 0; i < Components.size(); ++i) + { + Component& component = Components[i]; + component.Program = _stream.ReadFourCC(); + component.Platform = _stream.ReadFourCC(); + component.Build = _stream.Read(32); + } + + if (_stream.Read(1)) + Login = _stream.ReadString(9, 3); +} + +std::string Battlenet::Authentication::LogonRequest::ToString() const +{ + std::ostringstream stream; + stream << "Battlenet::Authentication::LogonRequest Program: " << Program << ", Platform: " << Platform << ", Locale: " << Locale; + for (Component const& component : Components) + stream << std::endl << "Battlenet::Component Program: " << component.Program << ", Platform: " << component.Platform << ", Build: " << component.Build; + + if (!Login.empty()) + stream << std::endl << "Battlenet::Authentication::LogonRequest Login: " << Login; + + return stream.str(); +} + +void Battlenet::Authentication::LogonRequest::CallHandler(Session* session) const +{ + session->HandleLogonRequest(*this); +} + +void Battlenet::Authentication::ResumeRequest::Read() +{ + Program = _stream.ReadFourCC(); + Platform = _stream.ReadFourCC(); + Locale = _stream.ReadFourCC(); + + Components.resize(_stream.Read(6)); + for (size_t i = 0; i < Components.size(); ++i) + { + Component& component = Components[i]; + component.Program = _stream.ReadFourCC(); + component.Platform = _stream.ReadFourCC(); + component.Build = _stream.Read(32); + } + + Login = _stream.ReadString(9, 3); + Region = _stream.Read(8); + GameAccountName = _stream.ReadString(5, 1); +} + +std::string Battlenet::Authentication::ResumeRequest::ToString() const +{ + std::ostringstream stream; + stream << "Battlenet::Authentication::ResumeRequest Program: " << Program << ", Platform: " << Platform << ", Locale: " << Locale; + for (Component const& component : Components) + stream << std::endl << "Battlenet::Component Program: " << component.Program << ", Platform: " << component.Platform << ", Build: " << component.Build; + + stream << std::endl << "Login: " << Login; + stream << std::endl << "Region: " << uint32(Region); + stream << std::endl << "GameAccountName: " << GameAccountName; + + return stream.str(); +} + +void Battlenet::Authentication::ResumeRequest::CallHandler(Session* session) const +{ + session->HandleResumeRequest(*this); +} + +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->Type.c_str(), 4); + _stream.WriteFourCC(info->Region); + _stream.WriteBytes(info->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 modules " << Modules.size(); + for (ModuleInfo const* module : Modules) + stream << std::endl << "Battlenet::ModuleInfo Locale " << module->Region.c_str() << ", ModuleId " << ByteArrayToHexStr(module->ModuleId, 32) << ", DataSize " << module->DataSize << ", Data " << ByteArrayToHexStr(module->Data, module->DataSize); + + return stream.str(); +} + +Battlenet::Authentication::ProofResponse::~ProofResponse() +{ + for (size_t i = 0; i < Modules.size(); ++i) + delete Modules[i]; +} + +void Battlenet::Authentication::ProofResponse::Read() +{ + Modules.resize(_stream.Read(3)); + for (size_t i = 0; i < Modules.size(); ++i) + { + BitStream*& dataStream = Modules[i]; + dataStream = new BitStream(_stream.Read(10)); + memcpy(dataStream->GetBuffer(), _stream.ReadBytes(dataStream->GetSize()).get(), dataStream->GetSize()); + } +} + +std::string Battlenet::Authentication::ProofResponse::ToString() const +{ + std::ostringstream stream; + stream << "Battlenet::Authentication::ProofResponse Modules " << Modules.size(); + for (BitStream* module : Modules) + { + std::string hexStr = ByteArrayToHexStr(module->GetBuffer(), module->GetSize()); + stream << std::endl << "Battlenet::Authentication::ProofResponse::ModuleData Size: " << module->GetSize() << ", Data: " << hexStr; + } + + return stream.str(); +} + +void Battlenet::Authentication::ProofResponse::CallHandler(Session* session) const +{ + session->HandleProofResponse(*this); +} + +Battlenet::Authentication::LogonResponse::~LogonResponse() +{ + for (ModuleInfo* m : Modules) + delete m; +} + +void Battlenet::Authentication::LogonResponse::Write() +{ + _stream.Write(Result.ResultValue != ResponseFailure::UPDATE, 1); + if (Result.ResultValue == ResponseFailure::UPDATE) + { + _stream.Write(Modules.size(), 3); + for (size_t i = 0; i < Modules.size(); ++i) + { + ModuleInfo* info = Modules[i]; + _stream.WriteBytes(info->Type.c_str(), 4); + _stream.WriteFourCC(info->Region); + _stream.WriteBytes(info->ModuleId, 32); + _stream.Write(info->DataSize, 10); + _stream.WriteBytes(info->Data, info->DataSize); + } + + _stream.Write(PingTimeout + std::numeric_limits::min(), 32); + _stream.Write(1, 1); // RegulatorRules != NULL (not a pointer for us, always write) + // if written == 1 + { + _stream.Write(RegulatorRules.Type == Regulator::LEAKY_BUCKET, 1); + if (RegulatorRules.Type == Regulator::LEAKY_BUCKET) + { + _stream.Write(RegulatorRules.Threshold, 32); + _stream.Write(RegulatorRules.Rate, 32); + } + } + + _stream.WriteString(FirstName, 8); // First name + _stream.WriteString(LastName, 8); // Last name - not set for WoW + + _stream.Write(AccountId, 32); + _stream.Write(Region, 8); + _stream.Write(Flags, 64); + + _stream.Write(GameAccountRegion, 8); + _stream.WriteString(GameAccountName, 5, -1); + _stream.Write(GameAccountFlags, 64); + + _stream.Write(FailedLogins, 32); + } + else + { + _stream.Write(!Modules.empty(), 1); + if (!Modules.empty()) + { + ModuleInfo* info = Modules[0]; + _stream.WriteBytes(info->Type.c_str(), 4); + _stream.WriteFourCC(info->Region); + _stream.WriteBytes(info->ModuleId, 32); + } + + _stream.Write(Result.ResultValue, 2); + if (Result.ResultValue == ResponseFailure::FAILURE) + { + _stream.Write(Result.Error, 16); + _stream.Write(Result.Wait + std::numeric_limits::min(), 32); + } + } +} + +std::string Battlenet::Authentication::LogonResponse::ToString() const +{ + std::ostringstream stream; + stream << "Battlenet::Authentication::LogonResponse AuthResult " << Result.Error << " PingTimeout " << PingTimeout + << " RegulatorRules.Threshold " << RegulatorRules.Threshold << " RegulatorRules.Rate " << RegulatorRules.Rate + << " FirstName " << FirstName << " LastName " << LastName << " AccountId " << AccountId << " Region " << uint32(Region) << " GameAccountName " << GameAccountName + << " GameAccountFlags " << GameAccountFlags << " FailedLogins " << FailedLogins << " Modules " << Modules.size(); + + for (ModuleInfo const* module : Modules) + stream << std::endl << "Battlenet::ModuleInfo Locale " << module->Region.c_str() << ", ModuleId " << ByteArrayToHexStr(module->ModuleId, 32) << ", DataSize " << module->DataSize << ", Data " << ByteArrayToHexStr(module->Data, module->DataSize); + + return stream.str(); +} + +void Battlenet::Authentication::LogonResponse::SetAuthResult(AuthResult result) +{ + Result.ResultValue = result != AUTH_OK ? ResponseFailure::FAILURE : ResponseFailure::UPDATE; + Result.Error = result; +} + +Battlenet::Authentication::ResumeResponse::~ResumeResponse() +{ + for (ModuleInfo* m : Modules) + delete m; +} + +void Battlenet::Authentication::ResumeResponse::Write() +{ + _stream.Write(Result.ResultValue != ResponseFailure::UPDATE, 1); + if (Result.ResultValue == ResponseFailure::UPDATE) + { + _stream.Write(Modules.size(), 3); + for (size_t i = 0; i < Modules.size(); ++i) + { + ModuleInfo* info = Modules[i]; + _stream.WriteBytes(info->Type.c_str(), 4); + _stream.WriteFourCC(info->Region); + _stream.WriteBytes(info->ModuleId, 32); + _stream.Write(info->DataSize, 10); + _stream.WriteBytes(info->Data, info->DataSize); + } + + _stream.Write(PingTimeout + std::numeric_limits::min(), 32); + _stream.Write(1, 1); // RegulatorRules != NULL (not a pointer for us, always write) + // if written == 1 + { + _stream.Write(RegulatorRules.Type == Regulator::LEAKY_BUCKET, 1); + if (RegulatorRules.Type == Regulator::LEAKY_BUCKET) + { + _stream.Write(RegulatorRules.Threshold, 32); + _stream.Write(RegulatorRules.Rate, 32); + } + } + } + else + { + _stream.Write(!Modules.empty(), 1); + if (!Modules.empty()) + { + ModuleInfo* info = Modules[0]; + _stream.WriteBytes(info->Type.c_str(), 4); + _stream.WriteFourCC(info->Region); + _stream.WriteBytes(info->ModuleId, 32); + } + + _stream.Write(Result.ResultValue, 2); + if (Result.ResultValue == ResponseFailure::FAILURE) + { + _stream.Write(Result.Error, 16); + _stream.Write(Result.Wait + std::numeric_limits::min(), 32); + } + } +} + +std::string Battlenet::Authentication::ResumeResponse::ToString() const +{ + std::ostringstream stream; + stream << "Battlenet::Authentication::ResumeResponse AuthResult " << Result.Error << " PingTimeout " << PingTimeout + << " RegulatorRules.Threshold " << RegulatorRules.Threshold << " RegulatorRules.Rate " << RegulatorRules.Rate + << " Modules " << Modules.size(); + + for (ModuleInfo const* module : Modules) + stream << std::endl << "Battlenet::ModuleInfo Locale " << module->Region.c_str() << ", ModuleId " << ByteArrayToHexStr(module->ModuleId, 32) << ", DataSize " << module->DataSize << ", Data " << ByteArrayToHexStr(module->Data, module->DataSize); + + return stream.str(); +} + +void Battlenet::Authentication::ResumeResponse::SetAuthResult(AuthResult result) +{ + Result.ResultValue = result != AUTH_OK ? ResponseFailure::FAILURE : ResponseFailure::UPDATE; + Result.Error = result; +} diff --git a/src/server/bnetserver/Packets/AuthenticationPackets.h b/src/server/bnetserver/Packets/AuthenticationPackets.h new file mode 100644 index 00000000000..8003e13db24 --- /dev/null +++ b/src/server/bnetserver/Packets/AuthenticationPackets.h @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * + * 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 . + */ + +#ifndef AuthenticationPackets_h__ +#define AuthenticationPackets_h__ + +#include "PacketsBase.h" + +namespace Battlenet +{ + namespace Authentication + { + enum Opcode + { + CMSG_LOGON_REQUEST = 0x0, + CMSG_RESUME_REQUEST = 0x1, + CMSG_PROOF_RESPONSE = 0x2, + + SMSG_LOGON_RESPONSE = 0x0, + SMSG_RESUME_RESPONSE = 0x1, + SMSG_PROOF_REQUEST = 0x2, + SMSG_PATCH = 0x3, // Not implemented + SMSG_AUTHORIZED_LICENSES = 0x4 // Not implemented + }; + + class LogonRequest final : public ClientPacket + { + public: + LogonRequest(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) + { + ASSERT(header == PacketHeader(CMSG_LOGON_REQUEST, AUTHENTICATION) && "Invalid packet header for LogonRequest"); + } + + void Read() override; + std::string ToString() const override; + void CallHandler(Session* session) const override; + + std::string Program; + std::string Platform; + std::string Locale; + std::vector Components; + std::string Login; + }; + + 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) const override; + + std::string Program; + std::string Platform; + std::string Locale; + std::vector Components; + std::string Login; + uint8 Region; + 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) const override; + + std::vector Modules; + }; + + class ProofRequest final : public ServerPacket + { + public: + ProofRequest() : ServerPacket(PacketHeader(SMSG_PROOF_REQUEST, AUTHENTICATION)) { } + ~ProofRequest(); + + void Write() override; + std::string ToString() const override; + + std::vector Modules; + }; + + class ResponseFailure + { + public: + enum Result + { + UPDATE = 0, + FAILURE = 1, + VERSION_CHECK_DISCONNECT = 2 + }; + + ResponseFailure() : ResultValue(UPDATE), Error(AUTH_OK), Wait(0) { } + + Result ResultValue; + AuthResult Error; + int32 Wait; + }; + + class Regulator + { + public: + enum Info + { + NONE = 0, + LEAKY_BUCKET = 1 + }; + + Regulator() : Type(LEAKY_BUCKET), Threshold(25000000), Rate(1000) { } + + Info Type; + uint32 Threshold; + uint32 Rate; + }; + + class LogonResponse final : public ServerPacket + { + public: + LogonResponse() : ServerPacket(PacketHeader(SMSG_LOGON_RESPONSE, AUTHENTICATION)), + PingTimeout(120000), FirstName(""), LastName(""), AccountId(0), Region(2), Flags(0), + GameAccountRegion(2), GameAccountName(""), FailedLogins(0) + { + } + + ~LogonResponse(); + + void Write() override; + std::string ToString() const override; + + std::vector Modules; + void SetAuthResult(AuthResult result); + ResponseFailure Result; + + int32 PingTimeout; + Regulator RegulatorRules; + std::string FirstName; + std::string LastName; + uint32 AccountId; + uint8 Region; + uint64 Flags; + uint8 GameAccountRegion; + std::string GameAccountName; + uint64 GameAccountFlags; + + uint32 FailedLogins; + }; + + class ResumeResponse final : public ServerPacket + { + public: + ResumeResponse() : ServerPacket(PacketHeader(SMSG_RESUME_RESPONSE, AUTHENTICATION)), PingTimeout(120000) + { + } + + ~ResumeResponse(); + + void Write() override; + std::string ToString() const override; + + std::vector Modules; + void SetAuthResult(AuthResult result); + ResponseFailure Result; + + int32 PingTimeout; + Regulator RegulatorRules; + }; + } +} + +#endif // AuthenticationPackets_h__ diff --git a/src/server/bnetserver/Packets/BitStream.cpp b/src/server/bnetserver/Packets/BitStream.cpp new file mode 100644 index 00000000000..5f002f6b1d9 --- /dev/null +++ b/src/server/bnetserver/Packets/BitStream.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * + * 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 . + */ + +#include "BitStream.h" + +template<> +bool Battlenet::BitStream::Read(uint32 /*bitCount*/) +{ + return Read(1) != 0; +} + +template<> +void Battlenet::BitStream::Write(bool value, uint32 /*bitCount*/) +{ + Write(value ? 1 : 0, 1); +} diff --git a/src/server/bnetserver/Packets/BitStream.h b/src/server/bnetserver/Packets/BitStream.h new file mode 100644 index 00000000000..952ec5a39e2 --- /dev/null +++ b/src/server/bnetserver/Packets/BitStream.h @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * + * 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 . + */ + +#ifndef BitStream_h__ +#define BitStream_h__ + +#include "Common.h" +#include "ByteConverter.h" +#include "MessageBuffer.h" +#include +#include +#include +#include + +namespace Battlenet +{ + 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(buffer.GetActiveSize() * 8), _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(bitCount) + baseLength; + AlignToNextByte(); + std::string str(reinterpret_cast(&_buffer[_readPos >> 3]), len); + _readPos += len * 8; + return str; + } + + std::unique_ptr ReadBytes(uint32 count) + { + AlignToNextByte(); + if (_readPos + count * 8 > _writePos) + throw BitStreamPositionException(true, count * 8, _readPos, _writePos); + + std::unique_ptr buf(new uint8[count]); + memcpy(buf.get(), &_buffer[_readPos >> 3], count); + _readPos += count * 8; + return buf; + } + + float ReadFloat() + { + uint32 val = Read(32); + return *reinterpret_cast(&val); + } + + std::string ReadFourCC() + { + uint32 fcc = Read(32); + EndianConvertReverse(fcc); + size_t len = 4; + while (!(fcc & 0xFF)) + { + fcc >>= 8; + --len; + } + + return std::string(reinterpret_cast(&fcc), len); + } + + template + T Read(uint32 bitCount) + { + static_assert(std::is_integral::value || std::is_enum::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(ret); + } + + void WriteString(std::string const& str, uint32 bitCount, int32 baseLength = 0) + { + Write(str.length() + baseLength, bitCount); + WriteBytes(str.c_str(), str.length()); + } + + template + 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) + { + uint32 intVal = *reinterpret_cast(&value); + Write(intVal, 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 + void Write(T value, uint32 bitCount) + { + static_assert(std::is_integral::value || std::is_enum::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; + } + } + + void SetReadPos(uint32 bits) + { + if (bits > _writePos) + throw BitStreamPositionException(true, bits, 0, _writePos); + + _readPos = bits; + } + + bool IsRead() const { return _readPos >= _writePos; } + + uint8* GetBuffer() { return _buffer.data(); } + uint8 const* GetBuffer() const { return _buffer.data(); } + + size_t GetSize() const { return ((_writePos + 7) & ~7) / 8; } + + private: + uint32 _writePos; + uint32 _readPos; + std::vector _buffer; + }; + + template<> + bool BitStream::Read(uint32 bitCount); + + template<> + void BitStream::Write(bool value, uint32 bitCount); +} + +#endif // BitStream_h__ diff --git a/src/server/bnetserver/Packets/CachePackets.h b/src/server/bnetserver/Packets/CachePackets.h new file mode 100644 index 00000000000..2e473df4e72 --- /dev/null +++ b/src/server/bnetserver/Packets/CachePackets.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * + * 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 . + */ + +#ifndef CachePackets_h__ +#define CachePackets_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 + SMSG_GET_STREAM_ITEMS_REQUEST = 0x9, // Not implemented + + 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 // Not implemented + }; + } +} + +#endif // CachePackets_h__ diff --git a/src/server/bnetserver/Packets/ChatPackets.h b/src/server/bnetserver/Packets/ChatPackets.h new file mode 100644 index 00000000000..fc4b638754c --- /dev/null +++ b/src/server/bnetserver/Packets/ChatPackets.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * + * 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 . + */ + +#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, // 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, // Not implemented + SMSG_CONFIG_CHANGED = 0x1D // Not implemented + }; + } +} + +#endif // ChatPackets_h__ diff --git a/src/server/bnetserver/Packets/ConnectionPackets.cpp b/src/server/bnetserver/Packets/ConnectionPackets.cpp new file mode 100644 index 00000000000..0449ecbb756 --- /dev/null +++ b/src/server/bnetserver/Packets/ConnectionPackets.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * + * 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 . + */ + +#include "Session.h" +#include "ConnectionPackets.h" + +std::string Battlenet::Connection::Ping::ToString() const +{ + return "Battlenet::Connection::Ping"; +} + +void Battlenet::Connection::Ping::CallHandler(Session* session) const +{ + session->HandlePing(*this); +} + +std::string Battlenet::Connection::EnableEncryption::ToString() const +{ + return "Battlenet::Connection::EnableEncryption"; +} + +void Battlenet::Connection::EnableEncryption::CallHandler(Session* session) const +{ + session->HandleEnableEncryption(*this); +} + +std::string Battlenet::Connection::LogoutRequest::ToString() const +{ + return "Battlenet::Connection::LogoutRequest"; +} + +void Battlenet::Connection::LogoutRequest::CallHandler(Session* session) const +{ + session->HandleLogoutRequest(*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 new file mode 100644 index 00000000000..f3fa4852d07 --- /dev/null +++ b/src/server/bnetserver/Packets/ConnectionPackets.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * + * 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 . + */ + +#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 implemented + CMSG_CONNECTION_CLOSING = 0x9, // Not implemented + + 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) const 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) const override; + }; + + 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) const override; + }; + + 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 new file mode 100644 index 00000000000..784d6980777 --- /dev/null +++ b/src/server/bnetserver/Packets/FriendsPackets.cpp @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * + * 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 . + */ + +#include "Session.h" +#include "FriendsPackets.h" + +void Battlenet::Friends::SocialnetworkCheckConnected::Read() +{ + SocialNetworkId = _stream.Read(32); +} + +std::string Battlenet::Friends::SocialnetworkCheckConnected::ToString() const +{ + return "Battlenet::Friends::SocialnetworkCheckConnected SocialNetworkId " + std::to_string(SocialNetworkId); +} + +void Battlenet::Friends::SocialnetworkCheckConnected::CallHandler(Session* session) const +{ + SocialNetworkCheckConnectedResult* result = new SocialNetworkCheckConnectedResult(SocialNetworkId); + session->AsyncWrite(result); +} + +void Battlenet::Friends::SocialnetworkConnect::Read() +{ + int32 unk1 = _stream.Read(32); + uint32 size1 = _stream.Read(9); + auto data1 = _stream.ReadBytes(size1); + uint32 size2 = _stream.Read(7); + auto data2 = _stream.ReadBytes(size2); +} + +std::string Battlenet::Friends::SocialnetworkConnect::ToString() const +{ + return "Battlenet::Friends::SocialnetworkConnect"; +} + +void Battlenet::Friends::SocialnetworkConnect::CallHandler(Session* session) const +{ + session->LogUnhandledPacket(*this); +} + +std::string Battlenet::Friends::SocialNetworkConnectResult::ToString() const +{ + return "Battlenet::Friends::SocialNetworkConnectResult"; +} + +void Battlenet::Friends::SocialNetworkConnectResult::Write() +{ +} + +std::string Battlenet::Friends::SocialNetworkCheckConnectedResult::ToString() const +{ + return "Battlenet::Friends::SocialNetworkCheckConnectedResult"; +} + +void Battlenet::Friends::SocialNetworkCheckConnectedResult::Write() +{ + _stream.Write(0, 23); // Ignored + volatile uint16 res = 0; + _stream.Write(res, 16); // Unknown + _stream.Write(SocialNetworkId, 32); +} + +void Battlenet::Friends::GetFriendsOfFriend::Read() +{ + uint8 unk = _stream.Read(2); + uint32 unk1 = _stream.Read(32); +} + +std::string Battlenet::Friends::GetFriendsOfFriend::ToString() const +{ + return "Battlenet::Friends::GetFriendsOfFriend"; +} + +void Battlenet::Friends::GetFriendsOfFriend::CallHandler(Session* session) const +{ + session->LogUnhandledPacket(*this); +} + +void Battlenet::Friends::RealIdFriendInvite::Read() +{ + _stream.Read(32); + uint8 type = _stream.Read(3); + + switch (type) + { + case 0: + { + _stream.Read(32); // Presence Id? + break; + } + case 1: // GameAccount? + { + _stream.Read(8); + _stream.Read(32); + _stream.Read(32); + uint8 size = _stream.Read(7); // Only if *(a1 + 16) <= 0x64 + _stream.ReadBytes(size); + break; + } + case 2: + Email = _stream.ReadString(9, 3); + break; + case 3: + { + _stream.Read(32); + break; + } + case 4: + { + _stream.Read(64); + _stream.Read(32); + break; + } + } + + _stream.Read(1); + + if (_stream.Read(1)) + Message = _stream.ReadString(9); + + _stream.Read(32); +} + +std::string Battlenet::Friends::RealIdFriendInvite::ToString() const +{ + return "Battlenet::Friends::RealIdFriendInvite Mail: " + Email + " Message: " + Message; +} + +void Battlenet::Friends::RealIdFriendInvite::CallHandler(Session* session) const +{ + FriendInviteResult* result = new FriendInviteResult(); + session->AsyncWrite(result); +} + +std::string Battlenet::Friends::FriendInviteResult::ToString() const +{ + return "Battlenet::Friends::RealIdFriendInviteResult"; +} + +void Battlenet::Friends::FriendInviteResult::Write() +{ + bool hasNames = false; + _stream.Write(hasNames, 1); + if (hasNames) + { + _stream.WriteString("Testing1", 8); + _stream.WriteString("Testing2", 8); + } + _stream.Write(5, 32); + + _stream.Write(0, 0xC); // Ignored + + _stream.Write(1, 16); + + bool moreInfo = true; + _stream.Write(moreInfo, 1); + if (moreInfo) + { + _stream.Write(0, 8); + _stream.Write(4, 32); + _stream.Write(3, 32); + _stream.WriteString("Testing3", 7, 2); + } +} diff --git a/src/server/bnetserver/Packets/FriendsPackets.h b/src/server/bnetserver/Packets/FriendsPackets.h new file mode 100644 index 00000000000..a0ef6f4a63f --- /dev/null +++ b/src/server/bnetserver/Packets/FriendsPackets.h @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * + * 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 . + */ + +#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, // Not implemented + CMSG_SOCIAL_NETWORK_CONNECT = 0x0F, // Not implemented + CMSG_SOCIAL_NETWORK_DISCONNECT = 0x11, // Not implemented + CMSG_SOCIAL_NETWORK_CHECK_CONNECTED = 0x13, + CMSG_REALID_FRIEND_INVITE = 0x16, // 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, // Not implemented + SMSG_BLOCK_ADD_FAILURE = 0x09, // Not implemented + SMSG_FRIENDS_OF_FRIEND = 0x0C, // Not implemented + SMSG_SOCIAL_NETWORK_FRIENDS = 0x0E, // Not implemented + SMSG_SOCIAL_NETWORK_CONNECT_RESULT = 0x10, // Not implemented + SMSG_SOCIAL_NETWORK_DISCONNECT_RESULT = 0x12, // Not implemented + SMSG_SOCIAL_NETWORK_CHECK_CONNECTED_RESULT = 0x14, + SMSG_MAX_FRIENDS_NOTIFY = 0x15, // Not implemented + SMSG_FRIENDS_LIST_NOTIFY_3 = 0x18 // Not implemented + }; + + class SocialnetworkConnect final : public ClientPacket + { + public: + SocialnetworkConnect(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) + { + ASSERT(header == PacketHeader(CMSG_SOCIAL_NETWORK_CONNECT, FRIENDS) && "Invalid packet header for SocialnetworkConnect"); + } + + void Read() override; + std::string ToString() const override; + void CallHandler(Session* session) const override; + }; + + class SocialNetworkConnectResult final : public ServerPacket + { + public: + SocialNetworkConnectResult() : ServerPacket(PacketHeader(SMSG_SOCIAL_NETWORK_CONNECT_RESULT, FRIENDS)) + { + } + + void Write() override; + std::string ToString() const override; + }; + + class SocialnetworkCheckConnected final : public ClientPacket + { + public: + SocialnetworkCheckConnected(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) + { + ASSERT(header == PacketHeader(CMSG_SOCIAL_NETWORK_CHECK_CONNECTED, FRIENDS) && "Invalid packet header for SocialNetworkCheckConnected"); + } + + void Read() override; + std::string ToString() const override; + void CallHandler(Session* session) const override; + + uint32 SocialNetworkId; + }; + + class SocialNetworkCheckConnectedResult final : public ServerPacket + { + public: + SocialNetworkCheckConnectedResult(uint32 socialNetworkId) : ServerPacket(PacketHeader(SMSG_SOCIAL_NETWORK_CHECK_CONNECTED_RESULT, FRIENDS)), SocialNetworkId(socialNetworkId) + { + } + + void Write() override; + std::string ToString() const override; + + uint32 SocialNetworkId; + }; + + class GetFriendsOfFriend final : public ClientPacket + { + public: + GetFriendsOfFriend(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) + { + ASSERT(header == PacketHeader(CMSG_GET_FRIENDS_OF_FRIEND, FRIENDS) && "Invalid packet header for GetFriendsOfFriend"); + } + + void Read() override; + std::string ToString() const override; + void CallHandler(Session* session) const override; + }; + + class FriendsOfFriend final : public ServerPacket + { + public: + FriendsOfFriend() : ServerPacket(PacketHeader(SMSG_FRIENDS_OF_FRIEND, FRIENDS)) + { + } + + void Write() override; + std::string ToString() const override; + }; + + class RealIdFriendInvite final : public ClientPacket + { + public: + RealIdFriendInvite(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) + { + ASSERT(header == PacketHeader(CMSG_REALID_FRIEND_INVITE, FRIENDS) && "Invalid packet header for RealIdFriendInvite"); + } + + void Read() override; + std::string ToString() const override; + void CallHandler(Session* session) const override; + + std::string Email; + std::string Message; + }; + + class FriendInviteResult final : public ServerPacket + { + public: + FriendInviteResult() : ServerPacket(PacketHeader(SMSG_FRIEND_INVITE_RESULT, FRIENDS)) + { + } + + void Write() override; + std::string ToString() const override; + }; + } +} + +#endif // FriendsPackets_h__ diff --git a/src/server/bnetserver/Packets/PacketFactory.h b/src/server/bnetserver/Packets/PacketFactory.h new file mode 100644 index 00000000000..4ae6338cfd7 --- /dev/null +++ b/src/server/bnetserver/Packets/PacketFactory.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * + * 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 . + */ + +#ifndef PacketFactory_h__ +#define PacketFactory_h__ + +#include "Packets.h" +#include + +namespace Battlenet +{ + class PacketFactory + { + typedef ClientPacket*(*PacketCreateFn)(PacketHeader const& header, BitStream& stream); + + public: + ClientPacket* Create(PacketHeader const& header, BitStream& stream) + { + auto creator = _creators.find(header); + if (creator == _creators.end()) + return nullptr; + + ClientPacket* packet = creator->second(header, stream); + packet->Read(); + return packet; + } + + static PacketFactory& Instance() + { + static PacketFactory instance; + return instance; + } + + private: + PacketFactory() + { + _creators[PacketHeader(Authentication::CMSG_LOGON_REQUEST, AUTHENTICATION)] = &New; + _creators[PacketHeader(Authentication::CMSG_RESUME_REQUEST, AUTHENTICATION)] = &New; + _creators[PacketHeader(Authentication::CMSG_PROOF_RESPONSE, AUTHENTICATION)] = &New; + + _creators[PacketHeader(Connection::CMSG_PING, CONNECTION)] = &New; + _creators[PacketHeader(Connection::CMSG_ENABLE_ENCRYPTION, CONNECTION)] = &New; + _creators[PacketHeader(Connection::CMSG_LOGOUT_REQUEST, CONNECTION)] = &New; + + _creators[PacketHeader(WoWRealm::CMSG_LIST_SUBSCRIBE_REQUEST, WOWREALM)] = &New; + _creators[PacketHeader(WoWRealm::CMSG_JOIN_REQUEST_V2, WOWREALM)] = &New; + + _creators[PacketHeader(Friends::CMSG_SOCIAL_NETWORK_CHECK_CONNECTED, FRIENDS)] = &New; + _creators[PacketHeader(Friends::CMSG_SOCIAL_NETWORK_CONNECT, FRIENDS)] = &New; + _creators[PacketHeader(Friends::CMSG_GET_FRIENDS_OF_FRIEND, FRIENDS)] = &New; + _creators[PacketHeader(Friends::CMSG_REALID_FRIEND_INVITE, FRIENDS)] = &New; + + _creators[PacketHeader(Presence::CMSG_UPDATE_REQUEST, PRESENCE)] = &New; + _creators[PacketHeader(Presence::CMSG_STATISTIC_SUBSCRIBE, PRESENCE)] = &New; + } + + template + static ClientPacket* New(PacketHeader const& header, BitStream& stream) + { + return new PacketType(header, stream); + } + + std::map _creators; + }; +} + +#define sPacketFactory Battlenet::PacketFactory::Instance() + +#endif // PacketFactory_h__ diff --git a/src/server/bnetserver/Packets/Packets.h b/src/server/bnetserver/Packets/Packets.h new file mode 100644 index 00000000000..f62ba6f65cd --- /dev/null +++ b/src/server/bnetserver/Packets/Packets.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * + * 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 . + */ + +#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.cpp b/src/server/bnetserver/Packets/PacketsBase.cpp new file mode 100644 index 00000000000..6471337060c --- /dev/null +++ b/src/server/bnetserver/Packets/PacketsBase.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * + * 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 . + */ + +#include "Packets.h" +#include + +std::string Battlenet::PacketHeader::ToString() const +{ + std::ostringstream stream; + stream << "Battlenet::PacketHeader opcode: " << Opcode << ", channel: " << Channel; + return stream.str(); +} + +Battlenet::ServerPacket::ServerPacket(PacketHeader const& header) : Packet(header, *new BitStream()) +{ + _stream.Write(header.Opcode, 6); + _stream.Write(1, 1); + _stream.Write(header.Channel, 4); +} + +Battlenet::ServerPacket::~ServerPacket() +{ + delete &_stream; +} diff --git a/src/server/bnetserver/Packets/PacketsBase.h b/src/server/bnetserver/Packets/PacketsBase.h new file mode 100644 index 00000000000..839a10548e9 --- /dev/null +++ b/src/server/bnetserver/Packets/PacketsBase.h @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * + * 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 . + */ + +#ifndef PacketsBase_h__ +#define PacketsBase_h__ + +#include "AuthCodes.h" +#include "BitStream.h" +#include "Define.h" +#include "Errors.h" +#include +#include + +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 + { + PacketHeader(uint32 opcode, uint32 channel) : Opcode(opcode), Channel(channel) { } + PacketHeader() : Opcode(0), Channel(AUTHENTICATION) { } + + uint32 Opcode; + int32 Channel; + + bool operator<(PacketHeader const& right) const + { + if (Opcode < right.Opcode) + return true; + if (Opcode > right.Opcode) + return false; + + return Channel < right.Channel; + } + + bool operator==(PacketHeader const& right) const + { + return Opcode == right.Opcode && Channel == right.Channel; + } + + std::string ToString() const; + }; + + class Packet + { + 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; + + virtual std::string ToString() const = 0; + + protected: + PacketHeader _header; + BitStream& _stream; + + private: + Packet(Packet const& right); + Packet& operator=(Packet const& right); + }; + + class ClientPacket : public Packet + { + public: + ClientPacket(PacketHeader const& header, BitStream& stream) : Packet(header, stream) { } + + void Write() override final { ASSERT(!"Write not implemented for this packet."); } + virtual void CallHandler(Session* session) const = 0; + }; + + 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/PresencePackets.cpp b/src/server/bnetserver/Packets/PresencePackets.cpp new file mode 100644 index 00000000000..da49f41af76 --- /dev/null +++ b/src/server/bnetserver/Packets/PresencePackets.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * + * 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 . + */ + +#include "Session.h" +#include "PresencePackets.h" + +void Battlenet::Presence::UpdateRequest::Read() +{ + +} + +std::string Battlenet::Presence::UpdateRequest::ToString() const +{ + return "Battlenet::Presence::UpdateRequest"; +} + +void Battlenet::Presence::UpdateRequest::CallHandler(Session* session) const +{ + session->LogUnhandledPacket(*this); +} + +void Battlenet::Presence::StatisticSubscribe::Read() +{ +} + +std::string Battlenet::Presence::StatisticSubscribe::ToString() const +{ + return "Battlenet::Presence::StatisticSubscribe"; +} + +void Battlenet::Presence::StatisticSubscribe::CallHandler(Session* session) const +{ + session->LogUnhandledPacket(*this); +} diff --git a/src/server/bnetserver/Packets/PresencePackets.h b/src/server/bnetserver/Packets/PresencePackets.h new file mode 100644 index 00000000000..c934228a3cb --- /dev/null +++ b/src/server/bnetserver/Packets/PresencePackets.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * + * 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 . + */ + +#ifndef PresencePackets_h__ +#define PresencePackets_h__ + +#include "PacketsBase.h" + +namespace Battlenet +{ + 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 + }; + + class UpdateRequest final : public ClientPacket + { + public: + UpdateRequest(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) + { + ASSERT(header == PacketHeader(CMSG_UPDATE_REQUEST, PRESENCE) && "Invalid packet header for UpdateRequest"); + } + + void Read() override; + std::string ToString() const override; + void CallHandler(Session* session) const override; + }; + + class StatisticSubscribe final : public ClientPacket + { + public: + StatisticSubscribe(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) + { + ASSERT(header == PacketHeader(CMSG_STATISTIC_SUBSCRIBE, PRESENCE) && "Invalid packet header for StatisticSubscribe"); + } + + void Read() override; + std::string ToString() const override; + void CallHandler(Session* session) const override; + }; + } +} + +#endif // PresencePackets_h__ diff --git a/src/server/bnetserver/Packets/ProfilePackets.h b/src/server/bnetserver/Packets/ProfilePackets.h new file mode 100644 index 00000000000..bf413471f62 --- /dev/null +++ b/src/server/bnetserver/Packets/ProfilePackets.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * + * 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 . + */ + +#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/SupportPackets.h b/src/server/bnetserver/Packets/SupportPackets.h new file mode 100644 index 00000000000..43f51bd564e --- /dev/null +++ b/src/server/bnetserver/Packets/SupportPackets.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * + * 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 . + */ + +#ifndef SupportPackets_h__ +#define SupportPackets_h__ + +#include "PacketsBase.h" + +namespace Battlenet +{ + namespace Support + { + enum Opcode + { + CMSG_COMPLAINT_REQUEST = 0x0 // Not implemented + }; + } +} + +#endif // SupportPackets_h__ diff --git a/src/server/bnetserver/Packets/WoWRealmPackets.cpp b/src/server/bnetserver/Packets/WoWRealmPackets.cpp new file mode 100644 index 00000000000..6845fc914b1 --- /dev/null +++ b/src/server/bnetserver/Packets/WoWRealmPackets.cpp @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * + * 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 . + */ + +#include "WoWRealmPackets.h" +#include "Session.h" +#include +#include + +std::string Battlenet::WoWRealm::ListSubscribeRequest::ToString() const +{ + return "Battlenet::WoWRealm::ListSubscribeRequest"; +} + +void Battlenet::WoWRealm::ListSubscribeRequest::CallHandler(Session* session) const +{ + session->HandleListSubscribeRequest(*this); +} + +Battlenet::WoWRealm::ListSubscribeResponse::~ListSubscribeResponse() +{ + for (ServerPacket* realmData : RealmData) + delete realmData; +} + +void Battlenet::WoWRealm::ListSubscribeResponse::Write() +{ + _stream.Write(Response, 1); + if (Response == SUCCESS) + { + _stream.Write(CharacterCounts.size(), 7); + for (CharacterCountEntry const& entry : CharacterCounts) + { + _stream.Write(entry.Realm.Battlegroup, 8); + _stream.Write(entry.Realm.Index, 32); + _stream.Write(entry.Realm.Region, 8); + _stream.Write(entry.CharacterCount, 16); + } + + for (ServerPacket* realmData : RealmData) + { + realmData->Write(); + _stream.WriteBytes(realmData->GetData(), realmData->GetSize()); + } + } + else + _stream.Write(ResponseCode, 8); +} + +std::string Battlenet::WoWRealm::ListSubscribeResponse::ToString() const +{ + std::ostringstream stream; + stream << "Battlenet::WoWRealm::ListSubscribeResponse"; + + if (Response == SUCCESS) + { + stream << " Realms " << CharacterCounts.size(); + + for (CharacterCountEntry const& entry : CharacterCounts) + stream << std::endl << "Region " << uint32(entry.Realm.Region) << " Battlegroup " << uint32(entry.Realm.Region) << " Index " << entry.Realm.Index << " Characters " << entry.CharacterCount; + + for (ServerPacket* realmData : RealmData) + stream << std::endl << realmData->ToString(); + } + else + stream << " Failure"; + + return stream.str().c_str(); +} + +void Battlenet::WoWRealm::ListUpdate::Write() +{ + _stream.Write(UpdateState, 1); + if (UpdateState == UPDATE) + { + _stream.Write(Type + -std::numeric_limits::min(), 32); + _stream.WriteFloat(Population); + _stream.Write(Flags, 8); + _stream.Write(Lock, 8); + _stream.Write(Timezone, 32); + _stream.Write(!Version.empty(), 1); + if (!Version.empty()) + { + _stream.WriteString(Version, 5); + _stream.Write(Build, 32); + + boost::asio::ip::address_v4::bytes_type ip = Address.address().to_v4().to_bytes(); + uint16 port = Address.port(); + + EndianConvertReverse(ip); + EndianConvertReverse(port); + + _stream.WriteBytes(ip.data(), 4); + _stream.WriteBytes(&port, 2); + } + + _stream.WriteString(Name, 10); + } + + _stream.Write(Battlegroup, 8); + _stream.Write(Index, 32); + _stream.Write(Region, 8); +} + +std::string Battlenet::WoWRealm::ListUpdate::ToString() const +{ + std::ostringstream stream; + stream << "Battlenet::WoWRealm::ListUpdate Timezone " << Timezone << " Population " << Population << " Lock " << uint32(Lock) << " Type " << Type << " Name " << Name + << " Flags " << uint32(Flags) << " Region " << uint32(Region) << " Battlegroup " << uint32(Battlegroup) << " Index " << Index; + + if (!Version.empty()) + stream << " Version " << Version; + + return stream.str().c_str(); +} + +void Battlenet::WoWRealm::JoinRequestV2::Read() +{ + Realm.Battlegroup = _stream.Read(8); + Realm.Index = _stream.Read(32); + Realm.Region = _stream.Read(8); + ClientSeed = _stream.Read(32); +} + +std::string Battlenet::WoWRealm::JoinRequestV2::ToString() const +{ + std::ostringstream stream; + stream << "Battlenet::WoWRealm::JoinRequestV2 ClientSeed " << ClientSeed << " Region " << uint32(Realm.Region) << " Battlegroup " << uint32(Realm.Battlegroup) << " Index " << Realm.Index; + return stream.str().c_str(); +} + +void Battlenet::WoWRealm::JoinRequestV2::CallHandler(Session* session) const +{ + session->HandleJoinRequestV2(*this); +} + +void Battlenet::WoWRealm::JoinResponseV2::Write() +{ + _stream.Write(0, 27); + _stream.Write(Response, 1); + if (Response == SUCCESS) + { + _stream.Write(ServerSeed, 32); + _stream.Write(IPv6.size(), 5); + for (tcp::endpoint const& addr : 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); + } + + _stream.Write(IPv4.size(), 5); + for (tcp::endpoint const& addr : 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); + } + } + else + _stream.Write(ResponseCode, 8); +} + +std::string Battlenet::WoWRealm::JoinResponseV2::ToString() const +{ + std::ostringstream stream; + stream << "Battlenet::WoWRealm::JoinResponseV2"; + if (Response == SUCCESS) + { + stream << " ServerSeed " << ServerSeed << " IPv4 Addresses " << IPv4.size() << " IPv6 Addresses " << IPv6.size(); + for (tcp::endpoint const& addr : IPv4) + stream << std::endl << "Battlenet::WoWRealm::JoinResponseV2::Address " << boost::lexical_cast(addr); + + for (tcp::endpoint const& addr : IPv6) + stream << std::endl << "Battlenet::WoWRealm::JoinResponseV2::Address " << boost::lexical_cast(addr); + } + else + stream << " Failure"; + + return stream.str().c_str(); +} diff --git a/src/server/bnetserver/Packets/WoWRealmPackets.h b/src/server/bnetserver/Packets/WoWRealmPackets.h new file mode 100644 index 00000000000..4ce5ea68835 --- /dev/null +++ b/src/server/bnetserver/Packets/WoWRealmPackets.h @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * + * 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 . + */ + +#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, // Not implemented + 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; + void CallHandler(Session* session) const 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) const override; + + uint32 ClientSeed; + RealmId Realm; + }; + + class ListSubscribeResponse final : public ServerPacket + { + public: + enum Result + { + SUCCESS = 0, + FAILURE = 1 + }; + + ListSubscribeResponse() : ServerPacket(PacketHeader(SMSG_LIST_SUBSCRIBE_RESPONSE, WOWREALM)), + Response(SUCCESS), ResponseCode(26) + { + } + + ~ListSubscribeResponse(); + + struct CharacterCountEntry + { + RealmId Realm; + uint32 CharacterCount; + }; + + void Write() override; + std::string ToString() const override; + + Result Response; + uint8 ResponseCode; + std::vector CharacterCounts; + std::vector RealmData; + }; + + class ListUpdate final : public ServerPacket + { + public: + enum State + { + DELETED = 0, + UPDATE = 1 + }; + + ListUpdate() : ServerPacket(PacketHeader(SMSG_LIST_UPDATE, WOWREALM)), UpdateState(UPDATE), + Timezone(0), Population(0.0f), Lock(0), Type(0), Name(""), Version(""), + Flags(0), Region(0), Battlegroup(0), Index(0), Build(0) + { + } + + void Write() override; + std::string ToString() const override; + + int UpdateState; + uint32 Timezone; + float Population; + uint8 Lock; + uint32 Type; + std::string Name; + std::string Version; + tcp::endpoint Address; + uint8 Flags; + uint8 Region; + uint8 Battlegroup; + uint32 Index; + uint32 Build; + }; + + 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 JoinResponseV2 final : public ServerPacket + { + public: + enum Result + { + SUCCESS = 0, + FAILURE = 1 + }; + + JoinResponseV2() : ServerPacket(PacketHeader(SMSG_JOIN_RESPONSE_V2, WOWREALM)), + ServerSeed(0), Response(SUCCESS), ResponseCode(26) + { + } + + void Write() override; + std::string ToString() const override; + + Result Response; + uint8 ResponseCode; + uint32 ServerSeed; + std::vector IPv4; + std::vector IPv6; + }; + } +} + +#endif // WoWRealmPackets_h__ diff --git a/src/server/bnetserver/PrecompiledHeaders/bnetPCH.cpp b/src/server/bnetserver/PrecompiledHeaders/bnetPCH.cpp new file mode 100644 index 00000000000..60b1d41a1a8 --- /dev/null +++ b/src/server/bnetserver/PrecompiledHeaders/bnetPCH.cpp @@ -0,0 +1 @@ +#include "bnetPCH.h" diff --git a/src/server/bnetserver/PrecompiledHeaders/bnetPCH.h b/src/server/bnetserver/PrecompiledHeaders/bnetPCH.h new file mode 100644 index 00000000000..82cd5393489 --- /dev/null +++ b/src/server/bnetserver/PrecompiledHeaders/bnetPCH.h @@ -0,0 +1,10 @@ +#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" diff --git a/src/server/bnetserver/Realms/RealmList.cpp b/src/server/bnetserver/Realms/RealmList.cpp new file mode 100644 index 00000000000..60d40f98edf --- /dev/null +++ b/src/server/bnetserver/Realms/RealmList.cpp @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * Copyright (C) 2005-2009 MaNGOS + * + * 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 . + */ + +#include +#include "Common.h" +#include "RealmList.h" +#include "Database/DatabaseEnv.h" +#include "Util.h" + +ip::tcp::endpoint Realm::GetAddressForClient(ip::address const& clientAddr) const +{ + ip::address realmIp; + + // Attempt to send best address for client + if (clientAddr.is_loopback()) + { + // Try guessing if realm is also connected locally + if (LocalAddress.is_loopback() || ExternalAddress.is_loopback()) + realmIp = clientAddr; + else + { + // Assume that user connecting from the machine that authserver is located on + // has all realms available in his local network + realmIp = LocalAddress; + } + } + else + { + if (clientAddr.is_v4() && + (clientAddr.to_v4().to_ulong() & LocalSubnetMask.to_v4().to_ulong()) == + (LocalAddress.to_v4().to_ulong() & LocalSubnetMask.to_v4().to_ulong())) + { + realmIp = LocalAddress; + } + else + realmIp = ExternalAddress; + } + + ip::tcp::endpoint endpoint(realmIp, port); + + // Return external IP + return endpoint; +} + +RealmList::RealmList() : m_UpdateInterval(0), m_NextUpdateTime(time(NULL)), _resolver(nullptr) +{ +} + +RealmList::~RealmList() +{ + delete _resolver; +} + +// Load the realm list from the database +void RealmList::Initialize(boost::asio::io_service& ioService, uint32 updateInterval) +{ + _resolver = new boost::asio::ip::tcp::resolver(ioService); + m_UpdateInterval = updateInterval; + + // Get the content of the realmlist table in the database + UpdateRealms(true); +} + +void RealmList::UpdateRealm(uint32 id, const std::string& name, ip::address const& address, ip::address const& localAddr, + ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population, uint32 build, uint8 region, uint8 battlegroup) +{ + // Create new if not exist or update existed + Realm& realm = m_realms[name]; + + realm.m_ID = id; + realm.name = name; + realm.icon = icon; + realm.flag = flag; + realm.timezone = timezone; + realm.allowedSecurityLevel = allowedSecurityLevel; + realm.populationLevel = population; + + // Append port to IP address. + + realm.ExternalAddress = address; + realm.LocalAddress = localAddr; + realm.LocalSubnetMask = localSubmask; + realm.port = port; + realm.gamebuild = build; + realm.Region = region; + realm.Battlegroup = battlegroup; +} + +void RealmList::UpdateIfNeed() +{ + // maybe disabled or updated recently + if (!m_UpdateInterval || m_NextUpdateTime > time(NULL)) + return; + + m_NextUpdateTime = time(NULL) + m_UpdateInterval; + + // Clears Realm list + m_realms.clear(); + + // Get the content of the realmlist table in the database + UpdateRealms(); +} + +void RealmList::UpdateRealms(bool init) +{ + TC_LOG_INFO("server.authserver", "Updating Realm List..."); + + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_REALMLIST); + PreparedQueryResult result = LoginDatabase.Query(stmt); + + // Circle through results and add them to the realm map + if (result) + { + do + { + try + { + boost::asio::ip::tcp::resolver::iterator end; + + Field* fields = result->Fetch(); + uint32 realmId = fields[0].GetUInt32(); + std::string name = fields[1].GetString(); + boost::asio::ip::tcp::resolver::query externalAddressQuery(ip::tcp::v4(), fields[2].GetString(), ""); + + boost::system::error_code ec; + boost::asio::ip::tcp::resolver::iterator endPoint = _resolver->resolve(externalAddressQuery, ec); + if (endPoint == end || ec) + { + TC_LOG_ERROR("server.authserver", "Could not resolve address %s", fields[2].GetString().c_str()); + return; + } + + ip::address externalAddress = (*endPoint).endpoint().address(); + + boost::asio::ip::tcp::resolver::query localAddressQuery(ip::tcp::v4(), fields[3].GetString(), ""); + endPoint = _resolver->resolve(localAddressQuery, ec); + if (endPoint == end || ec) + { + TC_LOG_ERROR("server.authserver", "Could not resolve address %s", fields[3].GetString().c_str()); + return; + } + + ip::address localAddress = (*endPoint).endpoint().address(); + + boost::asio::ip::tcp::resolver::query localSubmaskQuery(ip::tcp::v4(), fields[4].GetString(), ""); + endPoint = _resolver->resolve(localSubmaskQuery, ec); + if (endPoint == end || ec) + { + TC_LOG_ERROR("server.authserver", "Could not resolve address %s", fields[4].GetString().c_str()); + return; + } + + ip::address localSubmask = (*endPoint).endpoint().address(); + + uint16 port = fields[5].GetUInt16(); + uint8 icon = fields[6].GetUInt8(); + RealmFlags flag = RealmFlags(fields[7].GetUInt8()); + uint8 timezone = fields[8].GetUInt8(); + uint8 allowedSecurityLevel = fields[9].GetUInt8(); + float pop = fields[10].GetFloat(); + uint32 build = fields[11].GetUInt32(); + uint8 region = fields[12].GetUInt8(); + uint8 battlegroup = fields[13].GetUInt8(); + + UpdateRealm(realmId, name, externalAddress, localAddress, localSubmask, port, icon, flag, timezone, + (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop, build, region, battlegroup); + + if (init) + TC_LOG_INFO("server.authserver", "Added realm \"%s\" at %s:%u.", name.c_str(), m_realms[name].ExternalAddress.to_string().c_str(), port); + } + catch (std::exception& ex) + { + TC_LOG_ERROR("server.authserver", "Realmlist::UpdateRealms has thrown an exception: %s", ex.what()); + ASSERT(false); + } + } + while (result->NextRow()); + } +} + +Realm const* RealmList::GetRealm(Battlenet::RealmId const& id) const +{ + auto itr = std::find_if(m_realms.begin(), m_realms.end(), [id](RealmMap::value_type const& pair) + { + return pair.second.Region == id.Region && pair.second.Battlegroup == id.Battlegroup && pair.second.m_ID == id.Index; + }); + + if (itr != m_realms.end()) + return &itr->second; + + return NULL; +} diff --git a/src/server/bnetserver/Realms/RealmList.h b/src/server/bnetserver/Realms/RealmList.h new file mode 100644 index 00000000000..502fef80ee7 --- /dev/null +++ b/src/server/bnetserver/Realms/RealmList.h @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * Copyright (C) 2005-2009 MaNGOS + * + * 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 . + */ + +#ifndef _REALMLIST_H +#define _REALMLIST_H + +#include +#include +#include +#include "Common.h" + +using namespace boost::asio; + +enum RealmFlags +{ + REALM_FLAG_NONE = 0x00, + REALM_FLAG_INVALID = 0x01, + REALM_FLAG_OFFLINE = 0x02, + REALM_FLAG_SPECIFYBUILD = 0x04, + REALM_FLAG_UNK1 = 0x08, + REALM_FLAG_UNK2 = 0x10, + REALM_FLAG_RECOMMENDED = 0x20, + REALM_FLAG_NEW = 0x40, + REALM_FLAG_FULL = 0x80 +}; + +// Storage object for a realm +struct Realm +{ + ip::address ExternalAddress; + ip::address LocalAddress; + ip::address LocalSubnetMask; + uint16 port; + std::string name; + uint8 icon; + RealmFlags flag; + uint8 timezone; + uint32 m_ID; + AccountTypes allowedSecurityLevel; + float populationLevel; + uint32 gamebuild; + uint8 Region; + uint8 Battlegroup; + + ip::tcp::endpoint GetAddressForClient(ip::address const& clientAddr) const; +}; + +namespace Battlenet +{ + struct RealmId + { + uint8 Region; + uint8 Battlegroup; + uint32 Index; + uint32 Build; + }; +} + +/// Storage object for the list of realms on the server +class RealmList +{ +public: + typedef std::map RealmMap; + + static RealmList* instance() + { + static RealmList instance; + return &instance; + } + + ~RealmList(); + + void Initialize(boost::asio::io_service& ioService, uint32 updateInterval); + + void UpdateIfNeed(); + + void AddRealm(const Realm& NewRealm) { m_realms[NewRealm.name] = NewRealm; } + + RealmMap::const_iterator begin() const { return m_realms.begin(); } + RealmMap::const_iterator end() const { return m_realms.end(); } + uint32 size() const { return m_realms.size(); } + Realm const* GetRealm(Battlenet::RealmId const& id) const; + +private: + RealmList(); + + void UpdateRealms(bool init = false); + void UpdateRealm(uint32 id, const std::string& name, ip::address const& address, ip::address const& localAddr, + ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population, uint32 build, uint8 region, uint8 battlegroup); + + RealmMap m_realms; + uint32 m_UpdateInterval; + time_t m_NextUpdateTime; + boost::asio::ip::tcp::resolver* _resolver; +}; + +#define sRealmList RealmList::instance() +#endif diff --git a/src/server/bnetserver/Server/ComponentManager.cpp b/src/server/bnetserver/Server/ComponentManager.cpp new file mode 100644 index 00000000000..be1f22022f4 --- /dev/null +++ b/src/server/bnetserver/Server/ComponentManager.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * + * 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 . + */ + +#include "ComponentManager.h" +#include "DatabaseEnv.h" + +Battlenet::ComponentMgr::~ComponentMgr() +{ + for (Component* 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(); + Component* component = new Component(); + component->Program = fields[0].GetString(); + component->Platform = fields[1].GetString(); + component->Build = fields[2].GetUInt32(); + + _components.insert(component); + _programs.insert(component->Program); + _platforms.insert(component->Platform); + + } while (result->NextRow()); + } +} + +bool Battlenet::ComponentMgr::HasComponent(Battlenet::Component const* component) const +{ + for (Component const* c : _components) + if (component->Program == c->Program && component->Platform == c->Platform && component->Build == c->Build) + return true; + + return false; +} diff --git a/src/server/bnetserver/Server/ComponentManager.h b/src/server/bnetserver/Server/ComponentManager.h new file mode 100644 index 00000000000..865cfca7f62 --- /dev/null +++ b/src/server/bnetserver/Server/ComponentManager.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * + * 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 . + */ + +#ifndef ComponentManager_h__ +#define ComponentManager_h__ + +#include "Define.h" +#include +#include +#include + +namespace Battlenet +{ + struct Component + { + std::string Program; + std::string Platform; + uint32 Build; + }; + + class ComponentMgr + { + ComponentMgr() { } + ~ComponentMgr(); + + public: + void Load(); + bool HasComponent(Component 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 _components; + std::set _programs; + std::set _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 new file mode 100644 index 00000000000..8dc43136739 --- /dev/null +++ b/src/server/bnetserver/Server/ModuleManager.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * + * 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 . + */ + +#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->Type = fields[2].GetString(); + HexStrToByteArray(fields[0].GetString(), module->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 }; + ASSERT(_modules.count(key)); + + return new ModuleInfo(*_modules.at(key)); +} diff --git a/src/server/bnetserver/Server/ModuleManager.h b/src/server/bnetserver/Server/ModuleManager.h new file mode 100644 index 00000000000..36ffb2fec3f --- /dev/null +++ b/src/server/bnetserver/Server/ModuleManager.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * + * 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 . + */ + +#ifndef ModuleManager_h__ +#define ModuleManager_h__ + +#include "Define.h" +#include +#include +#include + +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 + { + ModuleInfo() : Region("EU"), DataSize(0), Data(nullptr) { } + ModuleInfo(ModuleInfo const& right) : Type(right.Type), Region(right.Region), DataSize(right.DataSize), Data(nullptr) + { + memcpy(ModuleId, right.ModuleId, 32); + if (DataSize) + { + Data = new uint8[DataSize]; + memcpy(Data, right.Data, DataSize); + } + } + ~ModuleInfo() + { + delete Data; + } + + std::string Type; + std::string Region; + uint8 ModuleId[32]; + uint32 DataSize; + uint8* Data; + }; + + 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: + void LoadComponents(); + void LoadModules(); + + std::map _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 new file mode 100644 index 00000000000..8935d520c40 --- /dev/null +++ b/src/server/bnetserver/Server/Session.cpp @@ -0,0 +1,1000 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * + * 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 . + */ + +#include "AuthCodes.h" +#include "BitStream.h" +#include "PacketFactory.h" +#include "SessionManager.h" +#include "Database/DatabaseEnv.h" +#include "HmacHash.h" +#include "Log.h" +#include "RealmList.h" +#include "SHA256.h" +#include + +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, +}; + +Battlenet::Session::Session(tcp::socket&& socket) : Socket(std::move(socket)), _accountId(0), _accountName(), _locale(), + _os(), _build(0), _gameAccountId(0), _gameAccountName(), _accountSecurityLevel(SEC_PLAYER), I(), s(), v(), b(), B(), K(), + _reconnectProof(), _crypt(), _authed(false) +{ + 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()); +} + +Battlenet::Session::~Session() +{ + sSessionMgr.RemoveSession(this); + TC_LOG_TRACE("server.battlenet", "Battlenet::Session::OnClose"); +} + +void Battlenet::Session::_SetVSFields(std::string const& pstr) +{ + s.SetRand(uint32(BufferSizes::SRP_6_S) * 8); + + BigNumber p; + p.SetHexStr(pstr.c_str()); + + SHA256Hash sha; + sha.UpdateBigNumbers(&s, &p, NULL); + sha.Finalize(); + BigNumber x; + x.SetBinary(sha.GetDigest(), sha.GetLength()); + v = g.ModExp(x, N); + + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_VS_FIELDS); + stmt->setString(0, v.AsHexStr()); + stmt->setString(1, s.AsHexStr()); + stmt->setString(2, _accountName); + + LoginDatabase.Execute(stmt); +} + +void Battlenet::Session::LogUnhandledPacket(ClientPacket const& packet) +{ + TC_LOG_DEBUG("server.battlenet", "Battlenet::Session::LogUnhandledPacket %s", packet.ToString().c_str()); +} + +void Battlenet::Session::HandleLogonRequest(Authentication::LogonRequest const& info) +{ + // Verify that this IP is not in the ip_banned table + LoginDatabase.Execute(LoginDatabase.GetPreparedStatement(LOGIN_DEL_EXPIRED_IP_BANS)); + + std::string ip_address = GetRemoteIpAddress().to_string(); + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_IP_BANNED); + stmt->setString(0, ip_address); + if (PreparedQueryResult result = LoginDatabase.Query(stmt)) + { + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); + complete->SetAuthResult(LOGIN_BANNED); + AsyncWrite(complete); + TC_LOG_DEBUG("server.battlenet", "[Battlenet::LogonRequest] Banned ip '%s:%d' tries to login!", ip_address.c_str(), GetRemotePort()); + return; + } + + if (info.Program != "WoW") + { + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); + complete->SetAuthResult(AUTH_INVALID_PROGRAM); + AsyncWrite(complete); + return; + } + + if (!sComponentMgr->HasPlatform(info.Platform)) + { + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); + complete->SetAuthResult(AUTH_INVALID_OS); + AsyncWrite(complete); + return; + } + + if (!sComponentMgr->HasPlatform(info.Locale)) + { + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); + complete->SetAuthResult(AUTH_UNSUPPORTED_LANGUAGE); + AsyncWrite(complete); + return; + } + + for (Component const& component : info.Components) + { + if (!sComponentMgr->HasComponent(&component)) + { + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); + if (!sComponentMgr->HasProgram(component.Program)) + complete->SetAuthResult(AUTH_INVALID_PROGRAM); + else if (!sComponentMgr->HasPlatform(component.Platform)) + complete->SetAuthResult(AUTH_INVALID_OS); + else + { + if (component.Program != "WoW" || AuthHelper::IsBuildSupportingBattlenet(component.Build)) + complete->SetAuthResult(AUTH_REGION_BAD_VERSION); + else + complete->SetAuthResult(AUTH_USE_GRUNT_LOGON); + } + + AsyncWrite(complete); + return; + } + + if (component.Platform == "base") + _build = component.Build; + } + + _accountName = info.Login; + _locale = info.Locale; + _os = info.Platform; + + Utf8ToUpperOnlyLatin(_accountName); + stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_ACCOUNT_INFO); + stmt->setString(0, _accountName); + + PreparedQueryResult result = LoginDatabase.Query(stmt); + if (!result) + { + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); + complete->SetAuthResult(AUTH_UNKNOWN_ACCOUNT); + AsyncWrite(complete); + return; + } + + Field* fields = result->Fetch(); + + _accountId = fields[1].GetUInt32(); + + // If the IP is 'locked', check that the player comes indeed from the correct IP address + if (fields[2].GetUInt8() == 1) // if ip is locked + { + TC_LOG_DEBUG("server.battlenet", "[Battlenet::LogonRequest] Account '%s' is locked to IP - '%s' is logging in from '%s'", _accountName.c_str(), fields[4].GetCString(), ip_address.c_str()); + + if (strcmp(fields[4].GetCString(), ip_address.c_str()) != 0) + { + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); + complete->SetAuthResult(AUTH_ACCOUNT_LOCKED); + AsyncWrite(complete); + return; + } + } + else + { + TC_LOG_DEBUG("server.battlenet", "[Battlenet::LogonRequest] Account '%s' is not locked to ip", _accountName.c_str()); + std::string accountCountry = fields[3].GetString(); + if (accountCountry.empty() || accountCountry == "00") + TC_LOG_DEBUG("server.battlenet", "[Battlenet::LogonRequest] Account '%s' is not locked to country", _accountName.c_str()); + else if (!accountCountry.empty()) + { + uint32 ip = inet_addr(ip_address.c_str()); + EndianConvertReverse(ip); + + stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_LOGON_COUNTRY); + stmt->setUInt32(0, ip); + if (PreparedQueryResult sessionCountryQuery = LoginDatabase.Query(stmt)) + { + std::string loginCountry = (*sessionCountryQuery)[0].GetString(); + TC_LOG_DEBUG("server.battlenet", "[Battlenet::AuthChallenge] Account '%s' is locked to country: '%s' Player country is '%s'", _accountName.c_str(), accountCountry.c_str(), loginCountry.c_str()); + if (loginCountry != accountCountry) + { + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); + complete->SetAuthResult(AUTH_ACCOUNT_LOCKED); + AsyncWrite(complete); + return; + } + } + } + } + + //set expired bans to inactive + LoginDatabase.DirectExecute(LoginDatabase.GetPreparedStatement(LOGIN_DEL_BNET_EXPIRED_BANS)); + + // If the account is banned, reject the logon attempt + stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_ACTIVE_ACCOUNT_BAN); + stmt->setUInt32(0, _accountId); + PreparedQueryResult banresult = LoginDatabase.Query(stmt); + if (banresult) + { + Field* fields = banresult->Fetch(); + if (fields[0].GetUInt32() == fields[1].GetUInt32()) + { + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); + complete->SetAuthResult(LOGIN_BANNED); + AsyncWrite(complete); + TC_LOG_DEBUG("server.battlenet", "'%s:%d' [Battlenet::LogonRequest] Banned account %s tried to login!", ip_address.c_str(), GetRemotePort(), _accountName.c_str()); + return; + } + else + { + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); + complete->SetAuthResult(LOGIN_SUSPENDED); + AsyncWrite(complete); + TC_LOG_DEBUG("server.battlenet", "'%s:%d' [Battlenet::LogonRequest] Temporarily banned account %s tried to login!", ip_address.c_str(), GetRemotePort(), _accountName.c_str()); + return; + } + } + + SHA256Hash sha; + sha.UpdateData(_accountName); + sha.Finalize(); + + I.SetBinary(sha.GetDigest(), sha.GetLength()); + + ModuleInfo* password = sModuleMgr->CreateModule(_os, "Password"); + ModuleInfo* thumbprint = sModuleMgr->CreateModule(_os, "Thumbprint"); + + std::string pStr = fields[0].GetString(); + + std::string databaseV = fields[5].GetString(); + std::string databaseS = fields[6].GetString(); + + if (databaseV.size() != size_t(BufferSizes::SRP_6_V) * 2 || databaseS.size() != size_t(BufferSizes::SRP_6_S) * 2) + _SetVSFields(pStr); + else + { + s.SetHexStr(databaseS.c_str()); + v.SetHexStr(databaseV.c_str()); + } + + 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* request = new Authentication::ProofRequest(); + request->Modules.push_back(password); + // if has authenticator, send Token module + request->Modules.push_back(thumbprint); + AsyncWrite(request); +} + +void Battlenet::Session::HandleResumeRequest(Authentication::ResumeRequest const& reconnect) +{ + _accountName = reconnect.Login; + _locale = reconnect.Locale; + _os = reconnect.Platform; + auto baseComponent = std::find_if(reconnect.Components.begin(), reconnect.Components.end(), [](Component const& c) { return c.Program == "base"; }); + if (baseComponent != reconnect.Components.end()) + _build = baseComponent->Build; + + Utf8ToUpperOnlyLatin(_accountName); + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_RECONNECT_INFO); + stmt->setString(0, _accountName); + stmt->setString(1, reconnect.GameAccountName); + PreparedQueryResult result = LoginDatabase.Query(stmt); + if (!result) + { + Authentication::ResumeResponse* resume = new Authentication::ResumeResponse(); + resume->SetAuthResult(AUTH_UNKNOWN_ACCOUNT); + AsyncWrite(resume); + return; + } + + Field* fields = result->Fetch(); + + _accountId = fields[0].GetUInt32(); + K.SetHexStr(fields[1].GetString().c_str()); + _gameAccountId = fields[2].GetUInt32(); + _gameAccountName = reconnect.GameAccountName; + + ModuleInfo* thumbprint = sModuleMgr->CreateModule(_os, "Thumbprint"); + ModuleInfo* resume = sModuleMgr->CreateModule(_os, "Resume"); + BitStream resumeData; + uint8 state = 0; + _reconnectProof.SetRand(16 * 8); + + 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); + + _modulesWaitingForData.push(MODULE_RESUME); + + Authentication::ProofRequest* request = new Authentication::ProofRequest(); + request->Modules.push_back(thumbprint); + request->Modules.push_back(resume); + AsyncWrite(request); +} + +void Battlenet::Session::HandleProofResponse(Authentication::ProofResponse const& proof) +{ + if (_modulesWaitingForData.size() < proof.Modules.size()) + { + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); + complete->SetAuthResult(AUTH_CORRUPTED_MODULE); + AsyncWrite(complete); + return; + } + + ServerPacket* response = nullptr; + for (size_t i = 0; i < proof.Modules.size(); ++i) + { + if (!(this->*(ModuleHandlers[_modulesWaitingForData.front()]))(proof.Modules[i], &response)) + break; + + _modulesWaitingForData.pop(); + } + + if (!response) + { + response = new Authentication::LogonResponse(); + static_cast(response)->SetAuthResult(AUTH_INTERNAL_ERROR); + } + + AsyncWrite(response); + return; +} + +void Battlenet::Session::HandlePing(Connection::Ping const& /*ping*/) +{ + AsyncWrite(new Connection::Pong()); +} + +void Battlenet::Session::HandleEnableEncryption(Connection::EnableEncryption const& /*enableEncryption*/) +{ + _crypt.Init(&K); +} + +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, _accountId); + LoginDatabase.Execute(stmt); +} + +void Battlenet::Session::HandleListSubscribeRequest(WoWRealm::ListSubscribeRequest const& /*listSubscribeRequest*/) +{ + sRealmList->UpdateIfNeed(); + + WoWRealm::ListSubscribeResponse* counts = new WoWRealm::ListSubscribeResponse(); + + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_CHARACTER_COUNTS); + stmt->setUInt32(0, _gameAccountId); + + if (PreparedQueryResult countResult = LoginDatabase.Query(stmt)) + { + do + { + Field* fields = countResult->Fetch(); + uint32 build = fields[4].GetUInt32(); + counts->CharacterCounts.push_back({ { fields[2].GetUInt8(), fields[3].GetUInt8(), fields[1].GetUInt32(), (_build != build ? build : 0) }, fields[0].GetUInt8() }); + } while (countResult->NextRow()); + } + + for (RealmList::RealmMap::const_iterator i = sRealmList->begin(); i != sRealmList->end(); ++i) + { + Realm const& realm = i->second; + + uint32 flag = realm.flag & ~REALM_FLAG_SPECIFYBUILD; + RealmBuildInfo const* buildInfo = AuthHelper::GetBuildInfo(realm.gamebuild); + if (realm.gamebuild != _build) + { + flag |= REALM_FLAG_INVALID; + if (buildInfo) + flag |= REALM_FLAG_SPECIFYBUILD; // tell the client what build the realm is for + } + + WoWRealm::ListUpdate* update = new WoWRealm::ListUpdate(); + update->Timezone = realm.timezone; + update->Population = realm.populationLevel; + update->Lock = (realm.allowedSecurityLevel > _accountSecurityLevel) ? 1 : 0; + update->Type = realm.icon; + update->Name = realm.name; + + if (flag & REALM_FLAG_SPECIFYBUILD) + { + std::ostringstream version; + version << buildInfo->MajorVersion << '.' << buildInfo->MinorVersion << '.' << buildInfo->BugfixVersion << '.' << buildInfo->Build; + + update->Version = version.str(); + update->Address = realm.GetAddressForClient(GetRemoteIpAddress()); + update->Build = buildInfo->Build; + } + + update->Flags = flag; + update->Region = realm.Region; + update->Battlegroup = realm.Battlegroup; + update->Index = realm.m_ID; + + counts->RealmData.push_back(update); + } + + counts->RealmData.push_back(new WoWRealm::ListComplete()); + + AsyncWrite(counts); +} + +void Battlenet::Session::HandleJoinRequestV2(WoWRealm::JoinRequestV2 const& join) +{ + WoWRealm::JoinResponseV2* result = new WoWRealm::JoinResponseV2(); + Realm const* realm = sRealmList->GetRealm(join.Realm); + if (!realm || realm->flag & (REALM_FLAG_INVALID | REALM_FLAG_OFFLINE)) + { + result->Response = WoWRealm::JoinResponseV2::FAILURE; + AsyncWrite(result); + return; + } + + result->ServerSeed = uint32(rand32()); + + uint8 sessionKey[40]; + HmacSha1 hmac(K.GetNumBytes(), K.AsByteArray().get()); + hmac.UpdateData((uint8*)"WoW\0", 4); + hmac.UpdateData((uint8*)&join.ClientSeed, 4); + hmac.UpdateData((uint8*)&result->ServerSeed, 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*)&result->ServerSeed, 4); + hmac2.UpdateData((uint8*)&join.ClientSeed, 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(), _gameAccountId); + + result->IPv4.emplace_back(realm->ExternalAddress, realm->port); + if (realm->ExternalAddress != realm->LocalAddress) + result->IPv4.emplace_back(realm->LocalAddress, realm->port); + + AsyncWrite(result); +} + +void Battlenet::Session::ReadHandler() +{ + BitStream stream(std::move(GetReadBuffer())); + _crypt.DecryptRecv(stream.GetBuffer(), stream.GetSize()); + + while (!stream.IsRead()) + { + try + { + PacketHeader header; + header.Opcode = stream.Read(6); + if (stream.Read(1)) + header.Channel = stream.Read(4); + + if (header.Channel != AUTHENTICATION && !_authed) + { + TC_LOG_DEBUG("server.battlenet", "Battlenet::Session::ReadDataHandler Received not allowed packet %s", header.ToString().c_str()); + CloseSocket(); + return; + } + + if (ClientPacket* packet = sPacketFactory.Create(header, stream)) + { + TC_LOG_TRACE("server.battlenet", "Battlenet::Session::ReadDataHandler %s", packet->ToString().c_str()); + packet->CallHandler(this); + delete packet; + } + else + { + TC_LOG_DEBUG("server.battlenet", "Battlenet::Session::ReadDataHandler Unhandled opcode %s", header.ToString().c_str()); + break; + } + + stream.AlignToNextByte(); + } + catch (BitStreamPositionException const& e) + { + TC_LOG_ERROR("server.battlenet", "Battlenet::Session::ReadDataHandler Exception: %s", e.what()); + CloseSocket(); + return; + } + } + + GetReadBuffer().Resize(size_t(BufferSizes::Read)); + AsyncRead(); +} + +void Battlenet::Session::Start() +{ + TC_LOG_TRACE("server.battlenet", "Battlenet::Session::Start"); + AsyncRead(); +} + +void Battlenet::Session::AsyncWrite(ServerPacket* packet) +{ + if (!IsOpen()) + { + delete packet; + return; + } + + TC_LOG_TRACE("server.battlenet", "Battlenet::Session::AsyncWrite %s", packet->ToString().c_str()); + + packet->Write(); + + MessageBuffer buffer; + buffer.Write(packet->GetData(), packet->GetSize()); + delete packet; + + std::unique_lock guard(_writeLock); + + _crypt.EncryptSend(buffer.GetReadPointer(), buffer.GetActiveSize()); + + QueuePacket(std::move(buffer), guard); +} + +inline void ReplaceResponse(Battlenet::ServerPacket** oldResponse, Battlenet::ServerPacket* newResponse) +{ + if (*oldResponse) + delete *oldResponse; + + *oldResponse = newResponse; +} + +bool Battlenet::Session::HandlePasswordModule(BitStream* dataStream, ServerPacket** response) +{ + if (dataStream->GetSize() != 1 + 128 + 32 + 128) + { + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); + complete->SetAuthResult(AUTH_CORRUPTED_MODULE); + ReplaceResponse(response, complete); + return false; + } + + if (dataStream->Read(8) != 2) // State + { + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); + complete->SetAuthResult(AUTH_CORRUPTED_MODULE); + ReplaceResponse(response, complete); + return false; + } + + + 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); + + if (A.isZero()) + { + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); + complete->SetAuthResult(AUTH_CORRUPTED_MODULE); + ReplaceResponse(response, complete); + return false; + } + + 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); + + uint8 part1[64]; + uint8 part2[64]; + + for (int i = 0; i < 64; ++i) + { + part1[i] = S_bytes[i * 2]; + part2[i] = S_bytes[i * 2 + 1]; + } + + 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) + { + 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, _accountName); + LoginDatabase.Execute(stmt); + + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); + complete->SetAuthResult(AUTH_UNKNOWN_ACCOUNT); + ReplaceResponse(response, complete); + return false; + } + + uint64 numAccounts = 0; + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_GAME_ACCOUNTS); + stmt->setUInt32(0, _accountId); + PreparedQueryResult result = LoginDatabase.Query(stmt); + if (result) + numAccounts = result->GetRowCount(); + + if (!numAccounts) + { + Authentication::LogonResponse* noAccounts = new Authentication::LogonResponse(); + noAccounts->SetAuthResult(LOGIN_NO_GAME_ACCOUNT); + ReplaceResponse(response, noAccounts); + return false; + } + + Field* fields = result->Fetch(); + + //set expired game account bans to inactive + LoginDatabase.DirectExecute(LoginDatabase.GetPreparedStatement(LOGIN_UPD_EXPIRED_ACCOUNT_BANS)); + + 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* request = new Authentication::ProofRequest(); + request->Modules.push_back(password); + if (numAccounts > 1) + { + BitStream accounts; + state = 0; + accounts.WriteBytes(&state, 1); + accounts.Write(numAccounts, 8); + do + { + fields = result->Fetch(); + std::ostringstream name; + std::string originalName = fields[1].GetString(); + if (originalName.find('#') != std::string::npos) + name << "WoW" << uint32(fields[0].GetUInt8()); + else + name << originalName; + + accounts.Write(2, 8); + accounts.WriteString(name.str(), 8); + } while (result->NextRow()); + + ModuleInfo* selectGameAccount = sModuleMgr->CreateModule(_os, "SelectGameAccount"); + selectGameAccount->DataSize = accounts.GetSize(); + selectGameAccount->Data = new uint8[selectGameAccount->DataSize]; + memcpy(selectGameAccount->Data, accounts.GetBuffer(), selectGameAccount->DataSize); + request->Modules.push_back(selectGameAccount); + _modulesWaitingForData.push(MODULE_SELECT_GAME_ACCOUNT); + } + else + { + if (fields[4].GetBool()) + { + delete request; + + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); + if (fields[2].GetUInt32() == fields[3].GetUInt32()) + { + complete->SetAuthResult(LOGIN_BANNED); + TC_LOG_DEBUG("server.battlenet", "'%s:%d' [Battlenet::Password] Banned account %s tried to login!", GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _accountName.c_str()); + } + else + { + complete->SetAuthResult(LOGIN_SUSPENDED); + TC_LOG_DEBUG("server.battlenet", "'%s:%d' [Battlenet::Password] Temporarily banned account %s tried to login!", GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _accountName.c_str()); + } + + ReplaceResponse(response, complete); + return false; + } + + _gameAccountId = fields[0].GetUInt32(); + _gameAccountName = fields[1].GetString(); + + request->Modules.push_back(sModuleMgr->CreateModule(_os, "RiskFingerprint")); + _modulesWaitingForData.push(MODULE_RISK_FINGERPRINT); + } + + ReplaceResponse(response, request); + return true; +} + +bool Battlenet::Session::HandleSelectGameAccountModule(BitStream* dataStream, ServerPacket** response) +{ + if (dataStream->Read(8) != 1) + { + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); + complete->SetAuthResult(AUTH_CORRUPTED_MODULE); + ReplaceResponse(response, complete); + return false; + } + + dataStream->Read(8); + std::string account = dataStream->ReadString(8); + if (account.empty()) + { + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); + complete->SetAuthResult(LOGIN_NO_GAME_ACCOUNT); + ReplaceResponse(response, complete); + return false; + } + + PreparedStatement* stmt; + if (account.substr(0, 3) != "WoW") + { + stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_GAME_ACCOUNT); + stmt->setString(0, account); + } + else + { + stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_GAME_ACCOUNT_UNNAMED); + stmt->setUInt8(0, atol(account.substr(3).c_str())); + } + + stmt->setUInt32(1, _accountId); + PreparedQueryResult result = LoginDatabase.Query(stmt); + if (!result) + { + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); + complete->SetAuthResult(LOGIN_NO_GAME_ACCOUNT); + ReplaceResponse(response, complete); + return false; + } + + Field* fields = result->Fetch(); + if (fields[4].GetBool()) + { + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); + if (fields[2].GetUInt32() == fields[3].GetUInt32()) + { + complete->SetAuthResult(LOGIN_BANNED); + TC_LOG_DEBUG("server.battlenet", "'%s:%d' [Battlenet::SelectGameAccount] Banned account %s tried to login!", GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _accountName.c_str()); + } + else + { + complete->SetAuthResult(LOGIN_SUSPENDED); + TC_LOG_DEBUG("server.battlenet", "'%s:%d' [Battlenet::SelectGameAccount] Temporarily banned account %s tried to login!", GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _accountName.c_str()); + } + + ReplaceResponse(response, complete); + return false; + } + + _gameAccountId = fields[0].GetUInt32(); + _gameAccountName = fields[1].GetString(); + + Authentication::ProofRequest* request = new Authentication::ProofRequest(); + request->Modules.push_back(sModuleMgr->CreateModule(_os, "RiskFingerprint")); + ReplaceResponse(response, request); + + _modulesWaitingForData.push(MODULE_RISK_FINGERPRINT); + return true; +} + +bool Battlenet::Session::HandleRiskFingerprintModule(BitStream* dataStream, ServerPacket** response) +{ + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); + if (dataStream->Read(8) == 1) + { + complete->AccountId = _accountId; + complete->GameAccountName = _gameAccountName; + complete->GameAccountFlags = GAMEACCOUNT_FLAG_PROPASS_LOCK; + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_FAILED_LOGINS); + stmt->setUInt32(0, _accountId); + if (PreparedQueryResult failedLoginsResult = LoginDatabase.Query(stmt)) + complete->FailedLogins = (*failedLoginsResult)[0].GetUInt32(); + + SQLTransaction trans = LoginDatabase.BeginTransaction(); + + 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, _accountId); + trans->Append(stmt); + + stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_SESSION_KEY); + stmt->setString(0, K.AsHexStr()); + stmt->setBool(1, true); + stmt->setUInt32(2, _accountId); + trans->Append(stmt); + + LoginDatabase.CommitTransaction(trans); + + _authed = true; + sSessionMgr.AddSession(this); + } + else + complete->SetAuthResult(AUTH_BAD_VERSION_HASH); + + ReplaceResponse(response, complete); + return true; +} + +bool Battlenet::Session::HandleResumeModule(BitStream* dataStream, ServerPacket** response) +{ + if (dataStream->Read(8) != 1) + { + Authentication::ResumeResponse* complete = new Authentication::ResumeResponse(); + complete->SetAuthResult(AUTH_CORRUPTED_MODULE); + ReplaceResponse(response, complete); + return false; + } + + static uint8 const ResumeClient = 0; + static uint8 const ResumeServer = 1; + + std::unique_ptr clientChallenge = dataStream->ReadBytes(16); + std::unique_ptr clientProof = dataStream->ReadBytes(32); + std::unique_ptr serverChallenge = _reconnectProof.AsByteArray(16); + std::unique_ptr 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); + + 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, _accountName); + LoginDatabase.Execute(stmt); + + TC_LOG_DEBUG("server.battlenet", "[Battlenet::Resume] Invalid proof!"); + Authentication::ResumeResponse* result = new Authentication::ResumeResponse(); + result->SetAuthResult(AUTH_UNKNOWN_ACCOUNT); + ReplaceResponse(response, result); + return false; + } + + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_SESSION_KEY); + stmt->setString(0, K.AsHexStr()); + stmt->setBool(1, true); + stmt->setUInt32(2, _accountId); + 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* result = new Authentication::ResumeResponse(); + result->Modules.push_back(resume); + ReplaceResponse(response, result); + _authed = true; + sSessionMgr.AddSession(this); + return true; +} + +bool Battlenet::Session::UnhandledModule(BitStream* /*dataStream*/, ServerPacket** response) +{ + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); + complete->SetAuthResult(AUTH_CORRUPTED_MODULE); + ReplaceResponse(response, complete); + return false; +} diff --git a/src/server/bnetserver/Server/Session.h b/src/server/bnetserver/Server/Session.h new file mode 100644 index 00000000000..41caadbab3f --- /dev/null +++ b/src/server/bnetserver/Server/Session.h @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * + * 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 . + */ + +#ifndef Session_h__ +#define Session_h__ + +#include "Packets.h" +#include "BattlenetPacketCrypt.h" +#include "Socket.h" +#include "BigNumber.h" +#include +#include + +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 + }; + + enum class BufferSizes : uint32 + { + SRP_6_V = 0x80, + SRP_6_S = 0x20, + Read = 0x4000 + }; + + class Session : public Socket + { + typedef Socket BattlenetSocket; + + public: + explicit Session(tcp::socket&& socket); + ~Session(); + + void LogUnhandledPacket(ClientPacket const& packet); + + // Authentication + void HandleLogonRequest(Authentication::LogonRequest const& logonRequest); + void HandleResumeRequest(Authentication::ResumeRequest const& resumeRequest); + void HandleProofResponse(Authentication::ProofResponse const& proofResponse); + + // Connection + void HandlePing(Connection::Ping const& ping); + void HandleEnableEncryption(Connection::EnableEncryption const& enableEncryption); + void HandleLogoutRequest(Connection::LogoutRequest const& logoutRequest); + + // WoWRealm + void HandleListSubscribeRequest(WoWRealm::ListSubscribeRequest const& listSubscribeRequest); + void HandleJoinRequestV2(WoWRealm::JoinRequestV2 const& joinRequest); + + void Start() override; + + void AsyncWrite(ServerPacket* packet); + + protected: + void ReadHandler() override; + + private: + void _SetVSFields(std::string const& rI); + + typedef bool(Session::*ModuleHandler)(BitStream* dataStream, ServerPacket** response); + static ModuleHandler const ModuleHandlers[MODULE_COUNT]; + + 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); + + uint32 _accountId; + std::string _accountName; + std::string _locale; + std::string _os; + uint32 _build; + uint32 _gameAccountId; + std::string _gameAccountName; + AccountTypes _accountSecurityLevel; + + BigNumber N; + BigNumber g; + BigNumber k; + + BigNumber I; + BigNumber s; + BigNumber v; + + BigNumber b; + BigNumber B; + BigNumber K; // session key + + BigNumber _reconnectProof; + + std::queue _modulesWaitingForData; + + PacketCrypt _crypt; + bool _authed; + }; + +} + +#endif // Session_h__ diff --git a/src/server/bnetserver/Server/SessionManager.cpp b/src/server/bnetserver/Server/SessionManager.cpp new file mode 100644 index 00000000000..d8b6bfca8d1 --- /dev/null +++ b/src/server/bnetserver/Server/SessionManager.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * + * 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 . + */ + +#include "SessionManager.h" + +bool Battlenet::SessionManager::StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port) +{ + if (!BaseSocketMgr::StartNetwork(service, bindIp, port)) + return false; + + _acceptor->AsyncAcceptManaged(&OnSocketAccept); + return true; +} + +NetworkThread* Battlenet::SessionManager::CreateThreads() const +{ + return new NetworkThread[GetNetworkThreadCount()]; +} + +void Battlenet::SessionManager::OnSocketAccept(tcp::socket&& sock) +{ + sSessionMgr.OnSocketOpen(std::forward(sock)); +} diff --git a/src/server/bnetserver/Server/SessionManager.h b/src/server/bnetserver/Server/SessionManager.h new file mode 100644 index 00000000000..10e7196e4d8 --- /dev/null +++ b/src/server/bnetserver/Server/SessionManager.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * + * 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 . + */ + +#ifndef SessionManager_h__ +#define SessionManager_h__ + +#include "Session.h" +#include "SocketMgr.h" + +namespace Battlenet +{ +#pragma pack(push, 1) + + struct SessionInfo + { + uint32 AccountId; + uint32 GameAccountIndex; + + bool operator<(SessionInfo const& right) const + { + return memcmp(this, &right, sizeof(SessionInfo)) < 0; + } + }; + +#pragma pack(pop) + + class SessionManager : SocketMgr + { + typedef SocketMgr BaseSocketMgr; + + public: + static SessionManager& Instance() + { + static SessionManager instance; + return instance; + } + + bool StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port) override; + + // noop for now, will be needed later to broadcast realmlist updates for example + void AddSession(Session* /*session*/) { } + + void RemoveSession(Session* /*session*/) { } + + protected: + NetworkThread* CreateThreads() const override; + + private: + static void OnSocketAccept(tcp::socket&& sock); + + std::map _sessions; + }; +} + +#define sSessionMgr Battlenet::SessionManager::Instance() + +#endif // SessionManager_h__ diff --git a/src/server/bnetserver/bnetserver.conf.dist b/src/server/bnetserver/bnetserver.conf.dist new file mode 100644 index 00000000000..e0ef6982353 --- /dev/null +++ b/src/server/bnetserver/bnetserver.conf.dist @@ -0,0 +1,257 @@ +############################################### +# Trinity Core Auth Server configuration file # +############################################### +[authserver] + +################################################################################################### +# SECTION INDEX +# +# EXAMPLE CONFIG +# AUTH SERVER SETTINGS +# MYSQL SETTINGS +# LOGGING SYSTEM SETTINGS +# +################################################################################################### + +################################################################################################### +# EXAMPLE CONFIG +# +# Variable +# Description: Brief description what the variable is doing. +# Important: Annotation for important things about this variable. +# Example: "Example, i.e. if the value is a string" +# Default: 10 - (Enabled|Comment|Variable name in case of grouped config options) +# 0 - (Disabled|Comment|Variable name in case of grouped config options) +# +# Note to developers: +# - Copy this example to keep the formatting. +# - Line breaks should be at column 100. +################################################################################################### + +################################################################################################### +# AUTH SERVER SETTINGS +# +# LogsDir +# Description: Logs directory setting. +# Important: LogsDir needs to be quoted, as the string might contain space characters. +# Logs directory must exists, or log file creation will be disabled. +# Default: "" - (Log files will be stored in the current path) + +LogsDir = "" + +# +# MaxPingTime +# Description: Time (in minutes) between database pings. +# Default: 30 + +MaxPingTime = 30 + +# +# RealmServerPort +# Description: TCP port to reach the auth server. +# Default: 3724 + +RealmServerPort = 3724 + +# +# BattlenetPort +# Description: TCP port to reach the auth server for battle.net connections. +# Default: 1119 + +BattlenetPort = 1119 + +# +# +# BindIP +# Description: Bind auth server to IP/hostname +# Default: "0.0.0.0" - (Bind to all IPs on the system) + +BindIP = "0.0.0.0" + +# +# PidFile +# Description: Auth server PID file. +# Example: "./authserver.pid" - (Enabled) +# Default: "" - (Disabled) + +PidFile = "" + +# +# UseProcessors +# Description: Processors mask for Windows and Linux based multi-processor systems. +# Example: A computer with 2 CPUs: +# 1 - 1st CPU only, 2 - 2nd CPU only, 3 - 1st and 2nd CPU, because 1 | 2 is 3 +# Default: 0 - (Selected by OS) +# 1+ - (Bit mask value of selected processors) + +UseProcessors = 0 + +# +# ProcessPriority +# Description: Process priority setting for Windows and Linux based systems. +# Details: On Linux, a nice value of -15 is used. (requires superuser). On Windows, process is set to HIGH class. +# Default: 0 - (Normal) +# 1 - (High) + +ProcessPriority = 0 + +# +# RealmsStateUpdateDelay +# Description: Time (in seconds) between realm list updates. +# Default: 20 - (Enabled) +# 0 - (Disabled) + +RealmsStateUpdateDelay = 20 + +# +# WrongPass.MaxCount +# Description: Number of login attemps with wrong password before the account or IP will be +# banned. +# Default: 0 - (Disabled) +# 1+ - (Enabled) + +WrongPass.MaxCount = 0 + +# +# WrongPass.BanTime +# Description: Time (in seconds) for banning account or IP for invalid login attempts. +# Default: 600 - (10 minutes) +# 0 - (Permanent ban) + +WrongPass.BanTime = 600 + +# +# WrongPass.BanType +# Description: Ban type for invalid login attempts. +# Default: 0 - (Ban IP) +# 1 - (Ban Account) + +WrongPass.BanType = 0 + +# +################################################################################################### + +################################################################################################### +# MYSQL SETTINGS +# +# LoginDatabaseInfo +# Description: Database connection settings for the realm server. +# Example: "hostname;port;username;password;database" +# ".;somenumber;username;password;database" - (Use named pipes on Windows +# "enable-named-pipe" to [mysqld] +# section my.ini) +# ".;/path/to/unix_socket;username;password;database" - (use Unix sockets on +# Unix/Linux) +# Default: "127.0.0.1;3306;trinity;trinity;auth" + +LoginDatabaseInfo = "127.0.0.1;3306;trinity;trinity;auth" + +# +# LoginDatabase.WorkerThreads +# Description: The amount of worker threads spawned to handle asynchronous (delayed) MySQL +# statements. Each worker thread is mirrored with its own connection to the +# Default: 1 + +LoginDatabase.WorkerThreads = 1 + +# +# Wrong.Password.Login.Logging +# Description: Additionally log attempted wrong password logging +# Default: 0 - (Disabled) +# 1 - (Enabled) + +Wrong.Password.Login.Logging = 0 +# +################################################################################################### + +################################################################################################### +# +# LOGGING SYSTEM SETTINGS +# +# Appender config values: Given a appender "name" +# Appender.name +# Description: Defines 'where to log' +# Format: Type,LogLevel,Flags,optional1,optional2,optional3 +# +# Type +# 0 - (None) +# 1 - (Console) +# 2 - (File) +# 3 - (DB) +# +# LogLevel +# 0 - (Disabled) +# 1 - (Trace) +# 2 - (Debug) +# 3 - (Info) +# 4 - (Warn) +# 5 - (Error) +# 6 - (Fatal) +# +# Flags: +# 0 - None +# 1 - Prefix Timestamp to the text +# 2 - Prefix Log Level to the text +# 4 - Prefix Log Filter type to the text +# 8 - Append timestamp to the log file name. Format: YYYY-MM-DD_HH-MM-SS (Only used with Type = 2) +# 16 - Make a backup of existing file before overwrite (Only used with Mode = w) +# +# Colors (read as optional1 if Type = Console) +# Format: "fatal error warn info debug trace" +# 0 - BLACK +# 1 - RED +# 2 - GREEN +# 3 - BROWN +# 4 - BLUE +# 5 - MAGENTA +# 6 - CYAN +# 7 - GREY +# 8 - YELLOW +# 9 - LRED +# 10 - LGREEN +# 11 - LBLUE +# 12 - LMAGENTA +# 13 - LCYAN +# 14 - WHITE +# Example: "13 11 9 5 3 1" +# +# File: Name of the file (read as optional1 if Type = File) +# Allows to use one "%s" to create dynamic files +# +# Mode: Mode to open the file (read as optional2 if Type = File) +# a - (Append) +# w - (Overwrite) +# +# MaxFileSize: Maximum file size of the log file before creating a new log file +# (read as optional3 if Type = File) +# Size is measured in bytes expressed in a 64-bit unsigned integer. +# Maximum value is 4294967295 (4 gb). Leave blank for no limit. +# NOTE: Does not work with dynamic filenames. +# Example: 536870912 (512 mb) +# + +Appender.Console=1,2,0 +Appender.Auth=2,2,0,Auth.log,w + +# Logger config values: Given a logger "name" +# Logger.name +# Description: Defines 'What to log' +# Format: LogLevel,AppenderList +# +# LogLevel +# 0 - (Disabled) +# 1 - (Trace) +# 2 - (Debug) +# 3 - (Info) +# 4 - (Warn) +# 5 - (Error) +# 6 - (Fatal) +# +# AppenderList: List of appenders linked to logger +# (Using spaces as separator). +# + +Logger.root=3,Console Auth + +# +################################################################################################### diff --git a/src/server/bnetserver/bnetserver.ico b/src/server/bnetserver/bnetserver.ico new file mode 100644 index 00000000000..da318f48a8c Binary files /dev/null and b/src/server/bnetserver/bnetserver.ico differ diff --git a/src/server/bnetserver/bnetserver.rc b/src/server/bnetserver/bnetserver.rc new file mode 100644 index 00000000000..f030203fdcd --- /dev/null +++ b/src/server/bnetserver/bnetserver.rc @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * Copyright (C) 2005-2009 MaNGOS + * + * 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 . + */ + +#include "resource.h" +#include "revision.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "windows.h" //"afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APPICON ICON "bnetserver.ico" + +///////////////////////////////////////////////////////////////////////////// +// Neutre (Par défaut système) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEUSD) +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_SYS_DEFAULT +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO +FILEVERSION VER_FILEVERSION +PRODUCTVERSION VER_PRODUCTVERSION + +FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + +#ifndef _DEBUG + FILEFLAGS 0 +#else + #define VER_PRERELEASE VS_FF_PRERELEASE + #define VER_PRIVATEBUILD VS_FF_PRIVATEBUILD + #define VER_DEBUG 0 + FILEFLAGS (VER_PRIVATEBUILD|VER_PRERELEASE|VER_DEBUG) +#endif + +FILEOS VOS_NT_WINDOWS32 +FILETYPE VFT_APP + +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "080004b0" + BEGIN + VALUE "CompanyName", VER_COMPANYNAME_STR + VALUE "FileDescription", "TrinityCore Battle.net Server Daemon" + VALUE "FileVersion", VER_FILEVERSION_STR + VALUE "InternalName", "bnetserver" + VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR + VALUE "OriginalFilename", "bnetserver.exe" + VALUE "ProductName", "TrinityCore Battle.net Server" + VALUE "ProductVersion", VER_PRODUCTVERSION_STR + END + END + + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x800, 1200 + END +END +#endif diff --git a/src/server/bnetserver/resource.h b/src/server/bnetserver/resource.h new file mode 100644 index 00000000000..7dc5cb9ef7b --- /dev/null +++ b/src/server/bnetserver/resource.h @@ -0,0 +1,15 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by TrinityCore.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif -- cgit v1.2.3