rendered paste bodyIndex: AccountHandler.h
===================================================================
--- AccountHandler.h (révision 0)
+++ AccountHandler.h (révision 0)
@@ -0,0 +1,58 @@
+#include "Common.h"
+
+struct Account
+{
+ uint32 id;
+ uint8 security;
+ uint8 locale;
+ bool tbc;
+ bool banned;
+ bool locked;
+ std::string name;
+ std::string I;
+ std::string LastIp;
+};
+
+struct BanIp
+{
+ std::string Ip;
+};
+
+struct RealmCharacter
+{
+ uint32 realmId;
+ uint32 acctId;
+ uint8 numChars;
+};
+
+class AcctContainer
+{
+ public:
+
+ AcctContainer();
+ Account* FindAccountById(uint32 acctid);
+ Account* FindAccountByName(std::string name);
+ bool IpBan(std::string ClientIp);
+ void LoadAll();
+ void ReloadEverythingIfNeed();
+ void Initialize(uint32 updateInterval);
+ void AddAccount(Account* account,uint32 id, uint8 security, uint8 locale, uint8 tbc, bool banned, uint8 locked, std::string name, std::string I, std::string lastip);
+ void AddCharacter(RealmCharacter* rcharacter, uint32 realmId, uint32 acctId, uint8 numChars);
+ void AddBan(BanIp* banip, std::string Ip){ banip->Ip = Ip; }
+ uint8 GetNumChar(uint32 realmId, uint32 accountId);
+
+ private:
+
+ typedef HM_NAMESPACE::hash_map<uint32, Account*> AccountList;
+ typedef std::map<std::string, BanIp*> IpBanList;
+ typedef HM_NAMESPACE::hash_map<uint32, RealmCharacter*> CharactersList;
+
+ AccountList m_accounts;
+ IpBanList m_banips;
+ CharactersList m_characters;
+
+ uint32 m_UpdateInterval;
+ time_t m_NextUpdateTime;
+};
+
+#define AcctMgr MaNGOS::Singleton<AcctContainer>::Instance()
Index: Main.cpp
===================================================================
--- Main.cpp (révision 5401)
+++ Main.cpp (copie de travail)
@@ -31,6 +31,8 @@
#include "SystemConfig.h"
#include "Util.h"
+#include "AccountHandler.h"
+
#ifdef WIN32
#include "ServiceWin32.h"
char serviceName[] = "realmd";
@@ -182,6 +184,15 @@
return 1;
}
+ // Activate or not account caching system, precache them before launching connection port
+ if(sConfig.GetIntDefault("AccountCaching", 0) == 1)
+ {
+ AcctMgr.Initialize(sConfig.GetIntDefault("AccountReloadingDelay", 300));
+ AcctMgr.ReloadEverythingIfNeed();
+ sLog.outString();
+ sLog.outString("Accounts will be reloaded in %u seconds", sConfig.GetIntDefault("AccountReloadingDelay", 300));
+ }
+
///- Launch the listening network socket
port_t rmport = sConfig.GetIntDefault( "RealmServerPort", DEFAULT_REALMSERVER_PORT );
std::string bind_ip = sConfig.GetStringDefault("BindIP", "0.0.0.0");
Index: Makefile.am
===================================================================
--- Makefile.am (révision 5401)
+++ Makefile.am (copie de travail)
@@ -27,7 +27,9 @@
AuthSocket.h \
Main.cpp \
RealmList.cpp \
- RealmList.h
+ RealmList.h \
+ AccountHandler.cpp \
+ AccountHandler.h
## Link realm list daemon against the shared library
mangos_realmd_LDADD = ../shared/Database/libmangosdatabase.a ../shared/Config/libmangosconfig.a ../shared/Auth/libmangosauth.a ../shared/libmangosshared.a ../framework/libmangosframework.a ../../dep/src/sockets/libmangossockets.a ../../dep/src/zthread/libZThread.la
Index: AuthSocket.cpp
===================================================================
--- AuthSocket.cpp (révision 5401)
+++ AuthSocket.cpp (copie de travail)
@@ -30,6 +30,9 @@
#include <cwctype> // needs for towupper
#include <openssl/md5.h>
#include "Auth/Sha1.h"
+#include "AccountHandler.h"
+#include "Config/ConfigEnv.h"
+#include <sstream>
extern RealmList m_realmList;
@@ -320,6 +323,8 @@
/// Logon Challenge command handler
bool AuthSocket::_HandleLogonChallenge()
{
+ AcctMgr.ReloadEverythingIfNeed();
+
DEBUG_LOG("Entering _HandleLogonChallenge");
if (ibuf.GetLength() < sizeof(sAuthLogonChallenge_C))
return false;
@@ -370,6 +375,8 @@
pkt << (uint8) AUTH_LOGON_CHALLENGE;
pkt << (uint8) 0x00;
+ if(sConfig.GetIntDefault("AccountCaching", 0) != 1)
+ {
///- Verify that this IP is not in the ip_banned table
// No SQL injection possible (paste the IP address as passed by the socket)
dbRealmServer.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate");
@@ -484,10 +491,98 @@
{
pkt<< (uint8) REALM_AUTH_NO_MATCH;
}
- }
- } //valid version
+ }
+ }
+ else
+ {
+ if(AcctMgr.IpBan(GetRemoteAddress()))
+ {
+ pkt << (uint8)REALM_AUTH_ACCOUNT_BANNED;
+ }
+ else
+ {
+ Account* acct = AcctMgr.FindAccountByName(_safelogin);
+
+ if(acct)
+ {
+ bool locked = false;
+
+ if(acct->locked == 1) // if ip is locked
+ {
+ if ( strcmp(acct->LastIp.c_str(),GetRemoteAddress().c_str()) )
+ {
+ pkt << (uint8) REALM_AUTH_ACCOUNT_FREEZED;
+ locked=true;
+ }
+ }
+
+ if (!locked)
+ {
+ if(acct->banned)
+ {
+ pkt << (uint8) REALM_AUTH_ACCOUNT_BANNED;
+ }
+ else
+ {
+ ///- Get the password from the account table, upper it, and make the SRP6 calculation
+ std::string rI = acct->I;
+ _SetVSFields(rI);
+ b.SetRand(19 * 8);
+ BigNumber gmod=g.ModExp(b, N);
+ B = ((v * 3) + gmod) % N;
+
+ if (B.GetNumBytes() < 32)
+ sLog.outDetail("Interesting, calculation of B in realmd is < 32.");
+
+ ASSERT(gmod.GetNumBytes() <= 32);
+
+ BigNumber unk3;
+ unk3.SetRand(16*8);
+
+ ///- Fill the response packet with the result
+ pkt << (uint8)REALM_AUTH_SUCCESS;
+ pkt.append(B.AsByteArray(), B.GetNumBytes());
+ pkt << (uint8)1;
+ pkt.append(g.AsByteArray(), 1);
+ pkt << (uint8)32;
+ pkt.append(N.AsByteArray(), 32);
+ pkt.append(s.AsByteArray(), s.GetNumBytes());
+ pkt.append(unk3.AsByteArray(), 16);
+ pkt << (uint8)0; // Added in 1.12.x client branch
+
+ uint8 secLevel = acct->security;
+ _accountSecurityLevel = secLevel <= SEC_ADMINISTRATOR ? AccountTypes(secLevel) : SEC_ADMINISTRATOR;
+
+ // There isn't many differents locale so i think we can hardcode them all
+
+ char charbuffer[3];
+ charbuffer[0] = ch->country[3];
+ charbuffer[1] = ch->country[2];
+ charbuffer[2] = '\0';
+
+ if(strcmp (charbuffer,"fr") == 0)
+ _localization = 2;
+ else if(strcmp (charbuffer,"de") == 0)
+ _localization = 3;
+ else
+ _localization = 0;
+
+ }
+ }
+ else
+ {
+ pkt << (uint8) REALM_AUTH_ACCOUNT_FREEZED;
+ }
+ }
+ else //no account
+ {
+ pkt<< (uint8) REALM_AUTH_NO_MATCH;
+ }
+ }
+ }
+ } //valid version
else
- ///<li> else
+ ///<li> else
{
///- Check if we have the apropriate patch on the disk
char tmp[64];
@@ -535,7 +630,7 @@
}
/// </ul>
SendBuf((char const*)pkt.contents(), pkt.size());
- return true;
+ return true;
}
/// Logon Proof command handler
@@ -661,9 +756,13 @@
ibuf.Remove(5);
+ std::string rI;
+ uint32 id;
+
+ if(sConfig.GetIntDefault("AccountCaching", 0) != 1)
+ {
///- Get the user id (else close the connection)
// No SQL injection (escaped user name)
-
QueryResult *result = dbRealmServer.PQuery("SELECT id,sha_pass_hash FROM account WHERE UPPER(username) = '%s'",_safelogin.c_str());
if(!result)
{
@@ -672,9 +771,16 @@
return false;
}
- uint32 id = (*result)[0].GetUInt32();
- std::string rI = (*result)[1].GetCppString();
+ id = (*result)[0].GetUInt32();
+ rI = (*result)[1].GetCppString();
delete result;
+ }
+ else
+ {
+ Account* acct = AcctMgr.FindAccountByName(_safelogin);
+ id = acct->id;
+ rI = acct->I;
+ }
///- Update realm list if need
m_realmList.UpdateIfNeed();
@@ -687,17 +793,22 @@
for( i = m_realmList.begin(); i != m_realmList.end(); i++ )
{
uint8 AmountOfCharacters;
-
- // No SQL injection. id of realm is controlled by the database.
- result = dbRealmServer.PQuery( "SELECT numchars FROM realmcharacters WHERE realmid = '%d' AND acctid='%u'",i->second.m_ID,id);
- if( result )
- {
- Field *fields = result->Fetch();
- AmountOfCharacters = fields[0].GetUInt8();
- delete result;
- }
- else
+ if(sConfig.GetIntDefault("AccountCaching", 0) != 1)
+ {
+ // No SQL injection. id of realm is controlled by the database.
+ QueryResult* result = dbRealmServer.PQuery( "SELECT numchars FROM realmcharacters WHERE realmid = '%d' AND acctid='%u'",i->second.m_ID,id);
+ if( result )
+ {
+ Field *fields = result->Fetch();
+ AmountOfCharacters = fields[0].GetUInt8();
+ delete result;
+ }
+ else
AmountOfCharacters = 0;
+ }
+ else
+ AmountOfCharacters = AcctMgr.GetNumChar(i->second.m_ID, id);
+
uint8 lock = (i->second.allowedSecurityLevel > _accountSecurityLevel) ? 1 : 0;
Index: AccountHandler.cpp
===================================================================
--- AccountHandler.cpp (révision 0)
+++ AccountHandler.cpp (révision 0)
@@ -0,0 +1,230 @@
+#include "Database/DatabaseEnv.h"
+#include "Policies/SingletonImp.h"
+#include "AccountHandler.h"
+#include "ProgressBar.h"
+
+#ifdef DO_POSTGRESQL
+extern DatabasePostgre dbRealmServer;
+#else
+extern DatabaseMysql dbRealmServer;
+#endif
+
+INSTANTIATE_SINGLETON_1( AcctContainer);
+
+AcctContainer::AcctContainer( ) : m_UpdateInterval(0), m_NextUpdateTime(time(NULL))
+{
+}
+
+void AcctContainer::Initialize(uint32 updateInterval)
+{
+ m_UpdateInterval = updateInterval;
+}
+
+void AcctContainer::AddAccount(Account* account,uint32 id, uint8 security, uint8 locale, uint8 tbc, bool banned, uint8 locked, std::string name, std::string I, std::string lastip)
+{
+ account->id = id;
+ account->security = security;
+ account->locale = locale;
+ account->tbc = tbc;
+ account->banned = banned;
+ account->locked = locked;
+ account->name = name;
+ account->I = I;
+ account->LastIp = lastip;
+}
+
+void AcctContainer::AddCharacter(RealmCharacter* rcharacter, uint32 realmId, uint32 acctId, uint8 numChars)
+{
+ rcharacter->realmId = realmId;
+ rcharacter->acctId = acctId;
+ rcharacter->numChars = numChars;
+}
+
+void AcctContainer::ReloadEverythingIfNeed()
+{
+ if(!m_UpdateInterval || m_NextUpdateTime > time(NULL))
+ return;
+
+ m_NextUpdateTime = time(NULL) + m_UpdateInterval;
+
+ // Clear maps
+ m_characters.clear();
+ m_banips.clear();
+ m_accounts.clear();
+
+ LoadAll();
+}
+
+void AcctContainer::LoadAll()
+{
+ // Load accounts
+ QueryResult* result = dbRealmServer.PQuery("SELECT id,username,sha_pass_hash,gmlevel,last_ip,locked,tbc,locale FROM account");
+
+ uint32 count = 0;
+
+ if(!result)
+ return;
+
+ sLog.outString();
+
+ sLog.outString("Loading Accounts In Progress...");
+
+ barGoLink bar( result->GetRowCount());
+
+ // Periodic Database Update ...
+ dbRealmServer.Execute("UPDATE account_banned SET active = 0 WHERE unbandate <= UNIX_TIMESTAMP() AND unbandate <> bandate");
+ dbRealmServer.Execute("DELETE FROM ip_banned WHERE unbandate <= UNIX_TIMESTAMP() AND unbandate <> bandate");
+
+ Account *acct;
+
+ do
+ {
+ Field *fields = result->Fetch();
+ bool banned = false;
+
+ bar.step();
+
+ QueryResult* banresult = dbRealmServer.PQuery("SELECT bandate,unbandate FROM account_banned WHERE id = %u AND active = 1", fields[0].GetUInt32());
+
+ if(banresult)
+ {
+ banned = true;
+ delete banresult;
+ }
+
+ // Create the account
+ acct = new Account();
+
+ AddAccount(acct, fields[0].GetUInt32(), fields[3].GetUInt8(), fields[7].GetUInt8(), fields[6].GetUInt8(), banned, fields[5].GetUInt8(), fields[1].GetCppString(), fields[2].GetCppString(), fields[4].GetCppString());
+
+ m_accounts[acct->id] = acct;
+
+ count++;
+
+ }while (result->NextRow());
+
+ sLog.outString();
+ sLog.outString(">> Loaded %u accounts", count);
+
+ delete result;
+
+ // Now load Ban by ip
+
+ result = dbRealmServer.PQuery("SELECT * FROM ip_banned");
+
+ BanIp* ban;
+
+ // If there is no ban don't load
+ if(result)
+ {
+ sLog.outString();
+
+ count = 0;
+
+ sLog.outString("Loading Ban Ip In Progress...");
+
+ barGoLink bar( result->GetRowCount());
+
+ do
+ {
+ Field *fields = result->Fetch();
+ bar.step();
+ ban = new BanIp();
+ AddBan(ban, fields[0].GetCppString());
+ m_banips[ban->Ip] = ban;
+ count++;
+
+ }while (result->NextRow());
+
+ delete result;
+ sLog.outString();
+
+ sLog.outString(">> Loaded %u ip banned", count);
+
+ count = 0;
+ }
+
+ // Now load Realm Characters
+
+ result = dbRealmServer.PQuery("SELECT * FROM realmcharacters");
+
+ RealmCharacter *realmcharacter;
+
+ // If there is no ban don't load
+ if(result)
+ {
+ sLog.outString();
+
+ count = 0;
+
+ sLog.outString("Loading Realm Characters In Progress...");
+
+ barGoLink bar( result->GetRowCount());
+
+ do
+ {
+ Field *fields = result->Fetch();
+
+ bar.step();
+
+ realmcharacter = new RealmCharacter();
+
+ AddCharacter(realmcharacter, fields[0].GetUInt32(), fields[1].GetUInt32(), fields[2].GetUInt8());
+
+ // Since nothing on this table is unique, order it by increment count value
+ m_characters[count] = realmcharacter;
+
+ count++;
+
+ }while (result->NextRow());
+
+ delete result;
+
+ sLog.outString();
+
+ sLog.outString(">> Loaded %u realm characters", count);
+ }
+
+
+}
+
+Account* AcctContainer::FindAccountById(uint32 acctid)
+{
+ AccountList::const_iterator itr = m_accounts.find(acctid);
+
+ if(itr != m_accounts.end())
+ return itr->second;
+}
+
+Account* AcctContainer::FindAccountByName(std::string name)
+{
+ for(AccountList::const_iterator itr = m_accounts.begin(); itr != m_accounts.end(); itr++)
+ {
+ if(!stricmp(itr->second->name.c_str(), name.c_str()))
+ return itr->second;
+ }
+
+ return NULL;
+}
+
+bool AcctContainer::IpBan(std::string ClientIp)
+{
+ for(IpBanList::const_iterator itr = m_banips.begin(); itr != m_banips.end(); itr++)
+ {
+ if(!stricmp(itr->second->Ip.c_str(), ClientIp.c_str()))
+ return true;
+ }
+
+ return false;
+}
+
+uint8 AcctContainer::GetNumChar(uint32 realmId, uint32 accountId)
+{
+ for(CharactersList::const_iterator itr = m_characters.begin(); itr != m_characters.end(); itr++)
+ {
+ if(itr->second->realmId == realmId && itr->second->acctId == accountId)
+ return itr->second->numChars;
+ }
+
+ return 0;
+}