Skip to content

Instantly share code, notes, and snippets.

@Bezo
Last active December 15, 2015 02:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Bezo/5190738 to your computer and use it in GitHub Desktop.
Save Bezo/5190738 to your computer and use it in GitHub Desktop.
account lock.
diff --git a/sql/updates/2013_03_xx_xx_auth_misc.sql b/sql/updates/2013_03_xx_xx_auth_misc.sql
new file mode 100644
index 0000000..31c50e7
--- /dev/null
+++ b/sql/updates/2013_03_xx_xx_auth_misc.sql
@@ -0,0 +1,43 @@
+ALTER TABLE `account`
+ DROP COLUMN `lock_country`;
+
+ALTER TABLE `account`
+ ADD COLUMN `lock_country` CHAR(2) NOT NULL DEFAULT '' AFTER `locked`;
+
+-- add ip2nation to auth/releam db
+-- Table structure for table `ip2nation`
+DROP TABLE IF EXISTS `ip2nation`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `ip2nation` (
+ `ip` int(10) unsigned NOT NULL DEFAULT '0',
+ `country` char(2) NOT NULL DEFAULT '',
+ KEY `ip` (`ip`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+-- Dumping data for table `ip2nation`
+LOCK TABLES `ip2nation` WRITE;
+/*!40000 ALTER TABLE `ip2nation` DISABLE KEYS */;
+/*!40000 ALTER TABLE `ip2nation` ENABLE KEYS */;
+UNLOCK TABLES;
+-- Table structure for table `ip2nationCountries`
+DROP TABLE IF EXISTS `ip2nationCountries`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+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`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+-- Dumping data for table `ip2nationCountries`
+LOCK TABLES `ip2nationCountries` WRITE;
+/*!40000 ALTER TABLE `ip2nationCountries` DISABLE KEYS */;
+/*!40000 ALTER TABLE `ip2nationCountries` ENABLE KEYS */;
+UNLOCK TABLES;
diff --git a/sql/updates/2013_03_xx_xx_world_command.sql b/sql/updates/2013_03_xx_xx_world_command.sql
new file mode 100644
index 0000000..c76736c
--- /dev/null
+++ b/sql/updates/2013_03_xx_xx_world_command.sql
@@ -0,0 +1,4 @@
+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.');
diff --git a/src/server/authserver/Server/AuthSocket.cpp b/src/server/authserver/Server/AuthSocket.cpp
index 32ddf02..4076ae3 100644
--- a/src/server/authserver/Server/AuthSocket.cpp
+++ b/src/server/authserver/Server/AuthSocket.cpp
@@ -386,7 +386,7 @@ bool AuthSocket::_HandleLogonChallenge()
sLog->outDebug(LOG_FILTER_AUTHSERVER, "[AuthChallenge] Account '%s' is locked to IP - '%s'", _login.c_str(), fields[3].GetCString());
sLog->outDebug(LOG_FILTER_AUTHSERVER, "[AuthChallenge] Player address is '%s'", ip_address.c_str());
- if (strcmp(fields[3].GetCString(), ip_address.c_str()))
+ if (strcmp(fields[4].GetCString(), ip_address.c_str()))
{
sLog->outDebug(LOG_FILTER_AUTHSERVER, "[AuthChallenge] Account IP differs");
pkt << (uint8) WOW_FAIL_SUSPENDED;
@@ -396,7 +396,54 @@ bool AuthSocket::_HandleLogonChallenge()
sLog->outDebug(LOG_FILTER_AUTHSERVER, "[AuthChallenge] Account IP matches");
}
else
+ {
sLog->outDebug(LOG_FILTER_AUTHSERVER, "[AuthChallenge] Account '%s' is not locked to ip", _login.c_str());
+ std::string contry = fields[3].GetString();
+ if (contry == "00")
+ sLog->outDebug(LOG_FILTER_AUTHSERVER, "[AuthChallenge] Account '%s' is not locked to country", _login.c_str());
+ else if (!contry.empty())
+ {
+ stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_LOGON_COUNTRY);
+ uint32 ip = inet_addr(ip_address.c_str());
+ EndianConvertReverse(ip);
+ stmt->setUInt32(0, ip);
+ PreparedQueryResult placontres = LoginDatabase.Query(stmt);
+ if (placontres)
+ {
+ std::string contry2 = (*placontres)[0].GetString();
+ sLog->outDebug(LOG_FILTER_AUTHSERVER, "[AuthChallenge] Account '%s' is locked to country: '%s' Player country is '%s'", _login.c_str(), contry.c_str(), contry2.c_str());
+ if (contry2 != contry)
+ {
+ sLog->outDebug(LOG_FILTER_AUTHSERVER, "[AuthChallenge] Account country diff.");
+ pkt << (uint8) WOW_FAIL_UNLOCKABLE_LOCK;
+ locked = true;
+ }
+ else
+ sLog->outDebug(LOG_FILTER_AUTHSERVER, "[AuthChallenge] Account country matches");
+ }
+ else
+ sLog->outDebug(LOG_FILTER_AUTHSERVER, "[AuthChallenge]IP2NATION Table empty");
+ }
+ else // if null then insert country as default lock.
+ {
+ stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_LOGON_COUNTRY);
+ uint32 ip = inet_addr(ip_address.c_str());
+ EndianConvertReverse(ip);
+ stmt->setUInt32(0, ip);
+ PreparedQueryResult placontres = LoginDatabase.Query(stmt);
+ if (placontres)
+ {
+ std::string contry2 = (*placontres)[0].GetString();
+ stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_ACCOUNT_LOCK_CONTRY);
+ stmt->setString(0, contry2);
+ stmt->setUInt32(1, fields[1].GetUInt32());
+ LoginDatabase.Execute(stmt);
+ sLog->outDebug(LOG_FILTER_AUTHSERVER, "[AuthChallenge] Country: '%s' set for account: '%s'", contry2.c_str(), _login.c_str());
+ }
+ else
+ sLog->outDebug(LOG_FILTER_AUTHSERVER, "[AuthChallenge]IP2NATION Table empty");
+ }
+ }
if (!locked)
{
@@ -426,8 +473,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());
@@ -484,7 +531,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);
diff --git a/src/server/scripts/Commands/cs_account.cpp b/src/server/scripts/Commands/cs_account.cpp
index 3953bea..cf2816c 100644
--- a/src/server/scripts/Commands/cs_account.cpp
+++ b/src/server/scripts/Commands/cs_account.cpp
@@ -42,13 +42,19 @@ class account_commandscript : public CommandScript
{ "password", SEC_CONSOLE, true, &HandleAccountSetPasswordCommand, "", NULL },
{ NULL, SEC_PLAYER, false, NULL, "", NULL }
};
+ static ChatCommand accountLockCommandTable[] =
+ {
+ { "country", SEC_PLAYER, true, &HandleAccountLockCountryCommand, "", NULL },
+ { "ip", SEC_PLAYER, true, &HandleAccountLockIpCommand, "", NULL },
+ { NULL, SEC_PLAYER, false, NULL, "", NULL },
+ };
static ChatCommand accountCommandTable[] =
{
{ "addon", SEC_MODERATOR, false, &HandleAccountAddonCommand, "", NULL },
{ "create", SEC_CONSOLE, true, &HandleAccountCreateCommand, "", NULL },
{ "delete", SEC_CONSOLE, true, &HandleAccountDeleteCommand, "", NULL },
{ "onlinelist", SEC_CONSOLE, true, &HandleAccountOnlineListCommand, "", NULL },
- { "lock", SEC_PLAYER, false, &HandleAccountLockCommand, "", NULL },
+ { "lock", SEC_PLAYER, false, NULL, "", accountLockCommandTable },
{ "set", SEC_ADMINISTRATOR, true, NULL, "", accountSetCommandTable },
{ "password", SEC_PLAYER, false, &HandleAccountPasswordCommand, "", NULL },
{ "", SEC_PLAYER, false, &HandleAccountCommand, "", NULL },
@@ -245,7 +251,57 @@ class account_commandscript : public CommandScript
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_AUTHSERVER, "[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)
{
diff --git a/src/server/shared/Database/Implementation/LoginDatabase.cpp b/src/server/shared/Database/Implementation/LoginDatabase.cpp
index a23294a..ab6df25 100644
--- a/src/server/shared/Database/Implementation/LoginDatabase.cpp
+++ b/src/server/shared/Database/Implementation/LoginDatabase.cpp
@@ -37,7 +37,8 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_SEL_SESSIONKEY, "SELECT a.sessionkey, a.id, aa.gmlevel FROM account a LEFT JOIN account_access aa ON (a.id = aa.id) WHERE username = ?", CONNECTION_SYNCH);
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_ASYNC);
- 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_LOGONCHALLENGE, "SELECT a.sha_pass_hash, a.id, a.locked, a.lock_country, 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);
@@ -59,6 +60,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_INS_LOG, "INSERT INTO logs (time, realm, type, level, string) VALUES (?, ?, ?, ?, ?)", 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);
diff --git a/src/server/shared/Database/Implementation/LoginDatabase.h b/src/server/shared/Database/Implementation/LoginDatabase.h
index 939cc4b..a12282e 100644
--- a/src/server/shared/Database/Implementation/LoginDatabase.h
+++ b/src/server/shared/Database/Implementation/LoginDatabase.h
@@ -56,6 +56,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,
@@ -79,6 +80,7 @@ enum LoginDatabaseStatements
LOGIN_INS_REALM_CHARACTERS_INIT,
LOGIN_UPD_EXPANSION,
LOGIN_UPD_ACCOUNT_LOCK,
+ LOGIN_UPD_ACCOUNT_LOCK_CONTRY,
LOGIN_INS_LOG,
LOGIN_UPD_USERNAME,
LOGIN_UPD_PASSWORD,
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment