Conflicts:
	src/server/authserver/Server/AuthSession.cpp
	src/server/game/Entities/Player/Player.cpp
	src/server/game/Server/WorldSocket.cpp
This commit is contained in:
Shauren committed 2014-08-21 23:59:00 +02:00
commit 42cac6796a
34 files changed
+3374 -761

No files matched your search

+96 -53
View File
@@ -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 ...
// 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);
_authCrypt.Init(&k);
_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);