mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2025-11-29 17:38:24 +08:00
feat: Added logs_ip_action + more (#1157)
This commit is contained in:
committed by
Francesco Borzì
parent
6750fd5a73
commit
2a71b2a666
17
data/sql/updates/pending_db_auth/rev_1546018964238773800.sql
Normal file
17
data/sql/updates/pending_db_auth/rev_1546018964238773800.sql
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
INSERT INTO version_db_auth (`sql_rev`) VALUES ('1546018964238773800');
|
||||||
|
|
||||||
|
CREATE TABLE `logs_ip_actions` (
|
||||||
|
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'Unique Identifier',
|
||||||
|
`account_id` INT(10) UNSIGNED NOT NULL COMMENT 'Account ID',
|
||||||
|
`character_guid` INT(10) UNSIGNED NOT NULL COMMENT 'Character Guid',
|
||||||
|
`type` TINYINT(3) UNSIGNED NOT NULL,
|
||||||
|
`ip` VARCHAR(15) NOT NULL DEFAULT '127.0.0.1',
|
||||||
|
`systemnote` TEXT NULL COMMENT 'Notes inserted by system',
|
||||||
|
`unixtime` INT(10) UNSIGNED NOT NULL COMMENT 'Unixtime',
|
||||||
|
`time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Timestamp',
|
||||||
|
`comment` TEXT NULL COMMENT 'Allows users to add a comment',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
)
|
||||||
|
COMMENT='Used to log ips of individual actions'
|
||||||
|
COLLATE='utf8_general_ci'
|
||||||
|
ENGINE=InnoDB;
|
||||||
@@ -55,6 +55,7 @@ void LoginDatabaseConnection::DoPrepareStatements()
|
|||||||
PrepareStatement(LOGIN_UPD_MUTE_TIME, "UPDATE account SET mutetime = ? , mutereason = ? , muteby = ? WHERE id = ?", CONNECTION_ASYNC);
|
PrepareStatement(LOGIN_UPD_MUTE_TIME, "UPDATE account SET mutetime = ? , mutereason = ? , muteby = ? WHERE id = ?", CONNECTION_ASYNC);
|
||||||
PrepareStatement(LOGIN_UPD_MUTE_TIME_LOGIN, "UPDATE account SET mutetime = ? WHERE id = ?", CONNECTION_ASYNC);
|
PrepareStatement(LOGIN_UPD_MUTE_TIME_LOGIN, "UPDATE account SET mutetime = ? WHERE id = ?", CONNECTION_ASYNC);
|
||||||
PrepareStatement(LOGIN_UPD_LAST_IP, "UPDATE account SET last_ip = ? WHERE username = ?", CONNECTION_ASYNC);
|
PrepareStatement(LOGIN_UPD_LAST_IP, "UPDATE account SET last_ip = ? WHERE username = ?", CONNECTION_ASYNC);
|
||||||
|
PrepareStatement(LOGIN_UPD_LAST_ATTEMPT_IP, "UPDATE account SET last_attempt_ip = ? WHERE username = ?", CONNECTION_ASYNC);
|
||||||
PrepareStatement(LOGIN_UPD_ACCOUNT_ONLINE, "UPDATE account SET online = online | (1<<(?-1)) WHERE id = ?", CONNECTION_ASYNC);
|
PrepareStatement(LOGIN_UPD_ACCOUNT_ONLINE, "UPDATE account SET online = online | (1<<(?-1)) WHERE id = ?", CONNECTION_ASYNC);
|
||||||
PrepareStatement(LOGIN_UPD_UPTIME_PLAYERS, "UPDATE uptime SET uptime = ?, maxplayers = ? WHERE realmid = ? AND starttime = ?", CONNECTION_ASYNC);
|
PrepareStatement(LOGIN_UPD_UPTIME_PLAYERS, "UPDATE uptime SET uptime = ?, maxplayers = ? WHERE realmid = ? AND starttime = ?", CONNECTION_ASYNC);
|
||||||
PrepareStatement(LOGIN_DEL_OLD_LOGS, "DELETE FROM logs WHERE (time + ?) < ?", CONNECTION_ASYNC);
|
PrepareStatement(LOGIN_DEL_OLD_LOGS, "DELETE FROM logs WHERE (time + ?) < ?", CONNECTION_ASYNC);
|
||||||
@@ -76,10 +77,20 @@ void LoginDatabaseConnection::DoPrepareStatements()
|
|||||||
PrepareStatement(LOGIN_SEL_ACCOUNT_RECRUITER, "SELECT 1 FROM account WHERE recruiter = ?", CONNECTION_SYNCH);
|
PrepareStatement(LOGIN_SEL_ACCOUNT_RECRUITER, "SELECT 1 FROM account WHERE recruiter = ?", CONNECTION_SYNCH);
|
||||||
PrepareStatement(LOGIN_SEL_BANS, "SELECT 1 FROM account_banned WHERE id = ? AND active = 1 UNION SELECT 1 FROM ip_banned WHERE ip = ?", CONNECTION_SYNCH);
|
PrepareStatement(LOGIN_SEL_BANS, "SELECT 1 FROM account_banned WHERE id = ? AND active = 1 UNION SELECT 1 FROM ip_banned WHERE ip = ?", CONNECTION_SYNCH);
|
||||||
PrepareStatement(LOGIN_SEL_ACCOUNT_WHOIS, "SELECT username, email, last_ip FROM account WHERE id = ?", CONNECTION_SYNCH);
|
PrepareStatement(LOGIN_SEL_ACCOUNT_WHOIS, "SELECT username, email, last_ip FROM account WHERE id = ?", CONNECTION_SYNCH);
|
||||||
|
PrepareStatement(LOGIN_SEL_LAST_ATTEMPT_IP, "SELECT last_attempt_ip FROM account WHERE id = ?", CONNECTION_SYNCH);
|
||||||
|
PrepareStatement(LOGIN_SEL_LAST_IP, "SELECT last_ip FROM account WHERE id = ?", CONNECTION_SYNCH);
|
||||||
PrepareStatement(LOGIN_SEL_REALMLIST_SECURITY_LEVEL, "SELECT allowedSecurityLevel from realmlist WHERE id = ?", CONNECTION_SYNCH);
|
PrepareStatement(LOGIN_SEL_REALMLIST_SECURITY_LEVEL, "SELECT allowedSecurityLevel from realmlist WHERE id = ?", CONNECTION_SYNCH);
|
||||||
PrepareStatement(LOGIN_DEL_ACCOUNT, "DELETE FROM account WHERE id = ?", CONNECTION_ASYNC);
|
PrepareStatement(LOGIN_DEL_ACCOUNT, "DELETE FROM account WHERE id = ?", CONNECTION_ASYNC);
|
||||||
PrepareStatement(LOGIN_SEL_IP2NATION_COUNTRY, "SELECT c.country FROM ip2nationCountries c, ip2nation i WHERE i.ip < ? AND c.code = i.country ORDER BY i.ip DESC LIMIT 0,1", CONNECTION_SYNCH);
|
PrepareStatement(LOGIN_SEL_IP2NATION_COUNTRY, "SELECT c.country FROM ip2nationCountries c, ip2nation i WHERE i.ip < ? AND c.code = i.country ORDER BY i.ip DESC LIMIT 0,1", CONNECTION_SYNCH);
|
||||||
PrepareStatement(LOGIN_SEL_AUTOBROADCAST, "SELECT id, weight, text FROM autobroadcast WHERE realmid = ? OR realmid = -1", CONNECTION_SYNCH);
|
PrepareStatement(LOGIN_SEL_AUTOBROADCAST, "SELECT id, weight, text FROM autobroadcast WHERE realmid = ? OR realmid = -1", CONNECTION_SYNCH);
|
||||||
PrepareStatement(LOGIN_INS_ACCOUNT_MUTE, "INSERT INTO account_muted VALUES (?, UNIX_TIMESTAMP(), ?, ?, ?)", CONNECTION_ASYNC);
|
PrepareStatement(LOGIN_INS_ACCOUNT_MUTE, "INSERT INTO account_muted VALUES (?, UNIX_TIMESTAMP(), ?, ?, ?)", CONNECTION_ASYNC);
|
||||||
PrepareStatement(LOGIN_SEL_ACCOUNT_MUTE_INFO, "SELECT mutedate, mutetime, mutereason, mutedby FROM account_muted WHERE guid = ? ORDER BY mutedate ASC", CONNECTION_SYNCH);
|
PrepareStatement(LOGIN_SEL_ACCOUNT_MUTE_INFO, "SELECT mutedate, mutetime, mutereason, mutedby FROM account_muted WHERE guid = ? ORDER BY mutedate ASC", CONNECTION_SYNCH);
|
||||||
|
// 0: uint32, 1: uint32, 2: uint8, 3: uint32, 4: string // Complete name: "Login_Insert_AccountLoginDeLete_IP_Logging"
|
||||||
|
PrepareStatement(LOGIN_INS_ALDL_IP_LOGGING, "INSERT INTO logs_ip_actions (account_id,character_guid,type,ip,systemnote,unixtime,time) VALUES (?, ?, ?, (SELECT last_ip FROM account WHERE id = ?), ?, unix_timestamp(NOW()), NOW())", CONNECTION_ASYNC);
|
||||||
|
// 0: uint32, 1: uint32, 2: uint8, 3: uint32, 4: string // Complete name: "Login_Insert_FailedAccountLogin_IP_Logging"
|
||||||
|
PrepareStatement(LOGIN_INS_FACL_IP_LOGGING, "INSERT INTO logs_ip_actions (account_id,character_guid,type,ip,systemnote,unixtime,time) VALUES (?, ?, ?, (SELECT last_attempt_ip FROM account WHERE id = ?), ?, unix_timestamp(NOW()), NOW())", CONNECTION_ASYNC);
|
||||||
|
// 0: uint32, 1: uint32, 2: uint8, 3: string, 4: string // Complete name: "Login_Insert_CharacterDelete_IP_Logging"
|
||||||
|
PrepareStatement(LOGIN_INS_CHAR_IP_LOGGING, "INSERT INTO logs_ip_actions (account_id,character_guid,type,ip,systemnote,unixtime,time) VALUES (?, ?, ?, ?, ?, unix_timestamp(NOW()), NOW())", CONNECTION_ASYNC);
|
||||||
|
// 0: string, 1: string, 2: string // Complete name: "Login_Insert_Failed_Account_Login_due_password_IP_Logging"
|
||||||
|
PrepareStatement(LOGIN_INS_FALP_IP_LOGGING, "INSERT INTO logs_ip_actions (account_id,character_guid,type,ip,systemnote,unixtime,time) VALUES ((SELECT id FROM account WHERE username = ?), 0, 1, ?, ?, unix_timestamp(NOW()), NOW())", CONNECTION_ASYNC);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ enum LoginDatabaseStatements
|
|||||||
LOGIN_UPD_MUTE_TIME,
|
LOGIN_UPD_MUTE_TIME,
|
||||||
LOGIN_UPD_MUTE_TIME_LOGIN,
|
LOGIN_UPD_MUTE_TIME_LOGIN,
|
||||||
LOGIN_UPD_LAST_IP,
|
LOGIN_UPD_LAST_IP,
|
||||||
|
LOGIN_UPD_LAST_ATTEMPT_IP,
|
||||||
LOGIN_UPD_ACCOUNT_ONLINE,
|
LOGIN_UPD_ACCOUNT_ONLINE,
|
||||||
LOGIN_UPD_UPTIME_PLAYERS,
|
LOGIN_UPD_UPTIME_PLAYERS,
|
||||||
LOGIN_DEL_OLD_LOGS,
|
LOGIN_DEL_OLD_LOGS,
|
||||||
@@ -100,6 +101,12 @@ enum LoginDatabaseStatements
|
|||||||
LOGIN_DEL_ACCOUNT,
|
LOGIN_DEL_ACCOUNT,
|
||||||
LOGIN_SEL_IP2NATION_COUNTRY,
|
LOGIN_SEL_IP2NATION_COUNTRY,
|
||||||
LOGIN_SEL_AUTOBROADCAST,
|
LOGIN_SEL_AUTOBROADCAST,
|
||||||
|
LOGIN_SEL_LAST_ATTEMPT_IP,
|
||||||
|
LOGIN_SEL_LAST_IP,
|
||||||
|
LOGIN_INS_ALDL_IP_LOGGING,
|
||||||
|
LOGIN_INS_FACL_IP_LOGGING,
|
||||||
|
LOGIN_INS_CHAR_IP_LOGGING,
|
||||||
|
LOGIN_INS_FALP_IP_LOGGING,
|
||||||
|
|
||||||
LOGIN_INS_ACCOUNT_MUTE,
|
LOGIN_INS_ACCOUNT_MUTE,
|
||||||
LOGIN_SEL_ACCOUNT_MUTE_INFO,
|
LOGIN_SEL_ACCOUNT_MUTE_INFO,
|
||||||
|
|||||||
@@ -764,6 +764,18 @@ bool AuthSocket::_HandleLogonProof()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint32 MaxWrongPassCount = sConfigMgr->GetIntDefault("WrongPass.MaxCount", 0);
|
uint32 MaxWrongPassCount = sConfigMgr->GetIntDefault("WrongPass.MaxCount", 0);
|
||||||
|
|
||||||
|
// We can not include the failed account login hook. However, this is a workaround to still log this.
|
||||||
|
if (sConfigMgr->GetBoolDefault("WrongPass.Logging", false))
|
||||||
|
{
|
||||||
|
PreparedStatement* logstmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_FALP_IP_LOGGING);
|
||||||
|
logstmt->setString(0, _login);
|
||||||
|
logstmt->setString(1, socket().getRemoteAddress());
|
||||||
|
logstmt->setString(2, "Logged on failed AccountLogin due wrong password");
|
||||||
|
|
||||||
|
LoginDatabase.Execute(logstmt);
|
||||||
|
}
|
||||||
|
|
||||||
if (MaxWrongPassCount > 0)
|
if (MaxWrongPassCount > 0)
|
||||||
{
|
{
|
||||||
//Increment number of failed logins by one and if it reaches the limit temporarily ban that account or IP
|
//Increment number of failed logins by one and if it reaches the limit temporarily ban that account or IP
|
||||||
|
|||||||
@@ -233,6 +233,15 @@ WrongPass.BanTime = 600
|
|||||||
|
|
||||||
WrongPass.BanType = 0
|
WrongPass.BanType = 0
|
||||||
|
|
||||||
|
#
|
||||||
|
# WrongPass.Logging
|
||||||
|
# Description: Additionally log attempted wrong password logging
|
||||||
|
# Default: 0 - (Disabled)
|
||||||
|
# 1 - (Enabled)
|
||||||
|
|
||||||
|
WrongPass.Logging = 0
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
###################################################################################################
|
###################################################################################################
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "DatabaseEnv.h"
|
#include "DatabaseEnv.h"
|
||||||
#include "ObjectAccessor.h"
|
#include "ObjectAccessor.h"
|
||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
|
#include "ScriptMgr.h"
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
#include "SHA1.h"
|
#include "SHA1.h"
|
||||||
#include "WorldSession.h"
|
#include "WorldSession.h"
|
||||||
@@ -149,10 +150,16 @@ namespace AccountMgr
|
|||||||
std::string username;
|
std::string username;
|
||||||
|
|
||||||
if (!GetName(accountId, username))
|
if (!GetName(accountId, username))
|
||||||
|
{
|
||||||
|
sScriptMgr->OnFailedPasswordChange(accountId);
|
||||||
return AOR_NAME_NOT_EXIST; // account doesn't exist
|
return AOR_NAME_NOT_EXIST; // account doesn't exist
|
||||||
|
}
|
||||||
|
|
||||||
if (utf8length(newPassword) > MAX_ACCOUNT_STR)
|
if (utf8length(newPassword) > MAX_ACCOUNT_STR)
|
||||||
|
{
|
||||||
|
sScriptMgr->OnFailedEmailChange(accountId);
|
||||||
return AOR_PASS_TOO_LONG;
|
return AOR_PASS_TOO_LONG;
|
||||||
|
}
|
||||||
|
|
||||||
normalizeString(username);
|
normalizeString(username);
|
||||||
normalizeString(newPassword);
|
normalizeString(newPassword);
|
||||||
@@ -164,6 +171,7 @@ namespace AccountMgr
|
|||||||
|
|
||||||
LoginDatabase.Execute(stmt);
|
LoginDatabase.Execute(stmt);
|
||||||
|
|
||||||
|
sScriptMgr->OnPasswordChange(accountId);
|
||||||
return AOR_OK;
|
return AOR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-GPL2
|
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-GPL2
|
||||||
* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
|
* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
|
||||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||||
|
|||||||
@@ -678,10 +678,13 @@ void WorldSession::HandleCharDeleteOpcode(WorldPacket& recvData)
|
|||||||
{
|
{
|
||||||
uint64 guid;
|
uint64 guid;
|
||||||
recvData >> guid;
|
recvData >> guid;
|
||||||
|
// Initiating
|
||||||
|
uint32 initAccountId = GetAccountId();
|
||||||
|
|
||||||
// can't delete loaded character
|
// can't delete loaded character
|
||||||
if (ObjectAccessor::FindPlayerInOrOutOfWorld(guid) || sWorld->FindOfflineSessionForCharacterGUID(GUID_LOPART(guid)))
|
if (ObjectAccessor::FindPlayerInOrOutOfWorld(guid) || sWorld->FindOfflineSessionForCharacterGUID(GUID_LOPART(guid)))
|
||||||
{
|
{
|
||||||
|
sScriptMgr->OnPlayerFailedDelete(guid, initAccountId);
|
||||||
WorldPacket data(SMSG_CHAR_DELETE, 1);
|
WorldPacket data(SMSG_CHAR_DELETE, 1);
|
||||||
data << (uint8)CHAR_DELETE_FAILED;
|
data << (uint8)CHAR_DELETE_FAILED;
|
||||||
SendPacket(&data);
|
SendPacket(&data);
|
||||||
@@ -694,6 +697,7 @@ void WorldSession::HandleCharDeleteOpcode(WorldPacket& recvData)
|
|||||||
// is guild leader
|
// is guild leader
|
||||||
if (sGuildMgr->GetGuildByLeader(guid))
|
if (sGuildMgr->GetGuildByLeader(guid))
|
||||||
{
|
{
|
||||||
|
sScriptMgr->OnPlayerFailedDelete(guid, initAccountId);
|
||||||
WorldPacket data(SMSG_CHAR_DELETE, 1);
|
WorldPacket data(SMSG_CHAR_DELETE, 1);
|
||||||
data << (uint8)CHAR_DELETE_FAILED_GUILD_LEADER;
|
data << (uint8)CHAR_DELETE_FAILED_GUILD_LEADER;
|
||||||
SendPacket(&data);
|
SendPacket(&data);
|
||||||
@@ -703,6 +707,7 @@ void WorldSession::HandleCharDeleteOpcode(WorldPacket& recvData)
|
|||||||
// is arena team captain
|
// is arena team captain
|
||||||
if (sArenaTeamMgr->GetArenaTeamByCaptain(guid))
|
if (sArenaTeamMgr->GetArenaTeamByCaptain(guid))
|
||||||
{
|
{
|
||||||
|
sScriptMgr->OnPlayerFailedDelete(guid, initAccountId);
|
||||||
WorldPacket data(SMSG_CHAR_DELETE, 1);
|
WorldPacket data(SMSG_CHAR_DELETE, 1);
|
||||||
data << (uint8)CHAR_DELETE_FAILED_ARENA_CAPTAIN;
|
data << (uint8)CHAR_DELETE_FAILED_ARENA_CAPTAIN;
|
||||||
SendPacket(&data);
|
SendPacket(&data);
|
||||||
@@ -716,15 +721,21 @@ void WorldSession::HandleCharDeleteOpcode(WorldPacket& recvData)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// prevent deleting other players' characters using cheating tools
|
// prevent deleting other players' characters using cheating tools
|
||||||
if (accountId != GetAccountId())
|
if (accountId != initAccountId)
|
||||||
|
{
|
||||||
|
sScriptMgr->OnPlayerFailedDelete(guid, initAccountId);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
std::string IP_str = GetRemoteAddress();
|
std::string IP_str = GetRemoteAddress();
|
||||||
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
|
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
|
||||||
sLog->outDetail("Account: %d (IP: %s) Delete Character:[%s] (GUID: %u)", GetAccountId(), IP_str.c_str(), name.c_str(), GUID_LOPART(guid));
|
sLog->outDetail("Account: %d (IP: %s) Delete Character:[%s] (GUID: %u)", GetAccountId(), IP_str.c_str(), name.c_str(), GUID_LOPART(guid));
|
||||||
#endif
|
#endif
|
||||||
sLog->outChar("Account: %d (IP: %s) Delete Character:[%s] (GUID: %u)", GetAccountId(), IP_str.c_str(), name.c_str(), GUID_LOPART(guid));
|
sLog->outChar("Account: %d (IP: %s) Delete Character:[%s] (GUID: %u)", GetAccountId(), IP_str.c_str(), name.c_str(), GUID_LOPART(guid));
|
||||||
sScriptMgr->OnPlayerDelete(guid);
|
|
||||||
|
// To prevent hook failure, place hook before removing reference from DB
|
||||||
|
sScriptMgr->OnPlayerDelete(guid, initAccountId); // To prevent race conditioning, but as it also makes sense, we hand the accountId over for successful delete.
|
||||||
|
// Shouldn't interfere with character deletion though
|
||||||
|
|
||||||
if (sLog->IsOutCharDump()) // optimize GetPlayerDump call
|
if (sLog->IsOutCharDump()) // optimize GetPlayerDump call
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ template class ScriptRegistry<AllMapScript>;
|
|||||||
template class ScriptRegistry<MovementHandlerScript>;
|
template class ScriptRegistry<MovementHandlerScript>;
|
||||||
template class ScriptRegistry<BGScript>;
|
template class ScriptRegistry<BGScript>;
|
||||||
template class ScriptRegistry<SpellSC>;
|
template class ScriptRegistry<SpellSC>;
|
||||||
|
template class ScriptRegistry<AccountScript>;
|
||||||
|
|
||||||
#include "ScriptMgrMacros.h"
|
#include "ScriptMgrMacros.h"
|
||||||
|
|
||||||
@@ -205,6 +206,7 @@ void ScriptMgr::Unload()
|
|||||||
SCR_CLEAR(TransportScript);
|
SCR_CLEAR(TransportScript);
|
||||||
SCR_CLEAR(AchievementCriteriaScript);
|
SCR_CLEAR(AchievementCriteriaScript);
|
||||||
SCR_CLEAR(PlayerScript);
|
SCR_CLEAR(PlayerScript);
|
||||||
|
SCR_CLEAR(AccountScript);
|
||||||
SCR_CLEAR(GuildScript);
|
SCR_CLEAR(GuildScript);
|
||||||
SCR_CLEAR(GroupScript);
|
SCR_CLEAR(GroupScript);
|
||||||
SCR_CLEAR(GlobalScript);
|
SCR_CLEAR(GlobalScript);
|
||||||
@@ -1577,12 +1579,17 @@ void ScriptMgr::OnPlayerSave(Player * player)
|
|||||||
FOREACH_SCRIPT(PlayerScript)->OnSave(player);
|
FOREACH_SCRIPT(PlayerScript)->OnSave(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptMgr::OnPlayerDelete(uint64 guid)
|
void ScriptMgr::OnPlayerDelete(uint64 guid, uint32 accountId)
|
||||||
{
|
{
|
||||||
#ifdef ELUNA
|
#ifdef ELUNA
|
||||||
sEluna->OnDelete(GUID_LOPART(guid));
|
sEluna->OnDelete(GUID_LOPART(guid));
|
||||||
#endif
|
#endif
|
||||||
FOREACH_SCRIPT(PlayerScript)->OnDelete(guid);
|
FOREACH_SCRIPT(PlayerScript)->OnDelete(guid, accountId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptMgr::OnPlayerFailedDelete(uint64 guid, uint32 accountId)
|
||||||
|
{
|
||||||
|
FOREACH_SCRIPT(PlayerScript)->OnFailedDelete(guid, accountId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptMgr::OnPlayerBindToInstance(Player* player, Difficulty difficulty, uint32 mapid, bool permanent)
|
void ScriptMgr::OnPlayerBindToInstance(Player* player, Difficulty difficulty, uint32 mapid, bool permanent)
|
||||||
@@ -1704,6 +1711,37 @@ void ScriptMgr::OnFirstLogin(Player* player)
|
|||||||
FOREACH_SCRIPT(PlayerScript)->OnFirstLogin(player);
|
FOREACH_SCRIPT(PlayerScript)->OnFirstLogin(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Account
|
||||||
|
void ScriptMgr::OnAccountLogin(uint32 accountId)
|
||||||
|
{
|
||||||
|
FOREACH_SCRIPT(AccountScript)->OnAccountLogin(accountId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptMgr::OnFailedAccountLogin(uint32 accountId)
|
||||||
|
{
|
||||||
|
FOREACH_SCRIPT(AccountScript)->OnFailedAccountLogin(accountId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptMgr::OnEmailChange(uint32 accountId)
|
||||||
|
{
|
||||||
|
FOREACH_SCRIPT(AccountScript)->OnEmailChange(accountId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptMgr::OnFailedEmailChange(uint32 accountId)
|
||||||
|
{
|
||||||
|
FOREACH_SCRIPT(AccountScript)->OnFailedEmailChange(accountId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptMgr::OnPasswordChange(uint32 accountId)
|
||||||
|
{
|
||||||
|
FOREACH_SCRIPT(AccountScript)->OnPasswordChange(accountId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptMgr::OnFailedPasswordChange(uint32 accountId)
|
||||||
|
{
|
||||||
|
FOREACH_SCRIPT(AccountScript)->OnFailedPasswordChange(accountId);
|
||||||
|
}
|
||||||
|
|
||||||
// Guild
|
// Guild
|
||||||
void ScriptMgr::OnGuildAddMember(Guild* guild, Player* player, uint8& plRank)
|
void ScriptMgr::OnGuildAddMember(Guild* guild, Player* player, uint8& plRank)
|
||||||
{
|
{
|
||||||
@@ -2162,6 +2200,12 @@ PlayerScript::PlayerScript(const char* name)
|
|||||||
ScriptRegistry<PlayerScript>::AddScript(this);
|
ScriptRegistry<PlayerScript>::AddScript(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AccountScript::AccountScript(const char* name)
|
||||||
|
: ScriptObject(name)
|
||||||
|
{
|
||||||
|
ScriptRegistry<AccountScript>::AddScript(this);
|
||||||
|
}
|
||||||
|
|
||||||
GuildScript::GuildScript(const char* name)
|
GuildScript::GuildScript(const char* name)
|
||||||
: ScriptObject(name)
|
: ScriptObject(name)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -855,7 +855,10 @@ class PlayerScript : public ScriptObject
|
|||||||
virtual void OnCreate(Player* /*player*/) { }
|
virtual void OnCreate(Player* /*player*/) { }
|
||||||
|
|
||||||
// Called when a player is deleted.
|
// Called when a player is deleted.
|
||||||
virtual void OnDelete(uint64 /*guid*/) { }
|
virtual void OnDelete(uint64 /*guid*/, uint32 /*accountId*/) { }
|
||||||
|
|
||||||
|
// Called when a player delete failed.
|
||||||
|
virtual void OnFailedDelete(uint64 /*guid*/, uint32 /*accountId*/) { }
|
||||||
|
|
||||||
// Called when a player is about to be saved.
|
// Called when a player is about to be saved.
|
||||||
virtual void OnSave(Player* /*player*/) { }
|
virtual void OnSave(Player* /*player*/) { }
|
||||||
@@ -947,6 +950,38 @@ class PlayerScript : public ScriptObject
|
|||||||
virtual void OnFirstLogin(Player* /*player*/) { }
|
virtual void OnFirstLogin(Player* /*player*/) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class AccountScript : public ScriptObject
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
AccountScript(const char* name);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Called when an account logged in successfully
|
||||||
|
virtual void OnAccountLogin(uint32 /*accountId*/) { }
|
||||||
|
|
||||||
|
|
||||||
|
// Called when an account login failed
|
||||||
|
virtual void OnFailedAccountLogin(uint32 /*accountId*/) { }
|
||||||
|
|
||||||
|
|
||||||
|
// Called when Email is successfully changed for Account
|
||||||
|
virtual void OnEmailChange(uint32 /*accountId*/) { }
|
||||||
|
|
||||||
|
|
||||||
|
// Called when Email failed to change for Account
|
||||||
|
virtual void OnFailedEmailChange(uint32 /*accountId*/) { }
|
||||||
|
|
||||||
|
|
||||||
|
// Called when Password is successfully changed for Account
|
||||||
|
virtual void OnPasswordChange(uint32 /*accountId*/) { }
|
||||||
|
|
||||||
|
|
||||||
|
// Called when Password failed to change for Account
|
||||||
|
virtual void OnFailedPasswordChange(uint32 /*accountId*/) { }
|
||||||
|
};
|
||||||
|
|
||||||
class GuildScript : public ScriptObject
|
class GuildScript : public ScriptObject
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
@@ -1300,7 +1335,8 @@ class ScriptMgr
|
|||||||
void OnPlayerLogout(Player* player);
|
void OnPlayerLogout(Player* player);
|
||||||
void OnPlayerCreate(Player* player);
|
void OnPlayerCreate(Player* player);
|
||||||
void OnPlayerSave(Player* player);
|
void OnPlayerSave(Player* player);
|
||||||
void OnPlayerDelete(uint64 guid);
|
void OnPlayerDelete(uint64 guid, uint32 accountId);
|
||||||
|
void OnPlayerFailedDelete(uint64 guid, uint32 accountId);
|
||||||
void OnPlayerBindToInstance(Player* player, Difficulty difficulty, uint32 mapid, bool permanent);
|
void OnPlayerBindToInstance(Player* player, Difficulty difficulty, uint32 mapid, bool permanent);
|
||||||
void OnPlayerUpdateZone(Player* player, uint32 newZone, uint32 newArea);
|
void OnPlayerUpdateZone(Player* player, uint32 newZone, uint32 newArea);
|
||||||
void OnPlayerUpdateArea(Player* player, uint32 oldArea, uint32 newArea);
|
void OnPlayerUpdateArea(Player* player, uint32 oldArea, uint32 newArea);
|
||||||
@@ -1333,6 +1369,15 @@ class ScriptMgr
|
|||||||
void OnFirstLogin(Player* player);
|
void OnFirstLogin(Player* player);
|
||||||
void OnPlayerCompleteQuest(Player* player, Quest const* quest);
|
void OnPlayerCompleteQuest(Player* player, Quest const* quest);
|
||||||
|
|
||||||
|
public: /* AccountScript */
|
||||||
|
|
||||||
|
void OnAccountLogin(uint32 accountId);
|
||||||
|
void OnFailedAccountLogin(uint32 accountId);
|
||||||
|
void OnEmailChange(uint32 accountId);
|
||||||
|
void OnFailedEmailChange(uint32 accountId);
|
||||||
|
void OnPasswordChange(uint32 accountId);
|
||||||
|
void OnFailedPasswordChange(uint32 accountId);
|
||||||
|
|
||||||
public: /* GuildScript */
|
public: /* GuildScript */
|
||||||
|
|
||||||
void OnGuildAddMember(Guild* guild, Player* player, uint8& plRank);
|
void OnGuildAddMember(Guild* guild, Player* player, uint8& plRank);
|
||||||
|
|||||||
@@ -965,6 +965,7 @@ class WorldSession
|
|||||||
Player* _player;
|
Player* _player;
|
||||||
WorldSocket* m_Socket;
|
WorldSocket* m_Socket;
|
||||||
std::string m_Address;
|
std::string m_Address;
|
||||||
|
// std::string m_LAddress; // Last Attempted Remote Adress - we can not set attempted ip for a non-existing session!
|
||||||
|
|
||||||
AccountTypes _security;
|
AccountTypes _security;
|
||||||
bool _skipQueue;
|
bool _skipQueue;
|
||||||
|
|||||||
@@ -741,6 +741,7 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
|
|||||||
WorldPacket packet, SendAddonPacked;
|
WorldPacket packet, SendAddonPacked;
|
||||||
|
|
||||||
BigNumber k;
|
BigNumber k;
|
||||||
|
bool wardenActive = sWorld->getBoolConfig(CONFIG_WARDEN_ENABLED);
|
||||||
|
|
||||||
if (sWorld->IsClosed())
|
if (sWorld->IsClosed())
|
||||||
{
|
{
|
||||||
@@ -779,6 +780,7 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
|
|||||||
// Stop if the account is not found
|
// Stop if the account is not found
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
|
// We can not log here, as we do not know the account. Thus, no accountId.
|
||||||
packet.Initialize (SMSG_AUTH_RESPONSE, 1);
|
packet.Initialize (SMSG_AUTH_RESPONSE, 1);
|
||||||
packet << uint8 (AUTH_UNKNOWN_ACCOUNT);
|
packet << uint8 (AUTH_UNKNOWN_ACCOUNT);
|
||||||
|
|
||||||
@@ -795,21 +797,37 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
|
|||||||
if (expansion > world_expansion)
|
if (expansion > world_expansion)
|
||||||
expansion = world_expansion;
|
expansion = world_expansion;
|
||||||
|
|
||||||
|
// For hook purposes, we get Remoteaddress at this point
|
||||||
|
std::string address = GetRemoteAddress(); // Originally, this variable should be called address, but for some reason, that variable name was already on the core.
|
||||||
|
|
||||||
|
// As we don't know if attempted login process by ip works, we update last_attempt_ip right away
|
||||||
|
stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LAST_ATTEMPT_IP);
|
||||||
|
|
||||||
|
stmt->setString(0, address);
|
||||||
|
stmt->setString(1, account);
|
||||||
|
|
||||||
|
LoginDatabase.Execute(stmt);
|
||||||
|
// This also allows to check for possible "hack" attempts on account
|
||||||
|
|
||||||
|
// id has to be fetched at this point, so that first actual account response that fails can be logged
|
||||||
|
id = fields[0].GetUInt32();
|
||||||
|
|
||||||
///- Re-check ip locking (same check as in realmd).
|
///- Re-check ip locking (same check as in realmd).
|
||||||
if (fields[3].GetUInt8() == 1) // if ip is locked
|
if (fields[3].GetUInt8() == 1) // if ip is locked
|
||||||
{
|
{
|
||||||
if (strcmp (fields[2].GetCString(), GetRemoteAddress().c_str()))
|
if (strcmp (fields[2].GetCString(), address.c_str()))
|
||||||
{
|
{
|
||||||
packet.Initialize (SMSG_AUTH_RESPONSE, 1);
|
packet.Initialize (SMSG_AUTH_RESPONSE, 1);
|
||||||
packet << uint8 (AUTH_FAILED);
|
packet << uint8 (AUTH_FAILED);
|
||||||
SendPacket(packet);
|
SendPacket(packet);
|
||||||
|
|
||||||
sLog->outBasic ("WorldSocket::HandleAuthSession: Sent Auth Response (Account IP differs).");
|
sLog->outBasic ("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);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
id = fields[0].GetUInt32();
|
|
||||||
/*
|
/*
|
||||||
if (security > SEC_ADMINISTRATOR) // prevent invalid security settings in DB
|
if (security > SEC_ADMINISTRATOR) // prevent invalid security settings in DB
|
||||||
security = SEC_ADMINISTRATOR;
|
security = SEC_ADMINISTRATOR;
|
||||||
@@ -840,13 +858,13 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
|
|||||||
TotalTime = fields[10].GetUInt32();
|
TotalTime = fields[10].GetUInt32();
|
||||||
|
|
||||||
// Must be done before WorldSession is created
|
// Must be done before WorldSession is created
|
||||||
if (sWorld->getBoolConfig(CONFIG_WARDEN_ENABLED) && os != "Win" && os != "OSX")
|
if (wardenActive && os != "Win" && os != "OSX")
|
||||||
{
|
{
|
||||||
packet.Initialize(SMSG_AUTH_RESPONSE, 1);
|
packet.Initialize(SMSG_AUTH_RESPONSE, 1);
|
||||||
packet << uint8(AUTH_REJECT);
|
packet << uint8(AUTH_REJECT);
|
||||||
SendPacket(packet);
|
SendPacket(packet);
|
||||||
|
|
||||||
sLog->outError("WorldSocket::HandleAuthSession: Client %s attempted to log in using invalid client OS (%s).", GetRemoteAddress().c_str(), os.c_str());
|
sLog->outError("WorldSocket::HandleAuthSession: Client %s attempted to log in using invalid client OS (%s).", address.c_str(), os.c_str());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -871,7 +889,7 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
|
|||||||
stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BANS);
|
stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BANS);
|
||||||
|
|
||||||
stmt->setUInt32(0, id);
|
stmt->setUInt32(0, id);
|
||||||
stmt->setString(1, GetRemoteAddress());
|
stmt->setString(1, address);
|
||||||
|
|
||||||
PreparedQueryResult banresult = LoginDatabase.Query(stmt);
|
PreparedQueryResult banresult = LoginDatabase.Query(stmt);
|
||||||
|
|
||||||
@@ -882,6 +900,7 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
|
|||||||
SendPacket(packet);
|
SendPacket(packet);
|
||||||
|
|
||||||
sLog->outError("WorldSocket::HandleAuthSession: Sent Auth Response (Account banned).");
|
sLog->outError("WorldSocket::HandleAuthSession: Sent Auth Response (Account banned).");
|
||||||
|
sScriptMgr->OnFailedAccountLogin(id);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -900,6 +919,7 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
|
|||||||
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
|
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
|
||||||
sLog->outDetail("WorldSocket::HandleAuthSession: User tries to login but his security level is not enough");
|
sLog->outDetail("WorldSocket::HandleAuthSession: User tries to login but his security level is not enough");
|
||||||
#endif
|
#endif
|
||||||
|
sScriptMgr->OnFailedAccountLogin(id);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -914,8 +934,6 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
|
|||||||
sha.UpdateBigNumbers (&k, NULL);
|
sha.UpdateBigNumbers (&k, NULL);
|
||||||
sha.Finalize();
|
sha.Finalize();
|
||||||
|
|
||||||
std::string address = GetRemoteAddress();
|
|
||||||
|
|
||||||
if (memcmp (sha.GetDigest(), digest, 20))
|
if (memcmp (sha.GetDigest(), digest, 20))
|
||||||
{
|
{
|
||||||
packet.Initialize (SMSG_AUTH_RESPONSE, 1);
|
packet.Initialize (SMSG_AUTH_RESPONSE, 1);
|
||||||
@@ -943,8 +961,7 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
|
|||||||
if (result)
|
if (result)
|
||||||
isRecruiter = true;
|
isRecruiter = true;
|
||||||
|
|
||||||
// Update the last_ip in the database
|
// Update the last_ip in the database as it was successful for login
|
||||||
|
|
||||||
stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LAST_IP);
|
stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LAST_IP);
|
||||||
|
|
||||||
stmt->setString(0, address);
|
stmt->setString(0, address);
|
||||||
@@ -965,6 +982,7 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
|
|||||||
SendPacket(packet);
|
SendPacket(packet);
|
||||||
|
|
||||||
sLog->outError("WorldSocket::HandleAuthSession: World closed, denying client (%s).", address.c_str());
|
sLog->outError("WorldSocket::HandleAuthSession: World closed, denying client (%s).", address.c_str());
|
||||||
|
sScriptMgr->OnFailedAccountLogin(id);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -976,6 +994,7 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
|
|||||||
|
|
||||||
sLog->outError("WorldSocket::HandleAuthSession: Client %s requested connecting with realm id %u but this realm has id %u set in config.",
|
sLog->outError("WorldSocket::HandleAuthSession: Client %s requested connecting with realm id %u but this realm has id %u set in config.",
|
||||||
address.c_str(), realm, realmID);
|
address.c_str(), realm, realmID);
|
||||||
|
sScriptMgr->OnFailedAccountLogin(id);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -983,8 +1002,11 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
|
|||||||
m_Session->LoadTutorialsData();
|
m_Session->LoadTutorialsData();
|
||||||
m_Session->ReadAddonsInfo(recvPacket);
|
m_Session->ReadAddonsInfo(recvPacket);
|
||||||
|
|
||||||
|
// At this point, we can safely hook a successful login
|
||||||
|
sScriptMgr->OnAccountLogin(id);
|
||||||
|
|
||||||
// Initialize Warden system only if it is enabled by config
|
// Initialize Warden system only if it is enabled by config
|
||||||
if (sWorld->getBoolConfig(CONFIG_WARDEN_ENABLED))
|
if (wardenActive)
|
||||||
m_Session->InitWarden(&k, os);
|
m_Session->InitWarden(&k, os);
|
||||||
|
|
||||||
// Sleep this Network thread for
|
// Sleep this Network thread for
|
||||||
|
|||||||
@@ -1296,6 +1296,8 @@ void World::LoadConfigSettings(bool reload)
|
|||||||
m_bool_configs[CONFIG_ENABLE_CONTINENT_TRANSPORT] = sConfigMgr->GetBoolDefault("IsContinentTransport.Enabled", true);
|
m_bool_configs[CONFIG_ENABLE_CONTINENT_TRANSPORT] = sConfigMgr->GetBoolDefault("IsContinentTransport.Enabled", true);
|
||||||
m_bool_configs[CONFIG_ENABLE_CONTINENT_TRANSPORT_PRELOADING] = sConfigMgr->GetBoolDefault("IsPreloadedContinentTransport.Enabled", false);
|
m_bool_configs[CONFIG_ENABLE_CONTINENT_TRANSPORT_PRELOADING] = sConfigMgr->GetBoolDefault("IsPreloadedContinentTransport.Enabled", false);
|
||||||
|
|
||||||
|
m_bool_configs[CONFIG_IP_BASED_ACTION_LOGGING] = sConfigMgr->GetBoolDefault("Allow.IP.Based.Action.Logging", false);
|
||||||
|
|
||||||
m_bool_configs[CONFIG_CALCULATE_CREATURE_ZONE_AREA_DATA] = sConfigMgr->GetBoolDefault("Calculate.Creature.Zone.Area.Data", false);
|
m_bool_configs[CONFIG_CALCULATE_CREATURE_ZONE_AREA_DATA] = sConfigMgr->GetBoolDefault("Calculate.Creature.Zone.Area.Data", false);
|
||||||
m_bool_configs[CONFIG_CALCULATE_GAMEOBJECT_ZONE_AREA_DATA] = sConfigMgr->GetBoolDefault("Calculate.Gameoject.Zone.Area.Data", false);
|
m_bool_configs[CONFIG_CALCULATE_GAMEOBJECT_ZONE_AREA_DATA] = sConfigMgr->GetBoolDefault("Calculate.Gameoject.Zone.Area.Data", false);
|
||||||
|
|
||||||
|
|||||||
@@ -162,6 +162,7 @@ enum WorldBoolConfigs
|
|||||||
CONFIG_ENABLE_CONTINENT_TRANSPORT,
|
CONFIG_ENABLE_CONTINENT_TRANSPORT,
|
||||||
CONFIG_ENABLE_CONTINENT_TRANSPORT_PRELOADING,
|
CONFIG_ENABLE_CONTINENT_TRANSPORT_PRELOADING,
|
||||||
CONFIG_MINIGOB_MANABONK,
|
CONFIG_MINIGOB_MANABONK,
|
||||||
|
CONFIG_IP_BASED_ACTION_LOGGING,
|
||||||
CONFIG_CALCULATE_CREATURE_ZONE_AREA_DATA,
|
CONFIG_CALCULATE_CREATURE_ZONE_AREA_DATA,
|
||||||
CONFIG_CALCULATE_GAMEOBJECT_ZONE_AREA_DATA,
|
CONFIG_CALCULATE_GAMEOBJECT_ZONE_AREA_DATA,
|
||||||
BOOL_CONFIG_VALUE_COUNT
|
BOOL_CONFIG_VALUE_COUNT
|
||||||
|
|||||||
@@ -347,6 +347,7 @@ public:
|
|||||||
if (!AccountMgr::CheckPassword(handler->GetSession()->GetAccountId(), std::string(oldPassword)))
|
if (!AccountMgr::CheckPassword(handler->GetSession()->GetAccountId(), std::string(oldPassword)))
|
||||||
{
|
{
|
||||||
handler->SendSysMessage(LANG_COMMAND_WRONGOLDPASSWORD);
|
handler->SendSysMessage(LANG_COMMAND_WRONGOLDPASSWORD);
|
||||||
|
sScriptMgr->OnFailedPasswordChange(handler->GetSession()->GetAccountId());
|
||||||
handler->SetSentErrorMessage(true);
|
handler->SetSentErrorMessage(true);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -354,6 +355,7 @@ public:
|
|||||||
if (strcmp(newPassword, passwordConfirmation) != 0)
|
if (strcmp(newPassword, passwordConfirmation) != 0)
|
||||||
{
|
{
|
||||||
handler->SendSysMessage(LANG_NEW_PASSWORDS_NOT_MATCH);
|
handler->SendSysMessage(LANG_NEW_PASSWORDS_NOT_MATCH);
|
||||||
|
sScriptMgr->OnFailedPasswordChange(handler->GetSession()->GetAccountId());
|
||||||
handler->SetSentErrorMessage(true);
|
handler->SetSentErrorMessage(true);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -363,9 +365,11 @@ public:
|
|||||||
{
|
{
|
||||||
case AOR_OK:
|
case AOR_OK:
|
||||||
handler->SendSysMessage(LANG_COMMAND_PASSWORD);
|
handler->SendSysMessage(LANG_COMMAND_PASSWORD);
|
||||||
|
sScriptMgr->OnPasswordChange(handler->GetSession()->GetAccountId());
|
||||||
break;
|
break;
|
||||||
case AOR_PASS_TOO_LONG:
|
case AOR_PASS_TOO_LONG:
|
||||||
handler->SendSysMessage(LANG_PASSWORD_TOO_LONG);
|
handler->SendSysMessage(LANG_PASSWORD_TOO_LONG);
|
||||||
|
sScriptMgr->OnFailedPasswordChange(handler->GetSession()->GetAccountId());
|
||||||
handler->SetSentErrorMessage(true);
|
handler->SetSentErrorMessage(true);
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "ScriptLoader.h"
|
#include "ScriptLoader.h"
|
||||||
#include "ScriptMgr.h"
|
#include "ScriptMgr.h"
|
||||||
|
#include "World.h"
|
||||||
|
|
||||||
// spells
|
// spells
|
||||||
void AddSC_deathknight_spell_scripts();
|
void AddSC_deathknight_spell_scripts();
|
||||||
@@ -73,6 +74,7 @@ void AddSC_npc_innkeeper();
|
|||||||
void AddSC_npcs_special();
|
void AddSC_npcs_special();
|
||||||
void AddSC_npc_taxi();
|
void AddSC_npc_taxi();
|
||||||
void AddSC_achievement_scripts();
|
void AddSC_achievement_scripts();
|
||||||
|
void AddSC_action_ip_logger();
|
||||||
|
|
||||||
//events
|
//events
|
||||||
void AddSC_event_brewfest_scripts();
|
void AddSC_event_brewfest_scripts();
|
||||||
@@ -577,6 +579,7 @@ void AddSC_outdoorpvp_gh();
|
|||||||
// player
|
// player
|
||||||
void AddSC_chat_log();
|
void AddSC_chat_log();
|
||||||
void AddSC_character_creation();
|
void AddSC_character_creation();
|
||||||
|
void AddSC_action_ip_logger();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -650,8 +653,9 @@ void AddWorldScripts()
|
|||||||
AddSC_npcs_special();
|
AddSC_npcs_special();
|
||||||
AddSC_npc_taxi();
|
AddSC_npc_taxi();
|
||||||
AddSC_achievement_scripts();
|
AddSC_achievement_scripts();
|
||||||
AddSC_chat_log();
|
AddSC_chat_log(); // location: scripts\World\chat_log.cpp
|
||||||
AddSC_character_creation();
|
AddSC_character_creation();
|
||||||
|
AddSC_action_ip_logger(); // location: scripts\World\action_ip_logger.cpp
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ set(scripts_STAT_SRCS
|
|||||||
${AC_SCRIPTS_DIR}/World/npc_taxi.cpp
|
${AC_SCRIPTS_DIR}/World/npc_taxi.cpp
|
||||||
${AC_SCRIPTS_DIR}/World/npcs_special.cpp
|
${AC_SCRIPTS_DIR}/World/npcs_special.cpp
|
||||||
${AC_SCRIPTS_DIR}/World/character_creation.cpp
|
${AC_SCRIPTS_DIR}/World/character_creation.cpp
|
||||||
|
${AC_SCRIPTS_DIR}/World/action_ip_logger.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
AC_ADD_SCRIPT_LOADER("World" "ScriptLoader.h")
|
AC_ADD_SCRIPT_LOADER("World" "ScriptLoader.h")
|
||||||
|
|||||||
312
src/server/scripts/World/action_ip_logger.cpp
Normal file
312
src/server/scripts/World/action_ip_logger.cpp
Normal file
@@ -0,0 +1,312 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>
|
||||||
|
* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ScriptMgr.h"
|
||||||
|
#include "Channel.h"
|
||||||
|
#include "Guild.h"
|
||||||
|
#include "Group.h"
|
||||||
|
|
||||||
|
enum IPLoggingTypes
|
||||||
|
{
|
||||||
|
|
||||||
|
// AccountActionIpLogger();
|
||||||
|
ACCOUNT_LOGIN = 0,
|
||||||
|
ACCOUNT_FAIL_LOGIN = 1,
|
||||||
|
ACCOUNT_CHANGE_PW = 2,
|
||||||
|
ACCOUNT_CHANGE_PW_FAIL = 3, // Only two types of account changes exist...
|
||||||
|
ACCOUNT_CHANGE_EMAIL = 4,
|
||||||
|
ACCOUNT_CHANGE_EMAIL_FAIL = 5, // ...so we log them individually
|
||||||
|
// OBSOLETE - ACCOUNT_LOGOUT = 6, /* Can not be logged. We still keep the type however */
|
||||||
|
// CharacterActionIpLogger();
|
||||||
|
CHARACTER_CREATE = 7,
|
||||||
|
CHARACTER_LOGIN = 8,
|
||||||
|
CHARACTER_LOGOUT = 9,
|
||||||
|
// CharacterDeleteActionIpLogger();
|
||||||
|
CHARACTER_DELETE = 10,
|
||||||
|
CHARACTER_FAILED_DELETE = 11,
|
||||||
|
// AccountActionIpLogger(), CharacterActionIpLogger(), CharacterActionIpLogger();
|
||||||
|
UNKNOWN_ACTION = 12
|
||||||
|
};
|
||||||
|
|
||||||
|
class AccountActionIpLogger : public AccountScript
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AccountActionIpLogger() : AccountScript("AccountActionIpLogger") { }
|
||||||
|
|
||||||
|
// We log last_ip instead of last_attempt_ip, as login was successful
|
||||||
|
// ACCOUNT_LOGIN = 0
|
||||||
|
void OnAccountLogin(uint32 accountId) override
|
||||||
|
{
|
||||||
|
AccountIPLogAction(accountId, ACCOUNT_LOGIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We log last_attempt_ip instead of last_ip, as failed login doesn't necessarily mean approperiate user
|
||||||
|
// ACCOUNT_FAIL_LOGIN = 1
|
||||||
|
void OnFailedAccountLogin(uint32 accountId) override
|
||||||
|
{
|
||||||
|
AccountIPLogAction(accountId, ACCOUNT_FAIL_LOGIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ACCOUNT_CHANGE_PW = 2
|
||||||
|
void OnPasswordChange(uint32 accountId) override
|
||||||
|
{
|
||||||
|
AccountIPLogAction(accountId, ACCOUNT_CHANGE_PW);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ACCOUNT_CHANGE_PW_FAIL = 3
|
||||||
|
void OnFailedPasswordChange(uint32 accountId) override
|
||||||
|
{
|
||||||
|
AccountIPLogAction(accountId, ACCOUNT_CHANGE_PW_FAIL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Registration Email can NOT be changed apart from GM level users. Thus, we do not require to log them...
|
||||||
|
// ACCOUNT_CHANGE_EMAIL = 4
|
||||||
|
void OnEmailChange(uint32 accountId) override
|
||||||
|
{
|
||||||
|
AccountIPLogAction(accountId, ACCOUNT_CHANGE_EMAIL); // ... they get logged by gm command logger anyway
|
||||||
|
}
|
||||||
|
|
||||||
|
// ACCOUNT_CHANGE_EMAIL_FAIL = 5
|
||||||
|
void OnFailedEmailChange(uint32 accountId) override
|
||||||
|
{
|
||||||
|
AccountIPLogAction(accountId, ACCOUNT_CHANGE_EMAIL_FAIL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* It's impossible to log the account logout process out of character selection - shouldn't matter anyway,
|
||||||
|
* as ip doesn't change through playing (obviously).*/
|
||||||
|
// ACCOUNT_LOGOUT = 6
|
||||||
|
void AccountIPLogAction(uint32 accountId, IPLoggingTypes aType)
|
||||||
|
{
|
||||||
|
if (!sWorld->getBoolConfig(CONFIG_IP_BASED_ACTION_LOGGING))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Action IP Logger is only intialized if config is set up
|
||||||
|
// Else, this script isn't loaded in the first place: We require no config check.
|
||||||
|
|
||||||
|
// We declare all the required variables
|
||||||
|
uint32 playerGuid = accountId;
|
||||||
|
uint32 characterGuid = 0;
|
||||||
|
std::string systemNote = "ERROR"; // "ERROR" is a placeholder here. We change it later.
|
||||||
|
|
||||||
|
// With this switch, we change systemNote so that we have a more accurate phrasing of what type it is.
|
||||||
|
// Avoids Magicnumbers in SQL table
|
||||||
|
switch (aType)
|
||||||
|
{
|
||||||
|
case ACCOUNT_LOGIN:
|
||||||
|
systemNote = "Logged on Successful AccountLogin";
|
||||||
|
break;
|
||||||
|
case ACCOUNT_FAIL_LOGIN:
|
||||||
|
systemNote = "Logged on Failed AccountLogin";
|
||||||
|
break;
|
||||||
|
case ACCOUNT_CHANGE_PW:
|
||||||
|
systemNote = "Logged on Successful Account Password Change";
|
||||||
|
break;
|
||||||
|
case ACCOUNT_CHANGE_PW_FAIL:
|
||||||
|
systemNote = "Logged on Failed Account Password Change";
|
||||||
|
break;
|
||||||
|
case ACCOUNT_CHANGE_EMAIL:
|
||||||
|
systemNote = "Logged on Successful Account Email Change";
|
||||||
|
break;
|
||||||
|
case ACCOUNT_CHANGE_EMAIL_FAIL:
|
||||||
|
systemNote = "Logged on Failed Account Email Change";
|
||||||
|
break;
|
||||||
|
/*case ACCOUNT_LOGOUT:
|
||||||
|
systemNote = "Logged on AccountLogout"; //Can not be logged
|
||||||
|
break;*/
|
||||||
|
// Neither should happen. Ever. Period. If it does, call Ghostbusters and all your local software defences to investigate.
|
||||||
|
case UNKNOWN_ACTION:
|
||||||
|
default:
|
||||||
|
systemNote = "ERROR! Unknown action!";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Once we have done everything, we can insert the new log.
|
||||||
|
// Seeing as the time differences should be minimal, we do not get unixtime and the timestamp right now;
|
||||||
|
// Rather, we let it be added with the SQL query.
|
||||||
|
if (aType != ACCOUNT_FAIL_LOGIN)
|
||||||
|
{
|
||||||
|
// As we can assume most account actions are NOT failed login, so this is the more accurate check.
|
||||||
|
// For those, we need last_ip...
|
||||||
|
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_ALDL_IP_LOGGING);
|
||||||
|
|
||||||
|
stmt->setUInt32(0, playerGuid);
|
||||||
|
stmt->setUInt32(1, characterGuid);
|
||||||
|
stmt->setUInt8(2, aType);
|
||||||
|
stmt->setUInt32(3, playerGuid);
|
||||||
|
stmt->setString(4, systemNote.c_str());
|
||||||
|
LoginDatabase.Execute(stmt);
|
||||||
|
}
|
||||||
|
else // ... but for failed login, we query last_attempt_ip from account table. Which we do with an unique query
|
||||||
|
{
|
||||||
|
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_FACL_IP_LOGGING);
|
||||||
|
|
||||||
|
stmt->setUInt32(0, playerGuid);
|
||||||
|
stmt->setUInt32(1, characterGuid);
|
||||||
|
stmt->setUInt8(2, aType);
|
||||||
|
stmt->setUInt32(3, playerGuid);
|
||||||
|
stmt->setString(4, systemNote.c_str());
|
||||||
|
LoginDatabase.Execute(stmt);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CharacterActionIpLogger : public PlayerScript
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CharacterActionIpLogger() : PlayerScript("CharacterActionIpLogger") { }
|
||||||
|
|
||||||
|
// CHARACTER_CREATE = 7
|
||||||
|
void OnCreate(Player* player) override
|
||||||
|
{
|
||||||
|
CharacterIPLogAction(player, CHARACTER_CREATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHARACTER_LOGIN = 8
|
||||||
|
void OnLogin(Player* player) override
|
||||||
|
{
|
||||||
|
CharacterIPLogAction(player, CHARACTER_LOGIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHARACTER_LOGOUT = 9
|
||||||
|
void OnLogout(Player* player) override
|
||||||
|
{
|
||||||
|
CharacterIPLogAction(player, CHARACTER_LOGOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHARACTER_DELETE = 10
|
||||||
|
// CHARACTER_FAILED_DELETE = 11
|
||||||
|
// We don't log either here - they require a guid
|
||||||
|
|
||||||
|
// UNKNOWN_ACTION = 12
|
||||||
|
// There is no real hook we could use for that.
|
||||||
|
// Shouldn't happen anyway, should it ? Nothing to see here.
|
||||||
|
|
||||||
|
/// Logs a number of actions done by players with an IP
|
||||||
|
void CharacterIPLogAction(Player* player, IPLoggingTypes aType)
|
||||||
|
{
|
||||||
|
if (!sWorld->getBoolConfig(CONFIG_IP_BASED_ACTION_LOGGING))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Action IP Logger is only intialized if config is set up
|
||||||
|
// Else, this script isn't loaded in the first place: We require no config check.
|
||||||
|
|
||||||
|
// We declare all the required variables
|
||||||
|
uint32 playerGuid = player->GetSession()->GetAccountId();
|
||||||
|
uint32 characterGuid = player->GetGUIDLow();
|
||||||
|
const std::string currentIp = player->GetSession()->GetRemoteAddress();
|
||||||
|
std::string systemNote = "ERROR"; // "ERROR" is a placeholder here. We change it...
|
||||||
|
|
||||||
|
// ... with this switch, so that we have a more accurate phrasing of what type it is
|
||||||
|
switch (aType)
|
||||||
|
{
|
||||||
|
case CHARACTER_CREATE:
|
||||||
|
systemNote = "Logged on CharacterCreate";
|
||||||
|
break;
|
||||||
|
case CHARACTER_LOGIN:
|
||||||
|
systemNote = "Logged on CharacterLogin";
|
||||||
|
break;
|
||||||
|
case CHARACTER_LOGOUT:
|
||||||
|
systemNote = "Logged on CharacterLogout";
|
||||||
|
break;
|
||||||
|
case CHARACTER_DELETE:
|
||||||
|
systemNote = "Logged on CharacterDelete";
|
||||||
|
break;
|
||||||
|
case CHARACTER_FAILED_DELETE:
|
||||||
|
systemNote = "Logged on Failed CharacterDelete";
|
||||||
|
break;
|
||||||
|
// Neither should happen. Ever. Period. If it does, call Mythbusters.
|
||||||
|
case UNKNOWN_ACTION:
|
||||||
|
default:
|
||||||
|
systemNote = "ERROR! Unknown action!";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Once we have done everything, we can insert the new log.
|
||||||
|
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_CHAR_IP_LOGGING);
|
||||||
|
|
||||||
|
stmt->setUInt32(0, playerGuid);
|
||||||
|
stmt->setUInt32(1, characterGuid);
|
||||||
|
stmt->setUInt8(2, aType);
|
||||||
|
stmt->setString(3, currentIp.c_str()); // We query the ip here.
|
||||||
|
stmt->setString(4, systemNote.c_str());
|
||||||
|
// Seeing as the time differences should be minimal, we do not get unixtime and the timestamp right now;
|
||||||
|
// Rather, we let it be added with the SQL query.
|
||||||
|
|
||||||
|
LoginDatabase.Execute(stmt);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CharacterDeleteActionIpLogger : public PlayerScript
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CharacterDeleteActionIpLogger() : PlayerScript("CharacterDeleteActionIpLogger") { }
|
||||||
|
|
||||||
|
// CHARACTER_DELETE = 10
|
||||||
|
void OnDelete(uint64 guid, uint32 accountId) override
|
||||||
|
{
|
||||||
|
DeleteIPLogAction(guid, accountId, CHARACTER_DELETE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHARACTER_FAILED_DELETE = 11
|
||||||
|
void OnFailedDelete(uint64 guid, uint32 accountId) override
|
||||||
|
{
|
||||||
|
DeleteIPLogAction(guid, accountId, CHARACTER_FAILED_DELETE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeleteIPLogAction(uint64 guid, uint32 playerGuid, IPLoggingTypes aType)
|
||||||
|
{
|
||||||
|
if (!sWorld->getBoolConfig(CONFIG_IP_BASED_ACTION_LOGGING))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Action IP Logger is only intialized if config is set up
|
||||||
|
// Else, this script isn't loaded in the first place: We require no config check.
|
||||||
|
|
||||||
|
// We declare all the required variables
|
||||||
|
uint32 characterGuid = GUID_LOPART(guid); // We have no access to any member function of Player* or WorldSession*. So use old-fashioned way.
|
||||||
|
// Query playerGuid/accountId, as we only have characterGuid
|
||||||
|
std::string systemNote = "ERROR"; // "ERROR" is a placeholder here. We change it later.
|
||||||
|
|
||||||
|
// With this switch, we change systemNote so that we have a more accurate phrasing of what type it is.
|
||||||
|
// Avoids Magicnumbers in SQL table
|
||||||
|
switch (aType)
|
||||||
|
{
|
||||||
|
case CHARACTER_DELETE:
|
||||||
|
systemNote = "Logged on CharacterDelete";
|
||||||
|
break;
|
||||||
|
case CHARACTER_FAILED_DELETE:
|
||||||
|
systemNote = "Logged on Failed CharacterDelete";
|
||||||
|
break;
|
||||||
|
// Neither should happen. Ever. Period. If it does, call to whatever god you have for mercy and guidance.
|
||||||
|
case UNKNOWN_ACTION:
|
||||||
|
default:
|
||||||
|
systemNote = "ERROR! Unknown action!";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Once we have done everything, we can insert the new log.
|
||||||
|
PreparedStatement* stmt2 = LoginDatabase.GetPreparedStatement(LOGIN_INS_ALDL_IP_LOGGING);
|
||||||
|
|
||||||
|
stmt2->setUInt32(0, playerGuid);
|
||||||
|
stmt2->setUInt32(1, characterGuid);
|
||||||
|
stmt2->setUInt8(2, aType);
|
||||||
|
stmt2->setUInt32(3, playerGuid);
|
||||||
|
stmt2->setString(4, systemNote.c_str());
|
||||||
|
// Seeing as the time differences should be minimal, we do not get unixtime and the timestamp right now;
|
||||||
|
// Rather, we let it be added with the SQL query.
|
||||||
|
|
||||||
|
LoginDatabase.Execute(stmt2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void AddSC_action_ip_logger()
|
||||||
|
{
|
||||||
|
new AccountActionIpLogger();
|
||||||
|
new CharacterActionIpLogger();
|
||||||
|
new CharacterDeleteActionIpLogger();
|
||||||
|
}
|
||||||
@@ -3174,6 +3174,14 @@ MoveMaps.Enable = 1
|
|||||||
Minigob.Manabonk.Enable = 1
|
Minigob.Manabonk.Enable = 1
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# Allow.IP.Based.Action.Logging
|
||||||
|
# Description: Logs actions, e.g. account login and logout to name a few, based on IP of current session.
|
||||||
|
# Default: 0 - (Disabled)
|
||||||
|
# 1 - (Enabled)
|
||||||
|
|
||||||
|
Allow.IP.Based.Action.Logging = 0
|
||||||
|
|
||||||
# Calculate.Creature.Zone.Area.Data
|
# Calculate.Creature.Zone.Area.Data
|
||||||
# Description: Calculate at loading creature zoneId / areaId and save in creature table (WARNING: SLOW WORLD SERVER STARTUP)
|
# Description: Calculate at loading creature zoneId / areaId and save in creature table (WARNING: SLOW WORLD SERVER STARTUP)
|
||||||
# Default: 0 - (Do not show)
|
# Default: 0 - (Do not show)
|
||||||
|
|||||||
Reference in New Issue
Block a user