aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Server
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2014-08-21 23:59:00 +0200
committerShauren <shauren.trinity@gmail.com>2014-08-21 23:59:00 +0200
commit42cac6796abbc683f8d383b43750860f05bb2dc6 (patch)
tree5984c512c709feca55efce941aa20a0ff6da7711 /src/server/game/Server
parentd2361ae056da8caf2c9b42e03a9f17f3fcb10790 (diff)
parent0c1587cc916de846eedf3ccf48f80caf053f427b (diff)
Merge branch 'master' of https://github.com/TrinityCore/TrinityCore into 4.3.4
Conflicts: src/server/authserver/Server/AuthSession.cpp src/server/game/Entities/Player/Player.cpp src/server/game/Server/WorldSocket.cpp
Diffstat (limited to 'src/server/game/Server')
-rw-r--r--src/server/game/Server/WorldSocket.cpp149
-rw-r--r--src/server/game/Server/WorldSocket.h2
2 files changed, 98 insertions, 53 deletions
diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp
index 09fb0acda97..4e7ad6590a8 100644
--- a/src/server/game/Server/WorldSocket.cpp
+++ b/src/server/game/Server/WorldSocket.cpp
@@ -16,14 +16,15 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <memory>
#include "WorldSocket.h"
#include "BigNumber.h"
#include "Opcodes.h"
+#include "Player.h"
#include "ScriptMgr.h"
#include "SHA1.h"
#include "PacketLog.h"
#include "BattlenetAccountMgr.h"
+#include <memory>
using boost::asio::ip::tcp;
@@ -68,6 +69,22 @@ void WorldSocket::ReadHeaderHandler()
EndianConvertReverse(header->size);
EndianConvert(header->cmd);
+ if (!header->IsValid())
+ {
+ if (_worldSession)
+ {
+ Player* player = _worldSession->GetPlayer();
+ TC_LOG_ERROR("network", "WorldSocket::ReadHeaderHandler(): client (account: %u, char [GUID: %u, name: %s]) sent malformed packet (size: %hu, cmd: %u)",
+ _worldSession->GetAccountId(), player ? player->GetGUIDLow() : 0, player ? player->GetName().c_str() : "<none>", header->size, header->cmd);
+ }
+ else
+ TC_LOG_ERROR("network", "WorldSocket::ReadHeaderHandler(): client %s sent malformed packet (size: %hu, cmd: %u)",
+ GetRemoteIpAddress().to_string().c_str(), header->size, header->cmd);
+
+ CloseSocket();
+ return;
+ }
+
AsyncReadData(header->size - sizeof(header->cmd));
}
@@ -75,8 +92,6 @@ void WorldSocket::ReadDataHandler()
{
ClientPktHeader* header = reinterpret_cast<ClientPktHeader*>(GetHeaderBuffer());
- header->size -= sizeof(header->cmd);
-
Opcodes opcode = PacketFilter::DropHighBytes(Opcodes(header->cmd));
std::string opcodeName = GetOpcodeNameForLogging(opcode);
@@ -141,7 +156,8 @@ void WorldSocket::ReadDataHandler()
if (!_worldSession)
{
TC_LOG_ERROR("network.opcode", "ProcessIncoming: Client not authed opcode = %u", uint32(opcode));
- break;
+ CloseSocket();
+ return;
}
// Our Idle timer will reset on any non PING opcodes.
@@ -197,10 +213,12 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
BigNumber k;
bool wardenActive = sWorld->getBoolConfig(CONFIG_WARDEN_ENABLED);
WorldPacket addonsData;
+ uint8 loginServerType;
+ uint32 realmIndex;
- recvPacket.read_skip<uint32>();
- recvPacket.read_skip<uint32>();
- recvPacket.read_skip<uint8>();
+ recvPacket.read_skip<uint32>(); // ServerId - Used for GRUNT only
+ recvPacket.read_skip<uint32>(); // Battlegroup
+ recvPacket >> loginServerType;
recvPacket >> digest[10];
recvPacket >> digest[18];
recvPacket >> digest[12];
@@ -215,7 +233,7 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
recvPacket >> digest[3];
recvPacket >> clientBuild;
recvPacket >> digest[8];
- recvPacket.read_skip<uint32>();
+ recvPacket >> realmIndex;
recvPacket.read_skip<uint8>();
recvPacket >> digest[17];
recvPacket >> digest[6];
@@ -224,7 +242,7 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
recvPacket >> digest[11];
recvPacket >> clientSeed;
recvPacket >> digest[2];
- recvPacket.read_skip<uint32>();
+ recvPacket.read_skip<uint32>(); // Region
recvPacket >> digest[14];
recvPacket >> digest[13];
@@ -236,15 +254,9 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
recvPacket.read((uint8*)addonsData.contents(), addonSize);
}
- recvPacket.ReadBit();
+ recvPacket.ReadBit(); // UseIPv6
uint32 accountNameLength = recvPacket.ReadBits(12);
account = recvPacket.ReadString(accountNameLength);
- if (sWorld->IsClosed())
- {
- SendAuthResponseError(AUTH_REJECT);
- TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: World closed, denying client (%s).", GetRemoteIpAddress().to_string().c_str());
- return;
- }
// Get the account information from the auth database
// 0 1 2 3 4 5 6 7 8
@@ -252,8 +264,17 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
PreparedStatement* stmt;
uint32 battlenetAccountId = 0;
uint8 battlenetAccountIndex = 0;
- if (Battlenet::AccountMgr::GetAccountIdAndIndex(account, &battlenetAccountId, &battlenetAccountIndex))
+ if (loginServerType == 1)
{
+ if (!Battlenet::AccountMgr::GetAccountIdAndIndex(account, &battlenetAccountId, &battlenetAccountIndex))
+ {
+ // We can not log here, as we do not know the account. Thus, no accountId.
+ SendAuthResponseError(AUTH_UNKNOWN_ACCOUNT);
+ TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Sent Auth Response (unknown account).");
+ DelayedCloseSocket();
+ return;
+ }
+
stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_INFO_BY_BNET);
stmt->setUInt32(0, battlenetAccountId);
stmt->setUInt8(1, battlenetAccountIndex);
@@ -272,6 +293,7 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
// We can not log here, as we do not know the account. Thus, no accountId.
SendAuthResponseError(AUTH_UNKNOWN_ACCOUNT);
TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Sent Auth Response (unknown account).");
+ DelayedCloseSocket();
return;
}
@@ -297,6 +319,57 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
// id has to be fetched at this point, so that first actual account response that fails can be logged
id = fields[0].GetUInt32();
+ k.SetHexStr(fields[1].GetCString());
+
+ // even if auth credentials are bad, try using the session key we have - client cannot read auth response error without it
+ _authCrypt.Init(&k);
+
+ // First reject the connection if packet contains invalid data or realm state doesn't allow logging in
+ if (sWorld->IsClosed())
+ {
+ SendAuthResponseError(AUTH_REJECT);
+ TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: World closed, denying client (%s).", GetRemoteIpAddress().to_string().c_str());
+ DelayedCloseSocket();
+ return;
+ }
+
+ if (realmIndex != realmID)
+ {
+ SendAuthResponseError(REALM_LIST_REALM_NOT_FOUND);
+ TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Sent Auth Response (bad realm).");
+ DelayedCloseSocket();
+ return;
+ }
+
+ std::string os = fields[8].GetString();
+
+ // Must be done before WorldSession is created
+ if (wardenActive && os != "Win" && os != "OSX")
+ {
+ SendAuthResponseError(AUTH_REJECT);
+ TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Client %s attempted to log in using invalid client OS (%s).", address.c_str(), os.c_str());
+ DelayedCloseSocket();
+ return;
+ }
+
+ // Check that Key and account name are the same on client and server
+ uint32 t = 0;
+
+ sha.UpdateData(account);
+ sha.UpdateData((uint8*)&t, 4);
+ sha.UpdateData((uint8*)&clientSeed, 4);
+ sha.UpdateData((uint8*)&_authSeed, 4);
+ sha.UpdateBigNumbers(&k, NULL);
+ sha.Finalize();
+
+ if (memcmp(sha.GetDigest(), digest, 20))
+ {
+ SendAuthResponseError(AUTH_FAILED);
+ TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Authentication failed for account: %u ('%s') address: %s", id, account.c_str(), address.c_str());
+ DelayedCloseSocket();
+ return;
+ }
+
///- Re-check ip locking (same check as in auth).
if (fields[3].GetUInt8() == 1) // if ip is locked
{
@@ -306,12 +379,11 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
TC_LOG_DEBUG("network", "WorldSocket::HandleAuthSession: Sent Auth Response (Account IP differs. Original IP: %s, new IP: %s).", fields[2].GetCString(), address.c_str());
// We could log on hook only instead of an additional db log, however action logger is config based. Better keep DB logging as well
sScriptMgr->OnFailedAccountLogin(id);
+ DelayedCloseSocket();
return;
}
}
- k.SetHexStr(fields[1].GetCString());
-
int64 mutetime = fields[5].GetInt64();
//! Negative mutetime indicates amount of seconds to be muted effective on next login - which is now.
if (mutetime < 0)
@@ -331,16 +403,6 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
locale = LOCALE_enUS;
uint32 recruiter = fields[7].GetUInt32();
- std::string os = fields[8].GetString();
-
- // Must be done before WorldSession is created
- if (wardenActive && os != "Win" && os != "OSX")
- {
- SendAuthResponseError(AUTH_REJECT);
- TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Client %s attempted to log in using invalid client OS (%s).", address.c_str(), os.c_str());
- return;
- }
-
// Checks gmlevel per Realm
stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_GMLEVEL_BY_REALMID);
@@ -370,6 +432,7 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
SendAuthResponseError(AUTH_BANNED);
TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Sent Auth Response (Account banned).");
sScriptMgr->OnFailedAccountLogin(id);
+ DelayedCloseSocket();
return;
}
@@ -381,23 +444,7 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
SendAuthResponseError(AUTH_UNAVAILABLE);
TC_LOG_INFO("network", "WorldSocket::HandleAuthSession: User tries to login but his security level is not enough");
sScriptMgr->OnFailedAccountLogin(id);
- return;
- }
-
- // Check that Key and account name are the same on client and server
- uint32 t = 0;
-
- sha.UpdateData(account);
- sha.UpdateData((uint8*)&t, 4);
- sha.UpdateData((uint8*)&clientSeed, 4);
- sha.UpdateData((uint8*)&_authSeed, 4);
- sha.UpdateBigNumbers(&k, NULL);
- sha.Finalize();
-
- if (memcmp(sha.GetDigest(), digest, 20))
- {
- SendAuthResponseError(AUTH_FAILED);
- TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Authentication failed for account: %u ('%s') address: %s", id, account.c_str(), address.c_str());
+ DelayedCloseSocket();
return;
}
@@ -424,19 +471,15 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
LoginDatabase.Execute(stmt);
- // NOTE ATM the socket is single-threaded, have this in mind ...
- _worldSession = new WorldSession(id, battlenetAccountId, shared_from_this(), AccountTypes(security), expansion, mutetime, locale, recruiter, isRecruiter);
-
- _authCrypt.Init(&k);
+ // At this point, we can safely hook a successful login
+ sScriptMgr->OnAccountLogin(id);
+ _worldSession = new WorldSession(id, battlenetAccountId, shared_from_this(), AccountTypes(security), expansion, mutetime, locale, recruiter, isRecruiter);
_worldSession->LoadGlobalAccountData();
_worldSession->LoadTutorialsData();
_worldSession->ReadAddonsInfo(addonsData);
_worldSession->LoadPermissions();
- // At this point, we can safely hook a successful login
- sScriptMgr->OnAccountLogin(id);
-
// Initialize Warden system only if it is enabled by config
if (wardenActive)
_worldSession->InitWarden(&k, os);
diff --git a/src/server/game/Server/WorldSocket.h b/src/server/game/Server/WorldSocket.h
index 404999499ef..d53896274d7 100644
--- a/src/server/game/Server/WorldSocket.h
+++ b/src/server/game/Server/WorldSocket.h
@@ -48,6 +48,8 @@ struct ClientPktHeader
{
uint16 size;
uint32 cmd;
+
+ bool IsValid() const { return size >= 4 && size < 10240 && (cmd < NUM_OPCODE_HANDLERS || (header.cmd >> 16) == 0x4C52); }
};
#pragma pack(pop)