56std::array<uint8, 32>
const WorldSocket::AuthCheckSeed = { 0xDE, 0x3A, 0x2A, 0x8E, 0x6B, 0x89, 0x52, 0x66, 0x88, 0x9D, 0x7E, 0x7A, 0x77, 0x1D, 0x5D, 0x1F,
57 0x4E, 0xD9, 0x0C, 0x23, 0x9B, 0xCD, 0x0E, 0xDC, 0xD2, 0xE8, 0x04, 0x3A, 0x68, 0x64, 0xC7, 0xB0 };
58std::array<uint8, 32>
const WorldSocket::SessionKeySeed = { 0xE8, 0x1E, 0x8B, 0x59, 0x27, 0x62, 0x1E, 0xAA, 0x86, 0x15, 0x18, 0xEA, 0xC0, 0xBF, 0x66, 0x8C,
59 0x6D, 0xBF, 0x83, 0x93, 0xBC, 0xAA, 0x80, 0x52, 0x5B, 0x1E, 0xDC, 0x23, 0xA0, 0x12, 0xB7, 0x50 };
60std::array<uint8, 32>
const WorldSocket::ContinuedSessionSeed = { 0x56, 0x5C, 0x61, 0x9C, 0x48, 0x3A, 0x52, 0x1F, 0x61, 0x5D, 0x05, 0x49, 0xB2, 0x9A, 0x39, 0xBF,
61 0x4B, 0x97, 0xB0, 0x1B, 0xF9, 0x6C, 0xDE, 0xD6, 0x80, 0x1D, 0xAB, 0x26, 0x02, 0xA9, 0x9B, 0x9D };
62std::array<uint8, 32>
const WorldSocket::EncryptionKeySeed = { 0x71, 0xC9, 0xED, 0x5A, 0xA7, 0x0E, 0x4D, 0xFF, 0x4C, 0x36, 0xA6, 0x5A, 0x3E, 0x46, 0x8A, 0x4A,
63 0x5D, 0xA1, 0x48, 0xC8, 0x30, 0x47, 0x4A, 0xDE, 0xF6, 0x0D, 0x6C, 0xBE, 0x6F, 0xE4, 0x55, 0x73 };
66 _type(
CONNECTION_TYPE_REALM), _key(0), _serverChallenge(), _sessionKey(), _encryptKey(), _overSpeedPings(0),
67 _worldSession(nullptr), _authed(false), _canRequestHotfixes(true), _headerBuffer(sizeof(
IncomingPacketHeader)), _sendBufferSize(4096), _compressionStream(nullptr)
103 [socketRef =
_socket->weak_from_this(), self = static_pointer_cast<WorldSocketProtocolInitializer>(this->shared_from_this())]
105 if (!socketRef.expired())
106 return self->ReadHandler();
108 return Trinity::Net::SocketReadCallbackResult::Stop;
124 std::array<std::shared_ptr<Trinity::Net::SocketConnectionInitializer>, 3> initializers =
126 std::make_shared<Trinity::Net::IpBanCheckConnectionInitializer<WorldSocket>>(
this),
127 std::make_shared<WorldSocketProtocolInitializer>(
this),
128 std::make_shared<Trinity::Net::ReadConnectionInitializer<WorldSocket>>(
this),
170 TC_LOG_ERROR(
"network",
"WorldSocket::InitializeHandler ByteBufferException {} occured while parsing initial packet from {}",
195 TC_LOG_ERROR(
"network",
"Can't initialize packet compression (zlib: deflateInit) Error code: {} ({})", z_res, zError(z_res));
234 if (!BaseSocket::Update())
248 memcpy(challenge.
DosChallenge.data(), Trinity::Crypto::GetRandomBytes<32>().data(), 32);
346 TC_LOG_ERROR(
"network",
"WorldSocket::ReadHeaderHandler(): client {} sent malformed packet (size: {}, opcode {})",
363 TC_LOG_ERROR(
"network",
"WorldSocket::ReadHeaderHandler(): client {} failed to decrypt packet (size: {})",
372 TC_LOG_ERROR(
"network",
"WorldSocket::ReadHeaderHandler(): client {} sent wrong opcode (opcode: {})",
485 cmp.
UncompressedAdler = adler32(adler32(0x9827D8F1, (Bytef*)&opcode,
sizeof(opcode)), packet.
data(), packetSize);
501 else if (!packet.
empty())
504 memcpy(dataPos, &opcode,
sizeof(opcode));
505 packetSize +=
sizeof(opcode);
508 header.
Size = packetSize;
527 TC_LOG_ERROR(
"network",
"Can't compress packet opcode (zlib: deflate) Error code: {} ({}, msg: {})", z_res, zError(z_res),
_compressionStream->msg);
537 TC_LOG_ERROR(
"network",
"Can't compress packet data (zlib: deflate) Error code: {} ({}, msg: {})", z_res, zError(z_res),
_compressionStream->msg);
583 (locale)(recruiter)(os)(timezone_offset)(bnet_account_id)(bnet_account_email)(SecurityLevel)(is_bnet_banned)(is_banned)(recruitId)) fields { *result };
585 Game.Id = fields.account_id().GetUInt32();
586 Game.KeyData = fields.session_key_bnet().GetBinary<64>();
587 BattleNet.LastIP = fields.last_ip().GetStringView();
588 BattleNet.IsLockedToIP = fields.locked().GetBool();
589 BattleNet.LockCountry = fields.lock_country().GetStringView();
590 Game.Expansion = fields.expansion().GetUInt8();
591 Game.MuteTime = fields.mutetime().GetInt64();
592 Game.Build = fields.client_build().GetUInt32();
594 Game.Recruiter = fields.recruiter().GetUInt32();
595 Game.OS = fields.os().GetStringView();
596 Game.TimezoneOffset =
Minutes(fields.timezone_offset().GetInt16());
597 BattleNet.Id = fields.bnet_account_id().GetUInt32();
598 BattleNet.Email = fields.bnet_account_email().GetStringView();
600 BattleNet.IsBanned = fields.is_bnet_banned().GetUInt32() != 0;
601 Game.IsBanned = fields.is_banned().GetUInt32() != 0;
602 Game.IsRecruiter = fields.recruitId().GetUInt32() != 0;
620 std::shared_ptr callbackData = std::make_shared<std::pair<WorldPackets::Auth::AuthSession, JSON::RealmList::RealmJoinTicket>>(
621 std::piecewise_construct, std::forward_as_tuple(std::move(packet)), std::forward_as_tuple());
622 if (!callbackData->first.ReadNoThrow())
628 if (!
JSON::Deserialize(callbackData->first.RealmJoinTicket, &callbackData->second))
638 stmt->
setString(1, callbackData->second.gameaccount());
642 HandleAuthSessionCallback(&callbackData->first, &callbackData->second, result.get());
653 TC_LOG_ERROR(
"network",
"WorldSocket::HandleAuthSession: Sent Auth Response (unknown account).");
666 TC_LOG_ERROR(
"network",
"WorldSocket::HandleAuthSession: Missing client build info for build {} ({}).", account.
Game.
Build, address);
673 if (clientBuildAuthKey == buildInfo->
AuthKeys.end())
676 TC_LOG_ERROR(
"network",
"WorldSocket::HandleAuthSession: Missing client build auth key for build {} variant {}-{}-{} ({}).", account.
Game.
Build,
685 digestKeyHash.
UpdateData(clientBuildAuthKey->Key.data(), clientBuildAuthKey->Key.size());
698 TC_LOG_ERROR(
"network",
"WorldSocket::HandleAuthSession: Authentication failed for account: {} ('{}') address: {}", account.
Game.
Id, joinTicket->
gameaccount(), address);
746 TC_LOG_ERROR(
"network",
"WorldSocket::HandleAuthSession: World closed, denying client ({}).", address);
754 TC_LOG_ERROR(
"network",
"WorldSocket::HandleAuthSession: Client {} requested connecting with realm id {} but this realm has id {} set in config.",
769 TC_LOG_DEBUG(
"network",
"WorldSocket::HandleAuthSession: Sent Auth Response (Account IP differs. Original IP: {}, new IP: {}).", account.
BattleNet.
LastIP, address);
804 TC_LOG_ERROR(
"network",
"WorldSocket::HandleAuthSession: Sent Auth Response (Account banned).");
816 TC_LOG_DEBUG(
"network",
"WorldSocket::HandleAuthSession: User tries to login but his security level is not enough");
822 TC_LOG_DEBUG(
"network",
"WorldSocket::HandleAuthSession: Client '{}' authenticated successfully from {}.", joinTicket->
gameaccount(), address);
846 LoadSessionPermissionsCallback(std::move(result));
870 std::shared_ptr<WorldPackets::Auth::AuthContinuedSession> authSession = std::make_shared<WorldPackets::Auth::AuthContinuedSession>(std::move(packet));
871 if (!authSession->ReadNoThrow())
878 key.
Raw = authSession->Key;
894 HandleAuthContinuedSessionCallback(authSession.get(), result.get());
913 std::string login = fields[0].
GetString();
917 hmac.UpdateData(
reinterpret_cast<uint8 const*
>(&authSession->
Key),
sizeof(authSession->
Key));
923 if (memcmp(hmac.GetDigest().data(), authSession->
Digest.data(), authSession->
Digest.size()))
925 TC_LOG_ERROR(
"network",
"WorldSocket::HandleAuthContinuedSession: Authentication failed for account: {} ('{}') address: {}", accountId, login,
GetRemoteIpAddress());
991 switch (connectToFailed.
Serial)
1033 sWorld->AddInstanceSocket(static_pointer_cast<WorldSocket>(shared_from_this()),
_key);
1070 bool ignoresOverspeedPingsLimit = [&]
1076 if (!ignoresOverspeedPingsLimit)
1078 TC_LOG_ERROR(
"network",
"WorldSocket::HandlePing: {} kicked for over-speed pings (address: {})",
1102 TC_LOG_ERROR(
"network",
"WorldSocket::HandlePing: peer sent CMSG_PING, but is not authenticated or got recently kicked, address = {}",
GetRemoteIpAddress());
constexpr size_t SESSION_KEY_LENGTH
@ ERROR_GAME_ACCOUNT_BANNED
@ ERROR_RISK_ACCOUNT_LOCKED
@ ERROR_WOW_SERVICES_INVALID_JOIN_TICKET
@ ERROR_SERVER_IS_PRIVATE
std::shared_ptr< PreparedResultSet > PreparedQueryResult
DatabaseWorkerPool< LoginDatabaseConnection > LoginDatabase
Accessor to the realm/login database.
std::chrono::steady_clock::time_point TimePoint
time_point shorthand typedefs
std::chrono::minutes Minutes
Minutes shorthand typedef.
#define TC_LOG_DEBUG(filterType__, message__,...)
#define TC_LOG_ERROR(filterType__, message__,...)
#define TC_LOG_TRACE(filterType__, message__,...)
@ LOGIN_UPD_MUTE_TIME_LOGIN
@ LOGIN_UPD_ACCOUNT_INFO_CONTINUED_SESSION
@ LOGIN_UPD_LAST_ATTEMPT_IP
@ LOGIN_SEL_ACCOUNT_INFO_CONTINUED_SESSION
@ LOGIN_SEL_ACCOUNT_INFO_BY_NAME
@ CONNECTION_TYPE_INSTANCE
constexpr FormattedOpcodeName< OpcodeClient > GetOpcodeNameForLogging(OpcodeClient opcode)
Lookup opcode name for human understandable logging.
@ CMSG_TIME_SYNC_RESPONSE
@ CMSG_AUTH_CONTINUED_SESSION
@ CMSG_ENTER_ENCRYPTED_MODE_ACK
@ CMSG_QUEUED_MESSAGES_END
@ CMSG_MOVE_INIT_ACTIVE_MOVER_COMPLETE
#define DEFINE_FIELD_ACCESSOR_CACHE_ANONYMOUS(result_type, fields_list)
Role Based Access Control related classes definition.
struct z_stream_s z_stream
T & AddCallback(T &&query)
void ProcessReadyCallbacks()
char const * what() const noexcept override
std::string_view ReadString(uint32 length, bool requireValidUtf8=true)
bool NeedsEncryption() const
Class used to access individual fields of database query result.
std::vector< uint8 > GetBinary() const noexcept
std::string GetString() const noexcept
inline ::google::protobuf::uint32 type() const
inline ::std::string * mutable_gameaccount()
inline ::google::protobuf::uint32 clientarch() const
inline ::google::protobuf::uint32 platform() const
const ::std::string & gameaccount() const
void Resize(size_type bytes)
size_type GetRemainingSpace() const
void ReadCompleted(size_type bytes)
void WriteCompleted(size_type bytes)
size_type GetActiveSize() const
uint8 * GetWritePointer()
void Write(void const *data, std::size_t size)
bool IsValid(OpcodeClient index) const
void setBinary(uint8 index, std::vector< uint8 > &&value)
void setString(uint8 index, std::string &&value)
void setUInt32(uint8 index, uint32 value)
void setInt64(uint8 index, int64 value)
void setInt32(uint8 index, int32 value)
QueryCallback && WithPreparedCallback(std::function< void(PreparedQueryResult)> &&callback)
void Generate(uint8 *buf, uint32 sz)
void UpdateData(uint8 const *data, size_t len)
Digest const & GetDigest() const
void UpdateData(uint8 const *data, size_t len)
Digest const & GetDigest() const
uint16 GetRemotePort() const
void SetNoDelay(bool enable)
boost::asio::ip::address const & GetRemoteIpAddress() const
void AsyncRead(Callback &&callback)
void QueuePacket(MessageBuffer &&buffer)
void DelayedCloseSocket()
Marks the socket for closing after write buffer becomes empty.
MessageBuffer & GetReadBuffer()
bool IsInitialized() const
bool PeekDecryptRecv(uint8 *data, size_t length)
void Init(Key const &key)
bool EncryptSend(uint8 *data, size_t length, Trinity::Crypto::AES::Tag &tag)
bool DecryptRecv(uint8 *data, size_t length, Trinity::Crypto::AES::Tag &tag)
void SetReceiveTime(TimePoint receivedTime)
void SetOpcode(uint32 opcode)
std::array< uint8, 32 > Challenge
WorldPacket const * Write() override
std::array< uint32, 8 > DosChallenge
std::array< uint8, DigestLength > Digest
std::array< uint8, 32 > LocalChallenge
uint32 Result
the result of the authentication process, possible values are BattlenetRpcErrorCode
WorldPacket const * Write() override
std::array< uint8, 32 > LocalChallenge
std::array< uint8, DigestLength > Digest
WorldPacket const * Write() override
Player session in the World.
void AbortLogin(WorldPackets::Character::LoginFailureReason reason)
void SendConnectToInstance(WorldPackets::Auth::ConnectToSerial serial)
std::string GetPlayerInfo() const
bool PlayerLoading() const
QueryCallback LoadPermissionsAsync()
bool HasPermission(uint32 permissionId)
void QueuePacket(WorldPacket &&new_packet)
Add an incoming packet to the queue.
void ResetTimeOutTime(bool onlyActive)
void SetLatency(uint32 latency)
rbac::RBACData * GetRBACData()
MessageBuffer _headerBuffer
static std::array< uint8, 32 > const SessionKeySeed
ReadDataHandlerResult HandleKeepAlive()
ConnectionType GetConnectionType() const
bool InitializeCompression()
void LogOpcodeText(OpcodeClient opcode) const
writes network.opcode log
void QueueQuery(QueryCallback &&queryCallback)
static std::array< uint8, 32 > const ContinuedSessionSeed
ReadDataHandlerResult HandleAuthSession(WorldPacket &&packet)
void LoadSessionPermissionsCallback(PreparedQueryResult result)
MessageBuffer _packetBuffer
void SendAuthResponseError(uint32 code)
QueryCallbackProcessor _queryProcessor
WorldPacketCrypt _authCrypt
ReadDataHandlerResult HandleAuthContinuedSession(WorldPacket &&packet)
std::size_t _sendBufferSize
static std::array< uint8, 32 > const AuthCheckSeed
Trinity::Net::SocketReadCallbackResult ReadHandler() override
WorldSocket(Trinity::Net::IoContextTcpSocket &&socket)
void SetWorldSession(WorldSession *session)
static std::array< uint8, 32 > const EncryptionKeySeed
ReadDataHandlerResult HandlePing(WorldPacket &&packet)
std::array< uint8, 32 > _serverChallenge
WorldSession * _worldSession
uint32 CompressPacket(uint8 *buffer, WorldPacket const &packet)
z_stream * _compressionStream
void SendPacket(WorldPacket const &packet)
MPSCQueue< EncryptablePacket, &EncryptablePacket::SocketQueueLink > _bufferQueue
std::array< uint8, 32 > _encryptKey
void SendPacketAndLogOpcode(WorldPacket const &packet)
sends and logs network.opcode without accessing WorldSession
ReadDataHandlerResult HandleConnectToFailed(WorldPacket &&packet)
void WritePacketToBuffer(EncryptablePacket const &packet, MessageBuffer &buffer)
ReadDataHandlerResult HandleLogDisconnect(WorldPacket &&packet) const
ReadDataHandlerResult HandleEnterEncryptedModeAck()
std::mutex _worldSessionLock
void HandleAuthSessionCallback(WorldPackets::Auth::AuthSession const *authSession, JSON::RealmList::RealmJoinTicket *joinTicket, PreparedResultSet const *result)
ReadDataHandlerResult ReadDataHandler()
void HandleAuthContinuedSessionCallback(WorldPackets::Auth::AuthContinuedSession const *authSession, PreparedResultSet const *result)
static uint32 const MinSizeForCompression
void LoadFromDBCallback(PreparedQueryResult result)
@ CONFIG_MAX_OVERSPEED_PINGS
@ CONFIG_ALLOW_LOGGING_IP_ADDRESSES_IN_DATABASE
Info const * GetBuildInfo(uint32 build)
std::array< char, 5 > ToCharArray(uint32 value)
TC_SHARED_API bool Deserialize(std::string const &json, google::protobuf::Message *message)
std::array< uint8, S > GetRandomBytes()
boost::asio::basic_stream_socket< boost::asio::ip::tcp, boost::asio::io_context::executor_type > IoContextTcpSocket
@ RBAC_PERM_SKIP_CHECK_OVERSPEED_PING
AccountInfo(PreparedResultSet const *result)
struct AccountInfo::@320 Game
std::array< uint8, 64 > KeyData
struct AccountInfo::@319 BattleNet
std::vector< AuthKey > AuthKeys
static std::shared_ptr< SocketConnectionInitializer > & SetupChain(std::span< std::shared_ptr< SocketConnectionInitializer > > initializers)
Trinity::Net::SocketReadCallbackResult ReadHandler()
static constexpr std::string_view ServerConnectionInitialize
WorldSocketProtocolInitializer(WorldSocket *socket)
static constexpr std::string_view ClientConnectionInitialize
MessageBuffer _packetBuffer
struct WorldSession::ConnectToKey::@318 Fields