Implement ip2nation and ip2nationCountries

This commit is contained in:
Nefertumm 2017-06-30 01:54:22 -03:00
parent ef57d9ba69
commit 9d2484bfc7
8 changed files with 143 additions and 7 deletions

View file

@ -20,6 +20,7 @@ CREATE TABLE `account`
`last_ip` varchar(15) NOT NULL DEFAULT '127.0.0.1',
`failed_logins` int(10) unsigned NOT NULL DEFAULT '0',
`locked` tinyint(3) unsigned NOT NULL DEFAULT '0',
`lock_country` varchar(2) NOT NULL DEFAULT '00',
`last_login` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`online` tinyint(3) unsigned NOT NULL DEFAULT '0',
`expansion` tinyint(3) unsigned NOT NULL DEFAULT '0',

View file

@ -0,0 +1,23 @@
INSERT INTO version_db_auth (`sql_rev`) VALUES ('1498796201292521600');
ALTER TABLE `account` ADD COLUMN `lock_country` VARCHAR(2) NOT NULL DEFAULT '00' AFTER `locked`;
DROP TABLE IF EXISTS ip2nation;
CREATE TABLE ip2nation (
ip int(11) unsigned NOT NULL default '0',
country char(2) NOT NULL default '',
KEY ip (ip)
);
DROP TABLE IF EXISTS ip2nationCountries;
CREATE TABLE ip2nationCountries (
code varchar(4) NOT NULL default '',
iso_code_2 varchar(2) NOT NULL default '',
iso_code_3 varchar(3) default '',
iso_country varchar(255) NOT NULL default '',
country varchar(255) NOT NULL default '',
lat float NOT NULL default '0',
lon float NOT NULL default '0',
PRIMARY KEY (code),
KEY code (code)
);

View file

@ -0,0 +1,9 @@
INSERT INTO version_db_world (`sql_rev`) VALUES ('1498796247453520600');
DROP TABLE IF EXISTS ip2nation;
DROP TABLE IF EXISTS ip2nationCountries;
DELETE FROM `command` WHERE `name` in ('account lock', 'account lock ip', 'account lock country');
INSERT INTO `command` (`name`,`security`,`help`) VALUES
('account lock ip', 0, 'Syntax: .account lock ip [on|off]\nAllow login from account only from current used IP or remove this requirement.'),
('account lock country', 0, 'Syntax: .account lock country [on|off]\nAllow login from account only from current used Country or remove this requirement.');

View file

@ -28,6 +28,7 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_UPD_VS, "UPDATE account SET v = ?, s = ? WHERE username = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_LOGONPROOF, "UPDATE account SET sessionkey = ?, last_ip = ?, last_login = NOW(), locale = ?, failed_logins = 0, os = ? WHERE username = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_LOGONCHALLENGE, "SELECT a.sha_pass_hash, a.id, a.locked, a.last_ip, aa.gmlevel, a.v, a.s FROM account a LEFT JOIN account_access aa ON (a.id = aa.id) WHERE a.username = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_LOGON_COUNTRY, "SELECT country FROM ip2nation WHERE ip < ? ORDER BY ip DESC LIMIT 0,1", CONNECTION_SYNCH);
PrepareStatement(LOGIN_UPD_FAILEDLOGINS, "UPDATE account SET failed_logins = failed_logins + 1 WHERE username = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_SEL_FAILEDLOGINS, "SELECT id, failed_logins FROM account WHERE username = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_ACCOUNT_ID_BY_NAME, "SELECT id FROM account WHERE username = ?", CONNECTION_SYNCH);
@ -49,6 +50,7 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_INS_REALM_CHARACTERS_INIT, "INSERT INTO realmcharacters (realmid, acctid, numchars) SELECT realmlist.id, account.id, 0 FROM realmlist, account LEFT JOIN realmcharacters ON acctid=account.id WHERE acctid IS NULL", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_EXPANSION, "UPDATE account SET expansion = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_ACCOUNT_LOCK, "UPDATE account SET locked = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_ACCOUNT_LOCK_CONTRY, "UPDATE account SET lock_country = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_USERNAME, "UPDATE account SET v = 0, s = 0, username = ?, sha_pass_hash = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_PASSWORD, "UPDATE account SET v = 0, s = 0, sha_pass_hash = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_MUTE_TIME, "UPDATE account SET mutetime = ? , mutereason = ? , muteby = ? WHERE id = ?", CONNECTION_ASYNC);
@ -76,5 +78,6 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_SEL_ACCOUNT_WHOIS, "SELECT username, email, last_ip FROM account 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_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);
}

View file

@ -46,6 +46,7 @@ enum LoginDatabaseStatements
LOGIN_UPD_VS,
LOGIN_UPD_LOGONPROOF,
LOGIN_SEL_LOGONCHALLENGE,
LOGIN_SEL_LOGON_COUNTRY,
LOGIN_UPD_FAILEDLOGINS,
LOGIN_SEL_FAILEDLOGINS,
LOGIN_SEL_ACCOUNT_ID_BY_NAME,
@ -69,6 +70,7 @@ enum LoginDatabaseStatements
LOGIN_INS_REALM_CHARACTERS_INIT,
LOGIN_UPD_EXPANSION,
LOGIN_UPD_ACCOUNT_LOCK,
LOGIN_UPD_ACCOUNT_LOCK_CONTRY,
LOGIN_UPD_USERNAME,
LOGIN_UPD_PASSWORD,
LOGIN_UPD_MUTE_TIME,
@ -96,6 +98,7 @@ enum LoginDatabaseStatements
LOGIN_SEL_ACCOUNT_WHOIS,
LOGIN_SEL_REALMLIST_SECURITY_LEVEL,
LOGIN_DEL_ACCOUNT,
LOGIN_SEL_IP2NATION_COUNTRY,
LOGIN_SEL_AUTOBROADCAST,
MAX_LOGINDATABASE_STATEMENTS

View file

@ -408,7 +408,7 @@ bool AuthSocket::_HandleLogonChallenge()
;//sLog->outDebug(LOG_FILTER_NETWORKIO, "[AuthChallenge] Account '%s' is locked to IP - '%s'", _login.c_str(), fields[3].GetCString());
;//sLog->outDebug(LOG_FILTER_NETWORKIO, "[AuthChallenge] Player address is '%s'", ip_address.c_str());
if (strcmp(fields[3].GetCString(), ip_address.c_str()) != 0)
if (strcmp(fields[4].GetCString(), ip_address.c_str()) != 0)
{
;//sLog->outDebug(LOG_FILTER_NETWORKIO, "[AuthChallenge] Account IP differs");
pkt << uint8(WOW_FAIL_LOCKED_ENFORCED);
@ -417,8 +417,36 @@ bool AuthSocket::_HandleLogonChallenge()
else
;//sLog->outDebug(LOG_FILTER_NETWORKIO, "[AuthChallenge] Account IP matches");
}
else
else
{
;//sLog->outDebug(LOG_FILTER_NETWORKIO, "[AuthChallenge] Account '%s' is not locked to ip", _login.c_str());
std::string accountCountry = fields[3].GetString();
if (accountCountry.empty() || accountCountry == "00")
;//sLog->outDebug(LOG_FILTER_NETWORKIO, "[AuthChallenge] Account '%s' is not locked to country", _login.c_str());
else if (!accountCountry.empty())
{
uint32 ip = inet_addr(ip_address.c_str());
EndianConvertReverse(ip);
stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_LOGON_COUNTRY);
stmt->setUInt32(0, ip);
if (PreparedQueryResult sessionCountryQuery = LoginDatabase.Query(stmt))
{
std::string loginCountry = (*sessionCountryQuery)[0].GetString();
;//sLog->outDebug(LOG_FILTER_NETWORKIO, "[AuthChallenge] Account '%s' is locked to country: '%s' Player country is '%s'", _login.c_str(), accountCountry.c_str(), loginCountry.c_str());
if (loginCountry != accountCountry)
{
;//sLog->outDebug(LOG_FILTER_NETWORKIO, "[AuthChallenge] Account country differs.");
pkt << uint8(WOW_FAIL_UNLOCKABLE_LOCK);
locked = true;
}
else
;//sLog->outDebug(LOG_FILTER_NETWORKIO, "[AuthChallenge] Account country matches");
}
else
;//sLog->outDebug(LOG_FILTER_NETWORKIO, "[AuthChallenge] IP2NATION Table empty");
}
}
if (!locked)
{
@ -448,8 +476,8 @@ bool AuthSocket::_HandleLogonChallenge()
std::string rI = fields[0].GetString();
// Don't calculate (v, s) if there are already some in the database
std::string databaseV = fields[5].GetString();
std::string databaseS = fields[6].GetString();
std::string databaseV = fields[6].GetString();
std::string databaseS = fields[7].GetString();
;//sLog->outDebug(LOG_FILTER_NETWORKIO, "database authentication values: v='%s' s='%s'", databaseV.c_str(), databaseS.c_str());
@ -506,7 +534,7 @@ bool AuthSocket::_HandleLogonChallenge()
if (securityFlags & 0x04) // Security token input
pkt << uint8(1);
uint8 secLevel = fields[4].GetUInt8();
uint8 secLevel = fields[5].GetUInt8();
_accountSecurityLevel = secLevel <= SEC_ADMINISTRATOR ? AccountTypes(secLevel) : SEC_ADMINISTRATOR;
_localizationName.resize(4);

View file

@ -30,13 +30,18 @@ public:
{ "gmlevel", SEC_CONSOLE, true, &HandleAccountSetGmLevelCommand, "" },
{ "password", SEC_CONSOLE, true, &HandleAccountSetPasswordCommand, "" }
};
static std::vector<ChatCommand> accountLockCommandTable
{
{ "country", SEC_PLAYER, true, &HandleAccountLockCountryCommand, "" },
{ "ip", SEC_PLAYER, true, &HandleAccountLockIpCommand, "" }
};
static std::vector<ChatCommand> accountCommandTable =
{
{ "addon", SEC_MODERATOR, false, &HandleAccountAddonCommand, "" },
{ "create", SEC_CONSOLE, true, &HandleAccountCreateCommand, "" },
{ "delete", SEC_CONSOLE, true, &HandleAccountDeleteCommand, "" },
{ "onlinelist", SEC_CONSOLE, true, &HandleAccountOnlineListCommand, "" },
{ "lock", SEC_PLAYER, false, &HandleAccountLockCommand, "" },
{ "lock", SEC_PLAYER, false, nullptr, "", accountLockCommandTable },
{ "set", SEC_ADMINISTRATOR, true, nullptr, "", accountSetCommandTable },
{ "password", SEC_PLAYER, false, &HandleAccountPasswordCommand, "" },
{ "", SEC_PLAYER, false, &HandleAccountCommand, "" }
@ -230,7 +235,59 @@ public:
return true;
}
static bool HandleAccountLockCommand(ChatHandler* handler, char const* args)
static bool HandleAccountLockCountryCommand(ChatHandler* handler, char const* args)
{
if (!*args)
{
handler->SendSysMessage(LANG_USE_BOL);
handler->SetSentErrorMessage(true);
return false;
}
std::string param = (char*)args;
if (!param.empty())
{
if (param == "on")
{
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_LOGON_COUNTRY);
uint32 ip = inet_addr(handler->GetSession()->GetRemoteAddress().c_str());
EndianConvertReverse(ip);
stmt->setUInt32(0, ip);
PreparedQueryResult result = LoginDatabase.Query(stmt);
if (result)
{
Field* fields = result->Fetch();
std::string country = fields[0].GetString();
stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_ACCOUNT_LOCK_CONTRY);
stmt->setString(0, country);
stmt->setUInt32(1, handler->GetSession()->GetAccountId());
LoginDatabase.Execute(stmt);
handler->PSendSysMessage(LANG_COMMAND_ACCLOCKLOCKED);
}
else
{
handler->PSendSysMessage("[IP2NATION] Table empty");
;//sLog->outDebug(LOG_FILTER_NETWORKIO, "[IP2NATION] Table empty");
}
}
else if (param == "off")
{
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_ACCOUNT_LOCK_CONTRY);
stmt->setString(0, "00");
stmt->setUInt32(1, handler->GetSession()->GetAccountId());
LoginDatabase.Execute(stmt);
handler->PSendSysMessage(LANG_COMMAND_ACCLOCKUNLOCKED);
}
return true;
}
handler->SendSysMessage(LANG_USE_BOL);
handler->SetSentErrorMessage(true);
return false;
}
static bool HandleAccountLockIpCommand(ChatHandler* handler, char const* args)
{
if (!*args)
{

View file

@ -1883,7 +1883,19 @@ public:
#if TRINITY_ENDIAN == BIGENDIAN
EndianConvertReverse(ip);
#endif
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_IP2NATION_COUNTRY);
stmt->setUInt32(0, ip);
PreparedQueryResult result2 = WorldDatabase.Query(stmt);
if (result2)
{
Field* fields2 = result2->Fetch();
lastIp.append(" (");
lastIp.append(fields2[0].GetString());
lastIp.append(")");
}
}
else
{