feat(Common/IPLocation): replace ip2nation by ip2location (#5653)

This commit is contained in:
Kargatum
2021-06-18 03:02:08 +07:00
committed by GitHub
parent 8ba1ddb033
commit 3da83cc0e6
17 changed files with 306 additions and 167 deletions

View File

@@ -1,28 +0,0 @@
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
DROP TABLE IF EXISTS `ip2nation`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = UTF8MB4 */;
CREATE TABLE `ip2nation`
(
`ip` INT unsigned NOT NULL DEFAULT 0,
`country` char(2) NOT NULL DEFAULT '',
KEY `ip` (`ip`)
) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4;
/*!40101 SET character_set_client = @saved_cs_client */;
LOCK TABLES `ip2nation` WRITE;
/*!40000 ALTER TABLE `ip2nation` DISABLE KEYS */;
/*!40000 ALTER TABLE `ip2nation` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

View File

@@ -1,34 +0,0 @@
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
DROP TABLE IF EXISTS `ip2nationCountries`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = UTF8MB4 */;
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=UTF8MB4;
/*!40101 SET character_set_client = @saved_cs_client */;
LOCK TABLES `ip2nationCountries` WRITE;
/*!40000 ALTER TABLE `ip2nationCountries` DISABLE KEYS */;
/*!40000 ALTER TABLE `ip2nationCountries` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

View File

@@ -0,0 +1,5 @@
INSERT INTO `version_db_auth` (`sql_rev`) VALUES ('1620146306002634000');
--
DROP TABLE IF EXISTS `ip2nation`;
DROP TABLE IF EXISTS `ip2nationCountries`;

View File

@@ -0,0 +1,120 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
* Copyright (C) 2021+ WarheadCore <https://github.com/WarheadCore>
*/
#include "IPLocation.h"
#include "Common.h"
#include "Config.h"
#include "Errors.h"
#include "IpAddress.h"
#include "Log.h"
#include "StringConvert.h"
#include <fstream>
#include <iostream>
IpLocationStore::IpLocationStore()
{
}
IpLocationStore::~IpLocationStore()
{
}
void IpLocationStore::Load()
{
_ipLocationStore.clear();
LOG_INFO("server.loading", "Loading IP Location Database...");
std::string databaseFilePath = sConfigMgr->GetOption<std::string>("IPLocationFile", "");
if (databaseFilePath.empty())
{
LOG_INFO("server.loading", " ");
return;
}
// Check if file exists
std::ifstream databaseFile(databaseFilePath);
if (!databaseFile)
{
LOG_ERROR("server.loading", "IPLocation: No ip database file exists (%s).", databaseFilePath.c_str());
return;
}
if (!databaseFile.is_open())
{
LOG_ERROR("server.loading", "IPLocation: Ip database file (%s) can not be opened.", databaseFilePath.c_str());
return;
}
std::string ipFrom;
std::string ipTo;
std::string countryCode;
std::string countryName;
while (databaseFile.good())
{
// Read lines
if (!std::getline(databaseFile, ipFrom, ','))
break;
if (!std::getline(databaseFile, ipTo, ','))
break;
if (!std::getline(databaseFile, countryCode, ','))
break;
if (!std::getline(databaseFile, countryName, '\n'))
break;
// Remove new lines and return
countryName.erase(std::remove(countryName.begin(), countryName.end(), '\r'), countryName.end());
countryName.erase(std::remove(countryName.begin(), countryName.end(), '\n'), countryName.end());
// Remove quotation marks
ipFrom.erase(std::remove(ipFrom.begin(), ipFrom.end(), '"'), ipFrom.end());
ipTo.erase(std::remove(ipTo.begin(), ipTo.end(), '"'), ipTo.end());
countryCode.erase(std::remove(countryCode.begin(), countryCode.end(), '"'), countryCode.end());
countryName.erase(std::remove(countryName.begin(), countryName.end(), '"'), countryName.end());
// Convert country code to lowercase
std::transform(countryCode.begin(), countryCode.end(), countryCode.begin(), ::tolower);
auto IpFrom = Acore::StringTo<uint32>(ipFrom);
auto IpTo = Acore::StringTo<uint32>(ipTo);
if (!IpFrom || !IpTo)
continue;
_ipLocationStore.emplace_back(*IpFrom, *IpTo, std::move(countryCode), std::move(countryName));
}
std::sort(_ipLocationStore.begin(), _ipLocationStore.end(), [](IpLocationRecord const& a, IpLocationRecord const& b) { return a.IpFrom < b.IpFrom; });
ASSERT(std::is_sorted(_ipLocationStore.begin(), _ipLocationStore.end(), [](IpLocationRecord const& a, IpLocationRecord const& b) { return a.IpFrom < b.IpTo; }),
"Overlapping IP ranges detected in database file");
databaseFile.close();
LOG_INFO("server.loading", ">> Loaded %u ip location entries.", static_cast<uint32>(_ipLocationStore.size()));
LOG_INFO("server.loading", " ");
}
IpLocationRecord const* IpLocationStore::GetLocationRecord(std::string const& ipAddress) const
{
uint32 ip = Acore::Net::address_to_uint(Acore::Net::make_address_v4(ipAddress));
auto itr = std::upper_bound(_ipLocationStore.begin(), _ipLocationStore.end(), ip, [](uint32 ip, IpLocationRecord const& loc) { return ip < loc.IpTo; });
if (itr == _ipLocationStore.end())
{
return nullptr;
}
if (ip < itr->IpFrom)
{
return nullptr;
}
return &(*itr);
}
IpLocationStore* IpLocationStore::instance()
{
static IpLocationStore instance;
return &instance;
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
* Copyright (C) 2021+ WarheadCore <https://github.com/WarheadCore>
*/
#include "Define.h"
#include <string>
#include <vector>
struct IpLocationRecord
{
IpLocationRecord() :
IpFrom(0), IpTo(0) { }
IpLocationRecord(uint32 ipFrom, uint32 ipTo, std::string countryCode, std::string countryName) :
IpFrom(ipFrom), IpTo(ipTo), CountryCode(std::move(countryCode)), CountryName(std::move(countryName)) { }
uint32 IpFrom;
uint32 IpTo;
std::string CountryCode;
std::string CountryName;
};
class AC_COMMON_API IpLocationStore
{
public:
IpLocationStore();
~IpLocationStore();
static IpLocationStore* instance();
void Load();
IpLocationRecord const* GetLocationRecord(std::string const& ipAddress) const;
private:
std::vector<IpLocationRecord> _ipLocationStore;
};
#define sIPLocation IpLocationStore::instance()

View File

@@ -12,29 +12,29 @@
* authentication server
*/
#include "AppenderDB.h"
#include "Banner.h"
#include "Common.h"
#include "AppenderDB.h"
#include "DatabaseEnv.h"
#include "Config.h"
#include "Log.h"
#include "GitRevision.h"
#include "Util.h"
#include "SignalHandler.h"
#include "RealmList.h"
#include "RealmAcceptor.h"
#include "DatabaseEnv.h"
#include "DatabaseLoader.h"
#include "GitRevision.h"
#include "IPLocation.h"
#include "Log.h"
#include "RealmAcceptor.h"
#include "RealmList.h"
#include "SecretMgr.h"
#include "SharedDefines.h"
#include "SignalHandler.h"
#include "Util.h"
#include "ProcessPriority.h"
#include <ace/Dev_Poll_Reactor.h>
#include <ace/TP_Reactor.h>
#include <ace/ACE.h>
#include <ace/Dev_Poll_Reactor.h>
#include <ace/Sig_Handler.h>
#include <ace/TP_Reactor.h>
#include <boost/version.hpp>
#include <openssl/opensslv.h>
#include <openssl/crypto.h>
#include <openssl/opensslv.h>
#ifndef _ACORE_REALM_CONFIG
#define _ACORE_REALM_CONFIG "authserver.conf"
@@ -128,6 +128,9 @@ extern int main(int argc, char** argv)
sSecretMgr->Initialize();
// Load IP Location Database
sIPLocation->Load();
// Get the list of realms for the server
sRealmList->Initialize(sConfigMgr->GetOption<int32>("RealmsStateUpdateDelay", 20));
if (sRealmList->GetRealms().empty())

View File

@@ -14,6 +14,7 @@
#include "CryptoHash.h"
#include "CryptoRandom.h"
#include "DatabaseEnv.h"
#include "IPLocation.h"
#include "Log.h"
#include "RealmList.h"
#include "SecretMgr.h"
@@ -419,31 +420,20 @@ bool AuthSocket::_HandleLogonChallenge()
}
else
{
LOG_DEBUG("network", "[AuthChallenge] Account '%s' is not locked to ip", _accountInfo.Login.c_str());
if (IpLocationRecord const* location = sIPLocation->GetLocationRecord(ipAddress))
_ipCountry = location->CountryCode;
LOG_DEBUG("server.authserver", "[AuthChallenge] Account '%s' is not locked to ip", _accountInfo.Login.c_str());
if (_accountInfo.LockCountry.empty() || _accountInfo.LockCountry == "00")
LOG_DEBUG("server.authserver", "[AuthChallenge] Account '%s' is not locked to country", _accountInfo.Login.c_str());
else if (!_ipCountry.empty())
{
LOG_DEBUG("network", "[AuthChallenge] Account '%s' is not locked to country", _accountInfo.Login.c_str());
}
else if (!_accountInfo.LockCountry.empty())
{
uint32 ip = inet_addr(ipAddress.c_str());
EndianConvertReverse(ip);
stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_LOGON_COUNTRY);
stmt->setUInt32(0, ip);
if (PreparedQueryResult sessionCountryQuery = LoginDatabase.Query(stmt))
LOG_DEBUG("server.authserver", "[AuthChallenge] Account '%s' is locked to country: '%s' Player country is '%s'", _accountInfo.Login.c_str(), _accountInfo.LockCountry.c_str(), _ipCountry.c_str());
if (_ipCountry != _accountInfo.LockCountry)
{
std::string loginCountry = (*sessionCountryQuery)[0].GetString();
LOG_DEBUG("network", "[AuthChallenge] Account '%s' is locked to country: '%s' Player country is '%s'", _accountInfo.Login.c_str(), _accountInfo.LockCountry.c_str(), loginCountry.c_str());
if (loginCountry != _accountInfo.LockCountry)
{
LOG_DEBUG("network", "[AuthChallenge] Account country differs.");
pkt << uint8(WOW_FAIL_UNLOCKABLE_LOCK);
SendAuthPacket();
return true;
}
pkt << uint8(WOW_FAIL_UNLOCKABLE_LOCK);
SendAuthPacket();
return true;
}
}
}

View File

@@ -89,6 +89,7 @@ private:
// between enUS and enGB, which is important for the patch system
std::string _localizationName;
std::string _os;
std::string _ipCountry;
uint16 _build;
uint8 _expversion;
};

View File

@@ -134,6 +134,15 @@ WrongPass.BanType = 0
WrongPass.Logging = 0
#
# IPLocationFile
# Description: The path to your IP2Location database CSV file.
# Example: "C:/acore/IP2LOCATION-LITE-DB1.CSV"
# "/home/acore/IP2LOCATION-LITE-DB1.CSV"
# Default: "" - (Disabled)
IPLocationFile = ""
#
###################################################################################################

View File

@@ -35,7 +35,6 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_DEL_ACCOUNT_BANNED, "DELETE FROM account_banned WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_LOGON, "UPDATE account SET salt = ?, verifier = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_LOGONPROOF, "UPDATE account SET session_key = ?, last_ip = ?, last_login = NOW(), locale = ?, failed_logins = 0, os = ? WHERE 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);
@@ -56,7 +55,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_ACCOUNT_LOCK_COUNTRY, "UPDATE account SET lock_country = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_USERNAME, "UPDATE account SET username = ? 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);
@@ -87,7 +86,6 @@ void LoginDatabaseConnection::DoPrepareStatements()
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_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);
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);

View File

@@ -45,7 +45,6 @@ enum LoginDatabaseStatements
LOGIN_UPD_LOGONPROOF,
LOGIN_SEL_LOGONCHALLENGE,
LOGIN_SEL_RECONNECTCHALLENGE,
LOGIN_SEL_LOGON_COUNTRY,
LOGIN_UPD_FAILEDLOGINS,
LOGIN_SEL_FAILEDLOGINS,
LOGIN_SEL_ACCOUNT_ID_BY_NAME,
@@ -69,7 +68,7 @@ enum LoginDatabaseStatements
LOGIN_INS_REALM_CHARACTERS_INIT,
LOGIN_UPD_EXPANSION,
LOGIN_UPD_ACCOUNT_LOCK,
LOGIN_UPD_ACCOUNT_LOCK_CONTRY,
LOGIN_UPD_ACCOUNT_LOCK_COUNTRY,
LOGIN_UPD_USERNAME,
LOGIN_UPD_MUTE_TIME,
LOGIN_UPD_MUTE_TIME_LOGIN,
@@ -98,7 +97,6 @@ enum LoginDatabaseStatements
LOGIN_SEL_ACCOUNT_WHOIS,
LOGIN_SEL_REALMLIST_SECURITY_LEVEL,
LOGIN_DEL_ACCOUNT,
LOGIN_SEL_IP2NATION_COUNTRY,
LOGIN_SEL_AUTOBROADCAST,
LOGIN_SEL_LAST_ATTEMPT_IP,
LOGIN_SEL_LAST_IP,

View File

@@ -11,6 +11,7 @@
#include "CryptoHash.h"
#include "CryptoRandom.h"
#include "DatabaseEnv.h"
#include "IPLocation.h"
#include "Log.h"
#include "Opcodes.h"
#include "PacketLog.h"
@@ -25,13 +26,13 @@
#include "WorldSocket.h"
#include "WorldSocketMgr.h"
#include <ace/Message_Block.h>
#include <ace/OS_NS_string.h>
#include <ace/OS_NS_unistd.h>
#include <ace/Reactor.h>
#include <ace/os_include/arpa/os_inet.h>
#include <ace/os_include/netinet/os_tcp.h>
#include <ace/os_include/sys/os_socket.h>
#include <ace/os_include/sys/os_types.h>
#include <ace/OS_NS_string.h>
#include <ace/OS_NS_unistd.h>
#include <ace/Reactor.h>
#include <thread>
#ifdef ELUNA
@@ -921,8 +922,8 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
return -1;
}
/*if (IpLocationRecord const* location = sIPLocation->GetLocationRecord(address))
_ipCountry = location->CountryCode;*/
if (IpLocationRecord const* location = sIPLocation->GetLocationRecord(address))
_ipCountry = location->CountryCode;
///- Re-check ip locking (same check as in auth).
if (account.IsLockedToIP)
@@ -938,18 +939,18 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
return -1;
}
}
//else if (!account.LockCountry.empty() && account.LockCountry != "00" && !_ipCountry.empty())
//{
// if (account.LockCountry != _ipCountry)
// {
// packet.Initialize(SMSG_AUTH_RESPONSE, 1);
// packet << uint8(AUTH_REJECT);
// LOG_DEBUG("network", "WorldSocket::HandleAuthSession: Sent Auth Response (Account country differs. Original country: %s, new country: %s).", account.LockCountry.c_str(), _ipCountry.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(account.Id);
// return -1;
// }
//}
else if (!account.LockCountry.empty() && account.LockCountry != "00" && !_ipCountry.empty())
{
if (account.LockCountry != _ipCountry)
{
packet.Initialize(SMSG_AUTH_RESPONSE, 1);
packet << uint8(AUTH_REJECT);
LOG_DEBUG("network", "WorldSocket::HandleAuthSession: Sent Auth Response (Account country differs. Original country: %s, new country: %s).", account.LockCountry.c_str(), _ipCountry.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(account.Id);
return -1;
}
}
if (account.IsBanned)
{

View File

@@ -191,6 +191,8 @@ private:
bool m_OutActive;
std::array<uint8, 4> m_Seed;
std::string _ipCountry;
};
#endif /* _WORLDSOCKET_H */

View File

@@ -41,6 +41,7 @@
#include "GuildMgr.h"
#include "InstanceSaveMgr.h"
#include "ItemEnchantmentMgr.h"
#include "IPLocation.h"
#include "Language.h"
#include "LFGMgr.h"
#include "Log.h"
@@ -1503,6 +1504,9 @@ void World::SetInitialWorldSettings()
LoadDBCStores(m_dataPath);
DetectDBCLang();
// Load IP Location Database
sIPLocation->Load();
std::vector<uint32> mapIds;
for (auto const& map : sMapStore)
mapIds.emplace_back(map->MapID);

View File

@@ -16,6 +16,7 @@ EndScriptData */
#include "Base32.h"
#include "Chat.h"
#include "CryptoGenerics.h"
#include "IPLocation.h"
#include "Language.h"
#include "Player.h"
#include "Realm.h"
@@ -23,8 +24,8 @@ EndScriptData */
#include "SecretMgr.h"
#include "StringConvert.h"
#include "TOTP.h"
#include <unordered_map>
#include <openssl/rand.h>
#include <unordered_map>
class account_commandscript : public CommandScript
{
@@ -35,35 +36,41 @@ public:
{
static std::vector<ChatCommand> accountSetCommandTable =
{
{ "addon", SEC_GAMEMASTER, true, &HandleAccountSetAddonCommand, "" },
{ "gmlevel", SEC_CONSOLE, true, &HandleAccountSetGmLevelCommand, "" },
{ "password", SEC_CONSOLE, true, &HandleAccountSetPasswordCommand, "" },
{ "2fa", SEC_PLAYER, true, &HandleAccountSet2FACommand, "" }
{ "addon", SEC_GAMEMASTER, true, &HandleAccountSetAddonCommand, "" },
{ "gmlevel", SEC_CONSOLE, true, &HandleAccountSetGmLevelCommand, "" },
{ "password", SEC_CONSOLE, true, &HandleAccountSetPasswordCommand, "" },
{ "2fa", SEC_PLAYER, true, &HandleAccountSet2FACommand, "" }
};
static std::vector<ChatCommand> accountLockCommandTable
{
{ "country", SEC_PLAYER, true, &HandleAccountLockCountryCommand, "" },
{ "ip", SEC_PLAYER, true, &HandleAccountLockIpCommand, "" }
{ "country", SEC_PLAYER, true, &HandleAccountLockCountryCommand, "" },
{ "ip", SEC_PLAYER, true, &HandleAccountLockIpCommand, "" }
};
static std::vector<ChatCommand> account2faCommandTable
{
{ "setup", SEC_PLAYER, false, &HandleAccount2FASetupCommand, "" },
{ "remove", SEC_PLAYER, false, &HandleAccount2FARemoveCommand, "" },
{ "setup", SEC_PLAYER, false, &HandleAccount2FASetupCommand, "" },
{ "remove", SEC_PLAYER, false, &HandleAccount2FARemoveCommand, "" },
};
static std::vector<ChatCommand> accountRemoveCommandTable
{
{ "country", SEC_ADMINISTRATOR, true, &HandleAccountRemoveLockCountryCommand, "" }
};
static std::vector<ChatCommand> accountCommandTable =
{
{ "2fa", SEC_PLAYER, true, nullptr, "", account2faCommandTable },
{ "addon", SEC_MODERATOR, false, &HandleAccountAddonCommand, "" },
{ "create", SEC_CONSOLE, true, &HandleAccountCreateCommand, "" },
{ "delete", SEC_CONSOLE, true, &HandleAccountDeleteCommand, "" },
{ "onlinelist", SEC_CONSOLE, true, &HandleAccountOnlineListCommand, "" },
{ "lock", SEC_PLAYER, false, nullptr, "", accountLockCommandTable },
{ "set", SEC_ADMINISTRATOR, true, nullptr, "", accountSetCommandTable },
{ "password", SEC_PLAYER, false, &HandleAccountPasswordCommand, "" },
{ "", SEC_PLAYER, false, &HandleAccountCommand, "" }
{ "2fa", SEC_PLAYER, true, nullptr, "", account2faCommandTable },
{ "addon", SEC_MODERATOR, false, &HandleAccountAddonCommand, "" },
{ "create", SEC_CONSOLE, true, &HandleAccountCreateCommand, "" },
{ "delete", SEC_CONSOLE, true, &HandleAccountDeleteCommand, "" },
{ "onlinelist", SEC_CONSOLE, true, &HandleAccountOnlineListCommand, "" },
{ "lock", SEC_PLAYER, false, nullptr, "", accountLockCommandTable },
{ "set", SEC_ADMINISTRATOR, true, nullptr, "", accountSetCommandTable },
{ "password", SEC_PLAYER, false, &HandleAccountPasswordCommand, "" },
{ "remove", SEC_ADMINISTRATOR, true, nullptr, "", accountRemoveCommandTable },
{ "", SEC_PLAYER, false, &HandleAccountCommand, "" }
};
static std::vector<ChatCommand> commandTable =
@@ -412,6 +419,45 @@ public:
return true;
}
static bool HandleAccountRemoveLockCountryCommand(ChatHandler* handler, char const* args)
{
if (!*args)
{
handler->SendSysMessage(LANG_CMD_SYNTAX);
handler->SetSentErrorMessage(true);
return false;
}
///- %Parse the command line arguments
char* _accountName = strtok((char*)args, " ");
if (!_accountName)
return false;
std::string accountName = _accountName;
if (!Utf8ToUpperOnlyLatin(accountName))
{
handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str());
handler->SetSentErrorMessage(true);
return false;
}
uint32 accountId = AccountMgr::GetId(accountName);
if (!accountId)
{
handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str());
handler->SetSentErrorMessage(true);
return false;
}
auto* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_ACCOUNT_LOCK_COUNTRY);
stmt->setString(0, "00");
stmt->setUInt32(1, accountId);
LoginDatabase.Execute(stmt);
handler->PSendSysMessage(LANG_COMMAND_ACCLOCKUNLOCKED);
return true;
}
static bool HandleAccountLockCountryCommand(ChatHandler* handler, char const* args)
{
if (!*args)
@@ -427,30 +473,24 @@ public:
{
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)
if (IpLocationRecord const* location = sIPLocation->GetLocationRecord(handler->GetSession()->GetRemoteAddress()))
{
Field* fields = result->Fetch();
std::string country = fields[0].GetString();
stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_ACCOUNT_LOCK_CONTRY);
stmt->setString(0, country);
auto* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_ACCOUNT_LOCK_COUNTRY);
stmt->setString(0, location->CountryCode);
stmt->setUInt32(1, handler->GetSession()->GetAccountId());
LoginDatabase.Execute(stmt);
handler->PSendSysMessage(LANG_COMMAND_ACCLOCKLOCKED);
}
else
{
handler->PSendSysMessage("[IP2NATION] Table empty");
;//LOG_DEBUG("network", "[IP2NATION] Table empty");
handler->PSendSysMessage("No IP2Location information - account not locked");
handler->SetSentErrorMessage(true);
return false;
}
}
else if (param == "off")
{
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_ACCOUNT_LOCK_CONTRY);
auto* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_ACCOUNT_LOCK_COUNTRY);
stmt->setString(0, "00");
stmt->setUInt32(1, handler->GetSession()->GetAccountId());
LoginDatabase.Execute(stmt);

View File

@@ -16,6 +16,7 @@
#include "GroupMgr.h"
#include "GuildMgr.h"
#include "InstanceSaveMgr.h"
#include "IPLocation.h"
#include "Language.h"
#include "LFG.h"
#include "MapManager.h"
@@ -1928,29 +1929,11 @@ public:
lastIp = fields[4].GetString();
lastLogin = fields[5].GetString();
/** if (IpLocationRecord const* location = sIPLocation->GetLocationRecord(lastIp))
if (IpLocationRecord const* location = sIPLocation->GetLocationRecord(lastIp))
{
lastIp.append(" (");
lastIp.append(location->CountryName);
lastIp.append(")");
} **/
uint32 ip = inet_addr(lastIp.c_str());
#if ACORE_ENDIAN == BIGENDIAN
EndianConvertReverse(ip);
#endif
stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_IP2NATION_COUNTRY);
stmt->setUInt32(0, ip);
PreparedQueryResult result2 = LoginDatabase.Query(stmt);
if (result2)
{
Field* fields2 = result2->Fetch();
lastIp.append(" (");
lastIp.append(fields2[0].GetString());
lastIp.append(")");
}
}
else

View File

@@ -157,6 +157,16 @@ WorldServerPort = 8085
BindIP = "0.0.0.0"
#
# IPLocationFile
# Description: The path to your IP2Location database CSV file.
# Example: "C:/acore/IP2LOCATION-LITE-DB1.CSV"
# "/home/acore/IP2LOCATION-LITE-DB1.CSV"
# Default: "" - (Disabled)
#
IPLocationFile = ""
#
###################################################################################################