mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-21 20:56:23 +00:00
feat(Common/IPLocation): replace ip2nation by ip2location (#5653)
This commit is contained in:
@@ -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 */;
|
||||
|
||||
@@ -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 */;
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
INSERT INTO `version_db_auth` (`sql_rev`) VALUES ('1620146306002634000');
|
||||
|
||||
--
|
||||
DROP TABLE IF EXISTS `ip2nation`;
|
||||
DROP TABLE IF EXISTS `ip2nationCountries`;
|
||||
120
src/common/IPLocation/IPLocation.cpp
Normal file
120
src/common/IPLocation/IPLocation.cpp
Normal 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;
|
||||
}
|
||||
37
src/common/IPLocation/IPLocation.h
Normal file
37
src/common/IPLocation/IPLocation.h
Normal 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()
|
||||
@@ -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())
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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 = ""
|
||||
|
||||
#
|
||||
###################################################################################################
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -191,6 +191,8 @@ private:
|
||||
bool m_OutActive;
|
||||
|
||||
std::array<uint8, 4> m_Seed;
|
||||
|
||||
std::string _ipCountry;
|
||||
};
|
||||
|
||||
#endif /* _WORLDSOCKET_H */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = ""
|
||||
|
||||
#
|
||||
###################################################################################################
|
||||
|
||||
|
||||
Reference in New Issue
Block a user