diff options
Diffstat (limited to 'src')
18 files changed, 1197 insertions, 916 deletions
diff --git a/src/server/authserver/CMakeLists.txt b/src/server/authserver/CMakeLists.txt index b40b8c906f4..ae706973ff7 100644 --- a/src/server/authserver/CMakeLists.txt +++ b/src/server/authserver/CMakeLists.txt @@ -58,6 +58,7 @@ 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/Server/BattlenetBitStream.cpp b/src/server/authserver/Server/BattlenetBitStream.cpp index e46334fecf8..712c9e58f08 100644 --- a/src/server/authserver/Server/BattlenetBitStream.cpp +++ b/src/server/authserver/Server/BattlenetBitStream.cpp @@ -22,3 +22,9 @@ bool Battlenet::BitStream::Read<bool>(uint32 /*bitCount*/) { return Read<uint8>(1) != 0; } + +template<> +void Battlenet::BitStream::Write<bool>(bool value, uint32 /*bitCount*/) +{ + Write<uint8>(value ? 1 : 0, 1); +} diff --git a/src/server/authserver/Server/BattlenetBitStream.h b/src/server/authserver/Server/BattlenetBitStream.h index 6a5e366ede5..3601c3b0b0c 100644 --- a/src/server/authserver/Server/BattlenetBitStream.h +++ b/src/server/authserver/Server/BattlenetBitStream.h @@ -125,7 +125,7 @@ namespace Battlenet { static_assert(std::is_integral<T>::value || std::is_enum<T>::value, "T must be an integer type"); - if (_readPos + bitCount >= _writePos) + if (_readPos + bitCount > _writePos) throw BitStreamPositionException(true, bitCount, _readPos, _writePos); uint64 ret = 0; @@ -188,7 +188,7 @@ namespace Battlenet { static_assert(std::is_integral<T>::value || std::is_enum<T>::value, "T must be an integer type"); - if (_writePos + bitCount >= 8 * MaxSize) + if (_writePos + bitCount > 8 * MaxSize) throw BitStreamPositionException(false, bitCount, _writePos, MaxSize * 8); while (bitCount != 0) @@ -214,7 +214,7 @@ namespace Battlenet void SetReadPos(uint32 bits) { - if (bits >= _writePos) + if (bits > _writePos) throw BitStreamPositionException(true, bits, 0, _writePos); _readPos = bits; @@ -235,6 +235,9 @@ namespace Battlenet template<> bool BitStream::Read<bool>(uint32 bitCount); + + template<> + void BitStream::Write<bool>(bool value, uint32 bitCount); } #endif // __BATTLENETBITSTREAM_H__ diff --git a/src/server/authserver/Server/BattlenetPackets.cpp b/src/server/authserver/Server/BattlenetPackets.cpp deleted file mode 100644 index 8b3ba06ef0d..00000000000 --- a/src/server/authserver/Server/BattlenetPackets.cpp +++ /dev/null @@ -1,464 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "BattlenetPackets.h" -#include "Common.h" -#include "Util.h" -#include <limits> -#include <sstream> -#include <boost/lexical_cast.hpp> -#include <boost/asio/ip/address.hpp> - -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; -} - -void Battlenet::AuthChallenge::Read() -{ - Program = _stream.ReadFourCC(); - Platform = _stream.ReadFourCC(); - Locale = _stream.ReadFourCC(); - - Components.resize(_stream.Read<uint32>(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<uint32>(32); - } - - if (_stream.Read<uint32>(1)) - Login = _stream.ReadString(9, 3); -} - -std::string Battlenet::AuthChallenge::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::AuthChallenge 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::AuthChallenge Login: " << Login; - - return stream.str(); -} - -void Battlenet::AuthResumeInfo::Read() -{ - Program = _stream.ReadFourCC(); - Platform = _stream.ReadFourCC(); - Locale = _stream.ReadFourCC(); - - Components.resize(_stream.Read<uint32>(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<uint32>(32); - } - - Login = _stream.ReadString(9, 3); - Region = _stream.Read<uint8>(8); - GameAccountName = _stream.ReadString(5, 1); -} - -std::string Battlenet::AuthResumeInfo::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::AuthReconnect 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 << "Battlenet::AuthReconnect Login: " << Login; - stream << std::endl << "Battlenet::AuthReconnect Region: " << uint32(Region); - stream << std::endl << "Battlenet::AuthReconnect GameAccountName: " << GameAccountName; - - return stream.str(); -} - -Battlenet::ProofRequest::~ProofRequest() -{ - for (size_t i = 0; i < Modules.size(); ++i) - delete Modules[i]; -} - -void Battlenet::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::ProofRequest::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::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::ProofResponse::~ProofResponse() -{ - for (size_t i = 0; i < Modules.size(); ++i) - delete Modules[i]; -} - -void Battlenet::ProofResponse::Read() -{ - Modules.resize(_stream.Read<uint32>(3)); - for (size_t i = 0; i < Modules.size(); ++i) - { - BitStream*& dataStream = Modules[i]; - dataStream = new BitStream(_stream.Read<uint32>(10)); - memcpy(dataStream->GetBuffer(), _stream.ReadBytes(dataStream->GetSize()).get(), dataStream->GetSize()); - } -} - -std::string Battlenet::ProofResponse::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::ProofResponse Modules " << Modules.size(); - for (BitStream* module : Modules) - { - std::string hexStr = ByteArrayToHexStr(module->GetBuffer(), module->GetSize()); - stream << std::endl << "Battlenet::ProofResponse::ModuleData Size: " << module->GetSize() << ", Data: " << hexStr; - } - - return stream.str(); -} - -Battlenet::AuthComplete::~AuthComplete() -{ - for (ModuleInfo* m : Modules) - delete m; -} - -void Battlenet::AuthComplete::Write() -{ - _stream.Write(Result != 0, 1); - if (Result == 0) - { - _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<int32>::min(), 32); - _stream.Write(1, 1); - // if written == 1 - { - _stream.Write(1, 1); - // if written == 1 - { - _stream.Write(Threshold, 32); - _stream.Write(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(0, 64); - - _stream.Write(GameAccountRegion, 8); - _stream.WriteString(GameAccountName, 5, -1); - _stream.Write(GameAccountFlags, 64); - - _stream.Write(0, 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(ErrorType, 2); - if (ErrorType == 1) - { - _stream.Write(Result, 16); - _stream.Write(0x80000000, 32); - } - } -} - -std::string Battlenet::AuthComplete::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::AuthComplete AuthResult " << Result << " PingTimeout " << PingTimeout << " Threshold " << Threshold << " Rate " << Rate - << " FirstName " << FirstName << " LastName " << LastName << " AccountId " << AccountId << " Region " << uint32(Region) << " GameAccountName " << GameAccountName - << " GameAccountFlags " << GameAccountFlags << " 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::AuthComplete::SetAuthResult(AuthResult result) -{ - ErrorType = result != AUTH_OK ? 1 : 0; - Result = result; -} - -Battlenet::AuthResume::~AuthResume() -{ - for (ModuleInfo* m : Modules) - delete m; -} - -void Battlenet::AuthResume::Write() -{ - _stream.Write(Result != 0, 1); - if (Result == 0) - { - _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<int32>::min(), 32); - _stream.Write(1, 1); - // if written == 1 - { - _stream.Write(1, 1); - // if written == 1 - { - _stream.Write(Threshold, 32); - _stream.Write(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(ErrorType, 2); - if (ErrorType == 1) - { - _stream.Write(Result, 16); - _stream.Write(0x80000000, 32); - } - } -} - -std::string Battlenet::AuthResume::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::AuthResume AuthResult " << Result << " PingTimeout " << PingTimeout << " Threshold " << Threshold << " Rate " << 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::AuthResume::SetAuthResult(AuthResult result) -{ - ErrorType = result != AUTH_OK ? 1 : 0; - Result = result; -} - -Battlenet::RealmCharacterCounts::~RealmCharacterCounts() -{ - for (ServerPacket* realmData : RealmData) - delete realmData; -} - -void Battlenet::RealmCharacterCounts::Write() -{ - _stream.Write(false, 1); // failure - _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()); - } -} - -std::string Battlenet::RealmCharacterCounts::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::RealmCharacterCounts 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(); - - return stream.str().c_str(); -} - -void Battlenet::RealmUpdate::Write() -{ - _stream.Write(true, 1); // Success - _stream.Write(Type + -std::numeric_limits<int32>::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::RealmUpdate::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::RealmUpdate 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::RealmJoinRequest::Read() -{ - Realm.Battlegroup = _stream.Read<uint8>(8); - Realm.Index = _stream.Read<uint32>(32); - Realm.Region = _stream.Read<uint8>(8); - ClientSeed = _stream.Read<uint32>(32); -} - -std::string Battlenet::RealmJoinRequest::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::RealmJoinRequest ClientSeed " << ClientSeed << " Region " << uint32(Realm.Region) << " Battlegroup " << uint32(Realm.Battlegroup) << " Index " << Realm.Index; - return stream.str().c_str(); -} - -void Battlenet::RealmJoinResult::Write() -{ - _stream.Write(0, 27); - _stream.Write(0, 1); // Fail - _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); - } -} - -std::string Battlenet::RealmJoinResult::ToString() const -{ - std::ostringstream stream; - stream << "Battlenet::RealmJoinResult ServerSeed " << ServerSeed << " IPv4 Addresses " << IPv4.size() << " IPv6 Addresses " << IPv6.size(); - for (tcp::endpoint const& addr : IPv4) - stream << std::endl << "Battlenet::RealmJoinResult::Address " << boost::lexical_cast<std::string>(addr); - - for (tcp::endpoint const& addr : IPv6) - stream << std::endl << "Battlenet::RealmJoinResult::Address " << boost::lexical_cast<std::string>(addr); - - return stream.str().c_str(); -} diff --git a/src/server/authserver/Server/BattlenetPackets.h b/src/server/authserver/Server/BattlenetPackets.h deleted file mode 100644 index e5f046379f5..00000000000 --- a/src/server/authserver/Server/BattlenetPackets.h +++ /dev/null @@ -1,383 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef __BATTLENETPACKETS_H__ -#define __BATTLENETPACKETS_H__ - -#include "AuthCodes.h" -#include "BattlenetBitStream.h" -#include "BattlenetManager.h" -#include "Define.h" -#include "Errors.h" -#include <string> -#include <boost/asio/ip/tcp.hpp> - -using boost::asio::ip::tcp; - -namespace Battlenet -{ - class BitStream; - - enum Channel - { - AUTHENTICATION = 0, - CONNECTION = 1, - WOW = 2, - FRIEND = 3, - PRESENCE = 4, - CHAT = 5, - SUPPORT = 7, - ACHIEVEMENT = 8, - CACHE = 11, - PROFILE = 14 - }; - - enum AuthOpcode - { - CMSG_AUTH_CHALLENGE = 0x0, - CMSG_AUTH_RECONNECT = 0x1, - CMSG_AUTH_PROOF_RESPONSE = 0x2, - - SMSG_AUTH_COMPLETE = 0x0, - SMSG_AUTH_RESUME = 0x1, - SMSG_AUTH_PROOF_REQUEST = 0x2 - }; - - enum ConnectionOpcodes - { - CMSG_PING = 0x0, - CMSG_ENABLE_ENCRYPTION = 0x5, - CMSG_DISCONNECT = 0x6, - CMSG_INVALID_PACKET = 0x9, - - SMSG_PONG = 0x0 - }; - - enum WoWOpcodes - { - CMSG_REALM_UPDATE_SUBSCRIBE = 0x0, - CMSG_REALM_UPDATE_UNSUBSCRIBE = 0x1, - CMSG_JOIN_REQUEST = 0x8, - - SMSG_CHARACTER_COUNTS = 0x0, - SMSG_REALM_UPDATE = 0x2, - SMSG_REALM_UPDATE_END = 0x3, - SMSG_JOIN_RESULT = 0x8 - }; - - 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."); } - }; - - 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(); } - }; - - class AuthChallenge final : public ClientPacket - { - public: - AuthChallenge(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) - { - ASSERT(header == PacketHeader(CMSG_AUTH_CHALLENGE, AUTHENTICATION) && "Invalid packet header for AuthChallenge"); - } - - void Read() override; - std::string ToString() const override; - - std::string Program; - std::string Platform; - std::string Locale; - std::vector<Component> Components; - std::string Login; - }; - - class AuthResumeInfo final : public ClientPacket - { - public: - AuthResumeInfo(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) - { - ASSERT(header == PacketHeader(CMSG_AUTH_RECONNECT, AUTHENTICATION) && "Invalid packet header for AuthResumeInfo"); - } - - void Read() override; - std::string ToString() const override; - - std::string Program; - std::string Platform; - std::string Locale; - std::vector<Component> Components; - std::string Login; - uint8 Region; - std::string GameAccountName; - }; - - class ProofRequest final : public ServerPacket - { - public: - ProofRequest() : ServerPacket(PacketHeader(SMSG_AUTH_PROOF_REQUEST, AUTHENTICATION)) { } - ~ProofRequest(); - - void Write() override; - std::string ToString() const override; - - std::vector<ModuleInfo*> Modules; - }; - - class ProofResponse final : public ClientPacket - { - public: - ProofResponse(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) - { - ASSERT(header == PacketHeader(CMSG_AUTH_PROOF_RESPONSE, AUTHENTICATION) && "Invalid packet header for ProofResponse"); - } - - ~ProofResponse(); - - void Read() override; - std::string ToString() const override; - - std::vector<BitStream*> Modules; - }; - - class AuthComplete final : public ServerPacket - { - public: - AuthComplete() : ServerPacket(PacketHeader(SMSG_AUTH_COMPLETE, AUTHENTICATION)), - Result(AUTH_OK), ErrorType(0), PingTimeout(120000), Threshold(25000000), Rate(1000), - FirstName(""), LastName(""), AccountId(0), Region(2), GameAccountRegion(2), GameAccountName("") - { - } - - ~AuthComplete(); - - void Write() override; - std::string ToString() const override; - - std::vector<ModuleInfo*> Modules; - void SetAuthResult(AuthResult result); - AuthResult Result; - uint32 ErrorType; - - int32 PingTimeout; - uint32 Threshold; - uint32 Rate; - std::string FirstName; - std::string LastName; - uint32 AccountId; - uint8 Region; - uint8 GameAccountRegion; - std::string GameAccountName; - uint64 GameAccountFlags; - }; - - class AuthResume final : public ServerPacket - { - public: - AuthResume() : ServerPacket(PacketHeader(SMSG_AUTH_RESUME, AUTHENTICATION)), - Result(AUTH_OK), ErrorType(0), PingTimeout(120000), Threshold(25000000), Rate(1000) - { - } - - ~AuthResume(); - - void Write() override; - std::string ToString() const override; - - std::vector<ModuleInfo*> Modules; - void SetAuthResult(AuthResult result); - AuthResult Result; - uint32 ErrorType; - - int32 PingTimeout; - uint32 Threshold; - uint32 Rate; - }; - - class Pong final : public ServerPacket - { - public: - Pong() : ServerPacket(PacketHeader(SMSG_PONG, CONNECTION)) - { - } - - void Write() override { } - std::string ToString() const override { return "Battlenet::Pong"; } - }; - - class RealmCharacterCounts final : public ServerPacket - { - public: - RealmCharacterCounts() : ServerPacket(PacketHeader(SMSG_CHARACTER_COUNTS, WOW)) - { - } - ~RealmCharacterCounts(); - - struct CharacterCountEntry - { - RealmId Realm; - uint32 CharacterCount; - }; - - void Write() override; - std::string ToString() const override; - - std::vector<CharacterCountEntry> CharacterCounts; - std::vector<ServerPacket*> RealmData; - }; - - class RealmUpdate final : public ServerPacket - { - public: - RealmUpdate() : ServerPacket(PacketHeader(SMSG_REALM_UPDATE, WOW)), - Timezone(0), Population(0.0f), Lock(0), Type(0), Name(""), Version(""), - Address(), Flags(0), Region(0), Battlegroup(0), Index(0), Build(0) - { - } - - void Write() override; - std::string ToString() const override; - - 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 RealmUpdateComplete final : public ServerPacket - { - public: - RealmUpdateComplete() : ServerPacket(PacketHeader(SMSG_REALM_UPDATE_END, WOW)) - { - } - - void Write() override { } - std::string ToString() const override { return "Battlenet::RealmUpdateComplete"; } - }; - - class RealmJoinRequest final : public ClientPacket - { - public: - RealmJoinRequest(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream) - { - ASSERT(header == PacketHeader(CMSG_JOIN_REQUEST, WOW) && "Invalid packet header for RealmJoinRequest"); - } - - void Read() override; - std::string ToString() const override; - - uint32 ClientSeed; - uint32 Unknown; - RealmId Realm; - }; - - class RealmJoinResult final : public ServerPacket - { - public: - RealmJoinResult() : ServerPacket(PacketHeader(SMSG_JOIN_RESULT, WOW)), ServerSeed(0) - { - } - - void Write() override; - std::string ToString() const override; - - uint32 ServerSeed; - std::vector<tcp::endpoint> IPv4; - std::vector<tcp::endpoint> IPv6; - }; -} - -namespace boost -{ - namespace asio - { - inline const_buffers_1 buffer(Battlenet::ServerPacket const* packet) - { - return buffer(packet->GetData(), packet->GetSize()); - } - } -} - -#endif // __BATTLENETPACKETS_H__ diff --git a/src/server/authserver/Server/BattlenetPackets/AuthenticationPackets.cpp b/src/server/authserver/Server/BattlenetPackets/AuthenticationPackets.cpp new file mode 100644 index 00000000000..58560e663de --- /dev/null +++ b/src/server/authserver/Server/BattlenetPackets/AuthenticationPackets.cpp @@ -0,0 +1,304 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "AuthenticationPackets.h" +#include "Util.h" + +void Battlenet::Authentication::LogonRequest::Read() +{ + Program = _stream.ReadFourCC(); + Platform = _stream.ReadFourCC(); + Locale = _stream.ReadFourCC(); + + Components.resize(_stream.Read<uint32>(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<uint32>(32); + } + + if (_stream.Read<uint32>(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::ResumeRequest::Read() +{ + Program = _stream.ReadFourCC(); + Platform = _stream.ReadFourCC(); + Locale = _stream.ReadFourCC(); + + Components.resize(_stream.Read<uint32>(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<uint32>(32); + } + + Login = _stream.ReadString(9, 3); + Region = _stream.Read<uint8>(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 << "Battlenet::Authentication::ResumeRequest Login: " << Login; + stream << std::endl << "Battlenet::Authentication::ResumeRequest Region: " << uint32(Region); + stream << std::endl << "Battlenet::Authentication::ResumeRequest GameAccountName: " << GameAccountName; + + return stream.str(); +} + +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<uint32>(3)); + for (size_t i = 0; i < Modules.size(); ++i) + { + BitStream*& dataStream = Modules[i]; + dataStream = new BitStream(_stream.Read<uint32>(10)); + memcpy(dataStream->GetBuffer(), _stream.ReadBytes(dataStream->GetSize()).get(), dataStream->GetSize()); + } +} + +std::string Battlenet::Authentication::ProofResponse::ToString() const +{ + std::ostringstream stream; + stream << "Battlenet::Authentication::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(); +} + +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<int32>::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<int32>::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<int32>::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<int32>::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/authserver/Server/BattlenetPackets/AuthenticationPackets.h b/src/server/authserver/Server/BattlenetPackets/AuthenticationPackets.h new file mode 100644 index 00000000000..5f079db65b3 --- /dev/null +++ b/src/server/authserver/Server/BattlenetPackets/AuthenticationPackets.h @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef AuthenticationPackets_h__ +#define AuthenticationPackets_h__ + +#include "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; + + std::string Program; + std::string Platform; + std::string Locale; + std::vector<Component> 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; + + std::string Program; + std::string Platform; + std::string Locale; + std::vector<Component> 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; + + std::vector<BitStream*> 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<ModuleInfo*> 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<ModuleInfo*> 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<ModuleInfo*> 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 new file mode 100644 index 00000000000..15c609b3ba4 --- /dev/null +++ b/src/server/authserver/Server/BattlenetPackets/BattlenetPackets.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef BattlenetPackets_h__ +#define BattlenetPackets_h__ + +#include "AuthenticationPackets.h" +#include "ConnectionPackets.h" +#include "WoWRealmPackets.h" + +#endif // BattlenetPackets_h__ diff --git a/src/server/authserver/Server/BattlenetPackets/BattlenetPacketsBase.cpp b/src/server/authserver/Server/BattlenetPackets/BattlenetPacketsBase.cpp new file mode 100644 index 00000000000..034bb8ba0a4 --- /dev/null +++ b/src/server/authserver/Server/BattlenetPackets/BattlenetPacketsBase.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "BattlenetPackets.h" +#include <sstream> + +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 new file mode 100644 index 00000000000..af02eb91f43 --- /dev/null +++ b/src/server/authserver/Server/BattlenetPackets/BattlenetPacketsBase.h @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef BattlenetPacketsBase_h__ +#define BattlenetPacketsBase_h__ + +#include "AuthCodes.h" +#include "BattlenetBitStream.h" +#include "BattlenetManager.h" +#include "Define.h" +#include "Errors.h" +#include <string> +#include <boost/asio/ip/tcp.hpp> + +using boost::asio::ip::tcp; + +namespace Battlenet +{ + class BitStream; + + enum Channel + { + AUTHENTICATION = 0, + CONNECTION = 1, + WOWREALM = 2, + FRIEND = 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."); } + }; + + 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/ConnectionPackets.cpp b/src/server/authserver/Server/BattlenetPackets/ConnectionPackets.cpp new file mode 100644 index 00000000000..9f53961c6ab --- /dev/null +++ b/src/server/authserver/Server/BattlenetPackets/ConnectionPackets.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "ConnectionPackets.h" + +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 new file mode 100644 index 00000000000..50ec9416ec1 --- /dev/null +++ b/src/server/authserver/Server/BattlenetPackets/ConnectionPackets.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef ConnectionPackets_h__ +#define ConnectionPackets_h__ + +#include "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 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/WoWRealmPackets.cpp b/src/server/authserver/Server/BattlenetPackets/WoWRealmPackets.cpp new file mode 100644 index 00000000000..c1341e18c7d --- /dev/null +++ b/src/server/authserver/Server/BattlenetPackets/WoWRealmPackets.cpp @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "WoWRealmPackets.h" +#include <boost/lexical_cast.hpp> +#include <boost/asio/ip/address.hpp> + +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<int32>::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<uint8>(8); + Realm.Index = _stream.Read<uint32>(32); + Realm.Region = _stream.Read<uint8>(8); + ClientSeed = _stream.Read<uint32>(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::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<std::string>(addr); + + for (tcp::endpoint const& addr : IPv6) + stream << std::endl << "Battlenet::WoWRealm::JoinResponseV2::Address " << boost::lexical_cast<std::string>(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 new file mode 100644 index 00000000000..881ddd3186a --- /dev/null +++ b/src/server/authserver/Server/BattlenetPackets/WoWRealmPackets.h @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef WoWRealmPackets_h__ +#define WoWRealmPackets_h__ + +#include "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 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; + + 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<CharacterCountEntry> CharacterCounts; + std::vector<ServerPacket*> 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<tcp::endpoint> IPv4; + std::vector<tcp::endpoint> IPv6; + }; + } +} + +#endif // WoWRealmPackets_h__ diff --git a/src/server/authserver/Server/BattlenetSession.cpp b/src/server/authserver/Server/BattlenetSession.cpp index 7abb9df9db9..2242a3ee4eb 100644 --- a/src/server/authserver/Server/BattlenetSession.cpp +++ b/src/server/authserver/Server/BattlenetSession.cpp @@ -30,16 +30,16 @@ std::map<Battlenet::PacketHeader, Battlenet::Session::PacketHandler> InitHandler { std::map<Battlenet::PacketHeader, Battlenet::Session::PacketHandler> handlers; - handlers[Battlenet::PacketHeader(Battlenet::CMSG_AUTH_CHALLENGE, Battlenet::AUTHENTICATION)] = &Battlenet::Session::HandleAuthChallenge; - handlers[Battlenet::PacketHeader(Battlenet::CMSG_AUTH_RECONNECT, Battlenet::AUTHENTICATION)] = &Battlenet::Session::HandleAuthReconnect; - handlers[Battlenet::PacketHeader(Battlenet::CMSG_AUTH_PROOF_RESPONSE, Battlenet::AUTHENTICATION)] = &Battlenet::Session::HandleAuthProofResponse; + handlers[Battlenet::PacketHeader(Battlenet::Authentication::CMSG_LOGON_REQUEST, Battlenet::AUTHENTICATION)] = &Battlenet::Session::HandleLogonRequest; + handlers[Battlenet::PacketHeader(Battlenet::Authentication::CMSG_RESUME_REQUEST, Battlenet::AUTHENTICATION)] = &Battlenet::Session::HandleResumeRequest; + handlers[Battlenet::PacketHeader(Battlenet::Authentication::CMSG_PROOF_RESPONSE, Battlenet::AUTHENTICATION)] = &Battlenet::Session::HandleProofResponse; - handlers[Battlenet::PacketHeader(Battlenet::CMSG_PING, Battlenet::CONNECTION)] = &Battlenet::Session::HandlePing; - handlers[Battlenet::PacketHeader(Battlenet::CMSG_ENABLE_ENCRYPTION, Battlenet::CONNECTION)] = &Battlenet::Session::HandleEnableEncryption; - handlers[Battlenet::PacketHeader(Battlenet::CMSG_DISCONNECT, Battlenet::CONNECTION)] = &Battlenet::Session::HandleDisconnect; + handlers[Battlenet::PacketHeader(Battlenet::Connection::CMSG_PING, Battlenet::CONNECTION)] = &Battlenet::Session::HandlePing; + handlers[Battlenet::PacketHeader(Battlenet::Connection::CMSG_ENABLE_ENCRYPTION, Battlenet::CONNECTION)] = &Battlenet::Session::HandleEnableEncryption; + handlers[Battlenet::PacketHeader(Battlenet::Connection::CMSG_LOGOUT_REQUEST, Battlenet::CONNECTION)] = &Battlenet::Session::HandleLogoutRequest; - handlers[Battlenet::PacketHeader(Battlenet::CMSG_REALM_UPDATE_SUBSCRIBE, Battlenet::WOW)] = &Battlenet::Session::HandleRealmUpdateSubscribe; - handlers[Battlenet::PacketHeader(Battlenet::CMSG_JOIN_REQUEST, Battlenet::WOW)] = &Battlenet::Session::HandleRealmJoinRequest; + handlers[Battlenet::PacketHeader(Battlenet::WoWRealm::CMSG_LIST_SUBSCRIBE_REQUEST, Battlenet::WOWREALM)] = &Battlenet::Session::HandleListSubscribeRequest; + handlers[Battlenet::PacketHeader(Battlenet::WoWRealm::CMSG_JOIN_REQUEST_V2, Battlenet::WOWREALM)] = &Battlenet::Session::HandleJoinRequestV2; return handlers; } @@ -109,7 +109,7 @@ void Battlenet::Session::_SetVSFields(std::string const& pstr) LoginDatabase.Execute(stmt); } -bool Battlenet::Session::HandleAuthChallenge(PacketHeader& header, BitStream& packet) +bool Battlenet::Session::HandleLogonRequest(PacketHeader& header, BitStream& packet) { // Verify that this IP is not in the ip_banned table LoginDatabase.Execute(LoginDatabase.GetPreparedStatement(LOGIN_DEL_EXPIRED_IP_BANS)); @@ -119,19 +119,19 @@ bool Battlenet::Session::HandleAuthChallenge(PacketHeader& header, BitStream& pa stmt->setString(0, ip_address); if (PreparedQueryResult result = LoginDatabase.Query(stmt)) { - AuthComplete* complete = new AuthComplete(); + 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 true; } - AuthChallenge info(header, packet); + Authentication::LogonRequest info(header, packet); info.Read(); if (info.Program != "WoW") { - AuthComplete* complete = new AuthComplete(); + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); complete->SetAuthResult(AUTH_INVALID_PROGRAM); AsyncWrite(complete); return true; @@ -139,7 +139,7 @@ bool Battlenet::Session::HandleAuthChallenge(PacketHeader& header, BitStream& pa if (!sBattlenetMgr->HasPlatform(info.Platform)) { - AuthComplete* complete = new AuthComplete(); + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); complete->SetAuthResult(AUTH_INVALID_OS); AsyncWrite(complete); return true; @@ -147,7 +147,7 @@ bool Battlenet::Session::HandleAuthChallenge(PacketHeader& header, BitStream& pa if (!sBattlenetMgr->HasPlatform(info.Locale)) { - AuthComplete* complete = new AuthComplete(); + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); complete->SetAuthResult(AUTH_UNSUPPORTED_LANGUAGE); AsyncWrite(complete); return true; @@ -157,7 +157,7 @@ bool Battlenet::Session::HandleAuthChallenge(PacketHeader& header, BitStream& pa { if (!sBattlenetMgr->HasComponent(&component)) { - AuthComplete* complete = new AuthComplete(); + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); if (!sBattlenetMgr->HasProgram(component.Program)) complete->SetAuthResult(AUTH_INVALID_PROGRAM); else if (!sBattlenetMgr->HasPlatform(component.Platform)) @@ -189,7 +189,7 @@ bool Battlenet::Session::HandleAuthChallenge(PacketHeader& header, BitStream& pa PreparedQueryResult result = LoginDatabase.Query(stmt); if (!result) { - AuthComplete* complete = new AuthComplete(); + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); complete->SetAuthResult(AUTH_UNKNOWN_ACCOUNT); AsyncWrite(complete); return true; @@ -206,7 +206,7 @@ bool Battlenet::Session::HandleAuthChallenge(PacketHeader& header, BitStream& pa if (strcmp(fields[4].GetCString(), ip_address.c_str()) != 0) { - AuthComplete* complete = new AuthComplete(); + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); complete->SetAuthResult(AUTH_ACCOUNT_LOCKED); AsyncWrite(complete); return true; @@ -231,7 +231,7 @@ bool Battlenet::Session::HandleAuthChallenge(PacketHeader& header, BitStream& pa 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) { - AuthComplete* complete = new AuthComplete(); + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); complete->SetAuthResult(AUTH_ACCOUNT_LOCKED); AsyncWrite(complete); return true; @@ -252,7 +252,7 @@ bool Battlenet::Session::HandleAuthChallenge(PacketHeader& header, BitStream& pa Field* fields = banresult->Fetch(); if (fields[0].GetUInt32() == fields[1].GetUInt32()) { - AuthComplete* complete = new AuthComplete(); + 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()); @@ -260,7 +260,7 @@ bool Battlenet::Session::HandleAuthChallenge(PacketHeader& header, BitStream& pa } else { - AuthComplete* complete = new AuthComplete(); + 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()); @@ -309,7 +309,7 @@ bool Battlenet::Session::HandleAuthChallenge(PacketHeader& header, BitStream& pa _modulesWaitingForData.push(MODULE_PASSWORD); - ProofRequest* request = new ProofRequest(); + Authentication::ProofRequest* request = new Authentication::ProofRequest(); request->Modules.push_back(password); // if has authenticator, send Token module request->Modules.push_back(thumbprint); @@ -317,9 +317,9 @@ bool Battlenet::Session::HandleAuthChallenge(PacketHeader& header, BitStream& pa return true; } -bool Battlenet::Session::HandleAuthReconnect(PacketHeader& header, BitStream& packet) +bool Battlenet::Session::HandleResumeRequest(PacketHeader& header, BitStream& packet) { - AuthResumeInfo reconnect(header, packet); + Authentication::ResumeRequest reconnect(header, packet); reconnect.Read(); TC_LOG_DEBUG("server.battlenet", "%s", reconnect.ToString().c_str()); @@ -338,7 +338,7 @@ bool Battlenet::Session::HandleAuthReconnect(PacketHeader& header, BitStream& pa PreparedQueryResult result = LoginDatabase.Query(stmt); if (!result) { - AuthResume* resume = new AuthResume(); + Authentication::ResumeResponse* resume = new Authentication::ResumeResponse(); resume->SetAuthResult(AUTH_UNKNOWN_ACCOUNT); AsyncWrite(resume); return false; @@ -366,21 +366,21 @@ bool Battlenet::Session::HandleAuthReconnect(PacketHeader& header, BitStream& pa _modulesWaitingForData.push(MODULE_RESUME); - ProofRequest* request = new ProofRequest(); + Authentication::ProofRequest* request = new Authentication::ProofRequest(); request->Modules.push_back(thumbprint); request->Modules.push_back(resume); AsyncWrite(request); return true; } -bool Battlenet::Session::HandleAuthProofResponse(PacketHeader& header, BitStream& packet) +bool Battlenet::Session::HandleProofResponse(PacketHeader& header, BitStream& packet) { - ProofResponse proof(header, packet); + Authentication::ProofResponse proof(header, packet); proof.Read(); if (_modulesWaitingForData.size() < proof.Modules.size()) { - AuthComplete* complete = new AuthComplete(); + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); complete->SetAuthResult(AUTH_CORRUPTED_MODULE); AsyncWrite(complete); return true; @@ -397,8 +397,8 @@ bool Battlenet::Session::HandleAuthProofResponse(PacketHeader& header, BitStream if (!response) { - response = new AuthComplete(); - static_cast<AuthComplete*>(response)->SetAuthResult(AUTH_INTERNAL_ERROR); + response = new Authentication::LogonResponse(); + static_cast<Authentication::LogonResponse*>(response)->SetAuthResult(AUTH_INTERNAL_ERROR); } AsyncWrite(response); @@ -407,7 +407,7 @@ bool Battlenet::Session::HandleAuthProofResponse(PacketHeader& header, BitStream bool Battlenet::Session::HandlePing(PacketHeader& /*header*/, BitStream& /*packet*/) { - AsyncWrite(new Pong()); + AsyncWrite(new Connection::Pong()); return true; } @@ -417,7 +417,7 @@ bool Battlenet::Session::HandleEnableEncryption(PacketHeader& /*header*/, BitStr return true; } -bool Battlenet::Session::HandleDisconnect(PacketHeader& /*header*/, BitStream& /*packet*/) +bool Battlenet::Session::HandleLogoutRequest(PacketHeader& /*header*/, BitStream& /*packet*/) { PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_SESSION_KEY); stmt->setString(0, ""); @@ -427,11 +427,11 @@ bool Battlenet::Session::HandleDisconnect(PacketHeader& /*header*/, BitStream& / return true; } -bool Battlenet::Session::HandleRealmUpdateSubscribe(PacketHeader& /*header*/, BitStream& /*packet*/) +bool Battlenet::Session::HandleListSubscribeRequest(PacketHeader& /*header*/, BitStream& /*packet*/) { sRealmList->UpdateIfNeed(); - RealmCharacterCounts* counts = new RealmCharacterCounts(); + WoWRealm::ListSubscribeResponse* counts = new WoWRealm::ListSubscribeResponse(); PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_CHARACTER_COUNTS); stmt->setUInt32(0, _gameAccountId); @@ -463,7 +463,7 @@ bool Battlenet::Session::HandleRealmUpdateSubscribe(PacketHeader& /*header*/, Bi if (!buildInfo) flag &= ~REALM_FLAG_SPECIFYBUILD; - RealmUpdate* update = new RealmUpdate(); + WoWRealm::ListUpdate* update = new WoWRealm::ListUpdate(); update->Timezone = realm.timezone; update->Population = realm.populationLevel; update->Lock = (realm.allowedSecurityLevel > _accountSecurityLevel) ? 1 : 0; @@ -488,21 +488,22 @@ bool Battlenet::Session::HandleRealmUpdateSubscribe(PacketHeader& /*header*/, Bi counts->RealmData.push_back(update); } - counts->RealmData.push_back(new RealmUpdateComplete()); + counts->RealmData.push_back(new WoWRealm::ListComplete()); AsyncWrite(counts); return true; } -bool Battlenet::Session::HandleRealmJoinRequest(PacketHeader& header, BitStream& packet) +bool Battlenet::Session::HandleJoinRequestV2(PacketHeader& header, BitStream& packet) { - RealmJoinRequest join(header, packet); + WoWRealm::JoinRequestV2 join(header, packet); join.Read(); - RealmJoinResult* result = new RealmJoinResult(); + 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 true; } @@ -626,7 +627,7 @@ bool Battlenet::Session::HandlePasswordModule(BitStream* dataStream, ServerPacke { if (dataStream->GetSize() != 1 + 128 + 32 + 128) { - AuthComplete* complete = new AuthComplete(); + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); complete->SetAuthResult(AUTH_CORRUPTED_MODULE); ReplaceResponse(response, complete); return false; @@ -634,7 +635,7 @@ bool Battlenet::Session::HandlePasswordModule(BitStream* dataStream, ServerPacke if (dataStream->Read<uint8>(8) != 2) // State { - AuthComplete* complete = new AuthComplete(); + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); complete->SetAuthResult(AUTH_CORRUPTED_MODULE); ReplaceResponse(response, complete); return false; @@ -648,7 +649,7 @@ bool Battlenet::Session::HandlePasswordModule(BitStream* dataStream, ServerPacke if (A.isZero()) { - AuthComplete* complete = new AuthComplete(); + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); complete->SetAuthResult(AUTH_CORRUPTED_MODULE); ReplaceResponse(response, complete); return false; @@ -720,7 +721,11 @@ bool Battlenet::Session::HandlePasswordModule(BitStream* dataStream, ServerPacke if (memcmp(M1.AsByteArray().get(), clientM1.AsByteArray().get(), 32)) { - AuthComplete* complete = new AuthComplete(); + 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; @@ -735,7 +740,7 @@ bool Battlenet::Session::HandlePasswordModule(BitStream* dataStream, ServerPacke if (!numAccounts) { - AuthComplete* noAccounts = new AuthComplete(); + Authentication::LogonResponse* noAccounts = new Authentication::LogonResponse(); noAccounts->SetAuthResult(LOGIN_NO_GAME_ACCOUNT); ReplaceResponse(response, noAccounts); return false; @@ -767,7 +772,7 @@ bool Battlenet::Session::HandlePasswordModule(BitStream* dataStream, ServerPacke password->Data = new uint8[password->DataSize]; memcpy(password->Data, stream.GetBuffer(), password->DataSize); - ProofRequest* request = new ProofRequest(); + Authentication::ProofRequest* request = new Authentication::ProofRequest(); request->Modules.push_back(password); if (numAccounts > 1) { @@ -802,7 +807,7 @@ bool Battlenet::Session::HandlePasswordModule(BitStream* dataStream, ServerPacke { delete request; - AuthComplete* complete = new AuthComplete(); + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); if (fields[2].GetUInt32() == fields[3].GetUInt32()) { complete->SetAuthResult(LOGIN_BANNED); @@ -833,7 +838,7 @@ bool Battlenet::Session::HandleSelectGameAccountModule(BitStream* dataStream, Se { if (dataStream->Read<uint8>(8) != 1) { - AuthComplete* complete = new AuthComplete(); + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); complete->SetAuthResult(AUTH_CORRUPTED_MODULE); ReplaceResponse(response, complete); return false; @@ -843,7 +848,7 @@ bool Battlenet::Session::HandleSelectGameAccountModule(BitStream* dataStream, Se std::string account = dataStream->ReadString(8); if (account.empty()) { - AuthComplete* complete = new AuthComplete(); + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); complete->SetAuthResult(LOGIN_NO_GAME_ACCOUNT); ReplaceResponse(response, complete); return false; @@ -865,7 +870,7 @@ bool Battlenet::Session::HandleSelectGameAccountModule(BitStream* dataStream, Se PreparedQueryResult result = LoginDatabase.Query(stmt); if (!result) { - AuthComplete* complete = new AuthComplete(); + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); complete->SetAuthResult(LOGIN_NO_GAME_ACCOUNT); ReplaceResponse(response, complete); return false; @@ -874,7 +879,7 @@ bool Battlenet::Session::HandleSelectGameAccountModule(BitStream* dataStream, Se Field* fields = result->Fetch(); if (fields[4].GetBool()) { - AuthComplete* complete = new AuthComplete(); + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); if (fields[2].GetUInt32() == fields[3].GetUInt32()) { complete->SetAuthResult(LOGIN_BANNED); @@ -893,7 +898,7 @@ bool Battlenet::Session::HandleSelectGameAccountModule(BitStream* dataStream, Se _gameAccountId = fields[0].GetUInt32(); _gameAccountName = fields[1].GetString(); - ProofRequest* request = new ProofRequest(); + Authentication::ProofRequest* request = new Authentication::ProofRequest(); request->Modules.push_back(sBattlenetMgr->CreateModule(_os, "RiskFingerprint")); ReplaceResponse(response, request); @@ -903,16 +908,20 @@ bool Battlenet::Session::HandleSelectGameAccountModule(BitStream* dataStream, Se bool Battlenet::Session::HandleRiskFingerprintModule(BitStream* dataStream, ServerPacket** response) { - AuthComplete* complete = new AuthComplete(); + Authentication::LogonResponse* complete = new Authentication::LogonResponse(); if (dataStream->Read<uint8>(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(); - PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_LAST_LOGIN_INFO); + stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_LAST_LOGIN_INFO); stmt->setString(0, GetRemoteIpAddress().to_string()); stmt->setUInt8(1, GetLocaleByName(_locale)); stmt->setString(2, _os); @@ -941,7 +950,7 @@ bool Battlenet::Session::HandleResumeModule(BitStream* dataStream, ServerPacket* { if (dataStream->Read<uint8>(8) != 1) { - AuthResume* complete = new AuthResume(); + Authentication::ResumeResponse* complete = new Authentication::ResumeResponse(); complete->SetAuthResult(AUTH_CORRUPTED_MODULE); ReplaceResponse(response, complete); return false; @@ -981,8 +990,12 @@ bool Battlenet::Session::HandleResumeModule(BitStream* dataStream, ServerPacket* 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!"); - AuthResume* result = new AuthResume(); + Authentication::ResumeResponse* result = new Authentication::ResumeResponse(); result->SetAuthResult(AUTH_UNKNOWN_ACCOUNT); ReplaceResponse(response, result); return false; @@ -1011,7 +1024,7 @@ bool Battlenet::Session::HandleResumeModule(BitStream* dataStream, ServerPacket* resume->Data = new uint8[resume->DataSize]; memcpy(resume->Data, resumeData.GetBuffer(), resume->DataSize); - AuthResume* result = new AuthResume(); + Authentication::ResumeResponse* result = new Authentication::ResumeResponse(); result->Modules.push_back(resume); ReplaceResponse(response, result); _authed = true; @@ -1021,7 +1034,7 @@ bool Battlenet::Session::HandleResumeModule(BitStream* dataStream, ServerPacket* bool Battlenet::Session::UnhandledModule(BitStream* /*dataStream*/, ServerPacket** response) { - AuthComplete* complete = new AuthComplete(); + 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 index 2e6c32cbabf..c3e4afee19b 100644 --- a/src/server/authserver/Server/BattlenetSession.h +++ b/src/server/authserver/Server/BattlenetSession.h @@ -61,19 +61,19 @@ namespace Battlenet typedef bool(Session::*PacketHandler)(PacketHeader& socket, BitStream& packet); - // Auth - bool HandleAuthChallenge(PacketHeader& header, BitStream& packet); - bool HandleAuthReconnect(PacketHeader& header, BitStream& packet); - bool HandleAuthProofResponse(PacketHeader& header, BitStream& packet); + // Authentication + bool HandleLogonRequest(PacketHeader& header, BitStream& packet); + bool HandleResumeRequest(PacketHeader& header, BitStream& packet); + bool HandleProofResponse(PacketHeader& header, BitStream& packet); - // Creep + // Connection bool HandlePing(PacketHeader& header, BitStream& packet); bool HandleEnableEncryption(PacketHeader& header, BitStream& packet); - bool HandleDisconnect(PacketHeader& header, BitStream& packet); + bool HandleLogoutRequest(PacketHeader& header, BitStream& packet); - // WoW - bool HandleRealmUpdateSubscribe(PacketHeader& header, BitStream& packet); - bool HandleRealmJoinRequest(PacketHeader& header, BitStream& packet); + // WoWRealm + bool HandleListSubscribeRequest(PacketHeader& header, BitStream& packet); + bool HandleJoinRequestV2(PacketHeader& header, BitStream& packet); void Start() override; diff --git a/src/server/shared/Database/Implementation/LoginDatabase.cpp b/src/server/shared/Database/Implementation/LoginDatabase.cpp index 6189ed4495f..2bdbc70933d 100644 --- a/src/server/shared/Database/Implementation/LoginDatabase.cpp +++ b/src/server/shared/Database/Implementation/LoginDatabase.cpp @@ -121,6 +121,8 @@ void LoginDatabaseConnection::DoPrepareStatements() PrepareStatement(LOGIN_SEL_BNET_GAME_ACCOUNTS, "SELECT a.id, a.username, ab.bandate, ab.unbandate, ab.active FROM account a LEFT JOIN account_banned ab ON a.id = ab.id WHERE battlenet_account = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_BNET_GAME_ACCOUNT, "SELECT a.id, a.username, ab.bandate, ab.unbandate, ab.active FROM account a LEFT JOIN account_banned ab ON a.id = ab.id WHERE username = ? AND battlenet_account = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_BNET_GAME_ACCOUNT_UNNAMED, "SELECT a.id, a.username, ab.bandate, ab.unbandate, ab.active FROM account a LEFT JOIN account_banned ab ON a.id = ab.id WHERE battlenet_index = ? AND battlenet_account = ?", CONNECTION_SYNCH); + PrepareStatement(LOGIN_SEL_BNET_FAILED_LOGINS, "SELECT failed_logins FROM battlenet_accounts WHERE id = ?", CONNECTION_SYNCH); + PrepareStatement(LOGIN_UPD_BNET_FAILED_LOGINS, "UPDATE battlenet_accounts SET failed_logins = failed_logins + 1 WHERE email = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_UPD_BNET_LAST_LOGIN_INFO, "UPDATE battlenet_accounts SET last_ip = ?, last_login = NOW(), locale = ?, failed_logins = 0, os = ? WHERE id = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_SEL_BNET_CHARACTER_COUNTS, "SELECT rc.numchars, r.id, r.Region, r.Battlegroup, r.gamebuild FROM realmcharacters rc INNER JOIN realmlist r ON rc.realmid = r.id WHERE rc.acctid = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_INS_BNET_ACCOUNT, "INSERT INTO battlenet_accounts (`email`,`sha_pass_hash`) VALUES (?, ?)", CONNECTION_ASYNC); diff --git a/src/server/shared/Database/Implementation/LoginDatabase.h b/src/server/shared/Database/Implementation/LoginDatabase.h index 8c1cc642835..c1816784f07 100644 --- a/src/server/shared/Database/Implementation/LoginDatabase.h +++ b/src/server/shared/Database/Implementation/LoginDatabase.h @@ -137,6 +137,8 @@ enum LoginDatabaseStatements LOGIN_SEL_BNET_GAME_ACCOUNTS, LOGIN_SEL_BNET_GAME_ACCOUNT, LOGIN_SEL_BNET_GAME_ACCOUNT_UNNAMED, + LOGIN_SEL_BNET_FAILED_LOGINS, + LOGIN_UPD_BNET_FAILED_LOGINS, LOGIN_UPD_BNET_LAST_LOGIN_INFO, LOGIN_SEL_BNET_CHARACTER_COUNTS, LOGIN_INS_BNET_ACCOUNT, |