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
This commit is contained in:
commit
42cac6796a
34 files changed
+3374
-761
No files matched your search
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user