Core/Networking: Added safety checks against linking instance socket with incorrect/old session

Ref #15892
This commit is contained in:
Shauren
2015-12-29 21:22:31 +01:00
parent 7b15207902
commit 6ace6aabbf
5 changed files with 46 additions and 14 deletions

View File

@@ -146,6 +146,7 @@ WorldSession::WorldSession(uint32 id, std::string&& name, uint32 battlenetAccoun
}
m_Socket[CONNECTION_TYPE_REALM] = sock;
_instanceConnectKey.Raw = UI64LIT(0);
InitializeQueryCallbackParameters();
}
@@ -716,8 +717,12 @@ void WorldSession::SendConnectToInstance(WorldPackets::Auth::ConnectToSerial ser
boost::asio::ip::tcp::endpoint instanceAddress = realm.GetAddressForClient(boost::asio::ip::address::from_string(GetRemoteAddress(), ignored_error));
instanceAddress.port(sWorld->getIntConfig(CONFIG_PORT_INSTANCE));
_instanceConnectKey.Fields.AccountId = GetAccountId();
_instanceConnectKey.Fields.ConnectionType = CONNECTION_TYPE_INSTANCE;
_instanceConnectKey.Fields.Key = urand(0, 0x7FFFFFFF);
WorldPackets::Auth::ConnectTo connectTo;
connectTo.Key = MAKE_PAIR64(GetAccountId(), CONNECTION_TYPE_INSTANCE);
connectTo.Key = _instanceConnectKey.Raw;
connectTo.Serial = serial;
connectTo.Payload.Where = instanceAddress;
connectTo.Con = CONNECTION_TYPE_INSTANCE;

View File

@@ -1634,6 +1634,19 @@ class WorldSession
void HandleBattlePetSummon(WorldPackets::BattlePet::BattlePetSummon& battlePetSummon);
void HandleCageBattlePet(WorldPackets::BattlePet::CageBattlePet& cageBattlePet);
union ConnectToKey
{
struct
{
uint64 AccountId : 32;
uint64 ConnectionType : 1;
uint64 Key : 31;
} Fields;
uint64 Raw;
};
uint64 GetConnectToInstanceKey() const { return _instanceConnectKey.Raw; }
private:
void InitializeQueryCallbackParameters();
void ProcessQueryCallbacks();
@@ -1750,6 +1763,8 @@ class WorldSession
std::unique_ptr<CollectionMgr> _collectionMgr;
ConnectToKey _instanceConnectKey;
WorldSession(WorldSession const& right) = delete;
WorldSession& operator=(WorldSession const& right) = delete;
};

View File

@@ -782,7 +782,10 @@ void WorldSocket::LoadSessionPermissionsCallback(PreparedQueryResult result)
void WorldSocket::HandleAuthContinuedSession(std::shared_ptr<WorldPackets::Auth::AuthContinuedSession> authSession)
{
_type = ConnectionType(PAIR64_HIPART(authSession->Key));
WorldSession::ConnectToKey key;
key.Raw = authSession->Key;
_type = ConnectionType(key.Fields.ConnectionType);
if (_type != CONNECTION_TYPE_INSTANCE)
{
SendAuthResponseError(AUTH_UNKNOWN_ACCOUNT);
@@ -793,7 +796,7 @@ void WorldSocket::HandleAuthContinuedSession(std::shared_ptr<WorldPackets::Auth:
// Client switches packet headers after sending CMSG_AUTH_CONTINUED_SESSION
_headerBuffer.Resize(SizeOfClientHeader[1][1]);
uint32 accountId = PAIR64_LOPART(authSession->Key);
uint32 accountId = uint32(key.Fields.AccountId);
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_INFO_CONTINUED_SESSION);
stmt->setUInt32(0, accountId);
@@ -813,7 +816,10 @@ void WorldSocket::HandleAuthContinuedSessionCallback(std::shared_ptr<WorldPacket
return;
}
uint32 accountId = PAIR64_LOPART(authSession->Key);
WorldSession::ConnectToKey key;
key.Raw = authSession->Key;
uint32 accountId = uint32(key.Fields.AccountId);
Field* fields = result->Fetch();
std::string login = fields[0].GetString();
BigNumber k;
@@ -835,7 +841,7 @@ void WorldSocket::HandleAuthContinuedSessionCallback(std::shared_ptr<WorldPacket
return;
}
sWorld->AddInstanceSocket(shared_from_this(), accountId);
sWorld->AddInstanceSocket(shared_from_this(), authSession->Key);
AsyncRead();
}

View File

@@ -227,9 +227,9 @@ void World::AddSession(WorldSession* s)
addSessQueue.add(s);
}
void World::AddInstanceSocket(std::shared_ptr<WorldSocket> sock, uint32 sessionAccountId)
void World::AddInstanceSocket(std::shared_ptr<WorldSocket> sock, uint64 connectToKey)
{
_linkSocketQueue.add(std::make_pair(sock, sessionAccountId));
_linkSocketQueue.add(std::make_pair(sock, connectToKey));
}
void World::AddSession_(WorldSession* s)
@@ -298,10 +298,16 @@ void World::AddSession_(WorldSession* s)
}
}
void World::ProcessLinkInstanceSocket(std::pair<std::shared_ptr<WorldSocket>, uint32> linkInfo)
void World::ProcessLinkInstanceSocket(std::pair<std::shared_ptr<WorldSocket>, uint64> linkInfo)
{
WorldSession* session = FindSession(linkInfo.second);
if (!session)
if (!linkInfo.first->IsOpen())
return;
WorldSession::ConnectToKey key;
key.Raw = linkInfo.second;
WorldSession* session = FindSession(uint32(key.Fields.AccountId));
if (!session || session->GetConnectToInstanceKey() != linkInfo.second)
{
linkInfo.first->SendAuthResponseError(AUTH_SESSION_EXPIRED);
linkInfo.first->DelayedCloseSocket();
@@ -2811,7 +2817,7 @@ void World::SendServerMessage(ServerMessageType messageID, std::string stringPar
void World::UpdateSessions(uint32 diff)
{
std::pair<std::shared_ptr<WorldSocket>, uint32> linkInfo;
std::pair<std::shared_ptr<WorldSocket>, uint64> linkInfo;
while (_linkSocketQueue.next(linkInfo))
ProcessLinkInstanceSocket(std::move(linkInfo));

View File

@@ -564,7 +564,7 @@ class World
WorldSession* FindSession(uint32 id) const;
void AddSession(WorldSession* s);
void AddInstanceSocket(std::shared_ptr<WorldSocket> sock, uint32 sessionAccountId);
void AddInstanceSocket(std::shared_ptr<WorldSocket> sock, uint64 connectToKey);
void SendAutoBroadcast();
bool RemoveSession(uint32 id);
/// Get the number of current active sessions
@@ -874,8 +874,8 @@ class World
void AddSession_(WorldSession* s);
LockedQueue<WorldSession*> addSessQueue;
void ProcessLinkInstanceSocket(std::pair<std::shared_ptr<WorldSocket>, uint32> linkInfo);
LockedQueue<std::pair<std::shared_ptr<WorldSocket>, uint32>> _linkSocketQueue;
void ProcessLinkInstanceSocket(std::pair<std::shared_ptr<WorldSocket>, uint64> linkInfo);
LockedQueue<std::pair<std::shared_ptr<WorldSocket>, uint64>> _linkSocketQueue;
// used versions
std::string m_DBVersion;