Index: AuthSocket.h =================================================================== --- AuthSocket.h (révision 5401) +++ AuthSocket.h (copie de travail) @@ -53,6 +53,11 @@ bool _HandleXferCancel(); bool _HandleXferAccept(); + bool _HandleInformationRetrieveAnsw(); + bool _HandleGMLevelAnsw(); + bool _HandleBanIPAnsw(); + bool _HandleRealmCharsAnsw(); + void _SetVSFields(std::string rI); FILE *pPatch; Index: SpecialCodes.h =================================================================== --- SpecialCodes.h (révision 0) +++ SpecialCodes.h (révision 0) @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** \file + \ingroup realmd +*/ + +#ifndef _SPECIALCODES_H +#define _SPECIALCODES_H + +enum eRealmSendCmds +{ + REALM_SEND_ACCT_INFOS = 0x100, + REALM_SEND_BANIP_STATUS = 0x101 +}; + +enum eRealmReceivedCmds +{ + REALM_RECV_ACCT_INFOS_ANSW = 0x102, + REALM_RECV_ACCT_BANIP_ANSW = 0x103, + REALM_RECV_ACCT_MOD_INFOS = 0x104, + REALM_RECV_ACCT_ADD_BANIP = 0x105, + REALM_RECV_ACCT_RM_BANIP = 0x106, + REALM_RECV_ACCT_ADD_BANACCT = 0x107, + REALM_RECV_ACCT_RM_BANACCT = 0x108, + REALM_RECV_ACCT_ADDACCOUNT = 0x109, + REALM_RECV_ACCT_DELACCOUNT = 0x110 +}; +#endif 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,10 @@ AuthSocket.h \ Main.cpp \ RealmList.cpp \ - RealmList.h + RealmList.h \ + AccountHandler.cpp \ + AccountHandler.h \ + SpecialCodes.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,10 @@ #include // needs for towupper #include #include "Auth/Sha1.h" +#include "AccountHandler.h" +#include "Config/ConfigEnv.h" +#include +#include "SpecialCodes.h" extern RealmList m_realmList; @@ -156,6 +160,12 @@ bool (AuthSocket::*handler)(void); }AuthHandler; +typedef struct SpecialCodesHandler +{ + eRealmReceivedCmds cmd; + bool (AuthSocket::*handler)(void); +}SpecialCodesHandler; + // GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some paltform #if defined( __GNUC__ ) #pragma pack() @@ -206,7 +216,24 @@ { XFER_CANCEL, STATUS_CONNECTED, &AuthSocket::_HandleXferCancel } }; +const SpecialCodesHandler sptable[] = +{ + { REALM_RECV_ACCT_INFOS_ANSW, &AuthSocket::_HandleInformationRetrieveAnsw}, + { REALM_RECV_ACCT_BANIP_ANSW, &AuthSocket::_HandleBanIPAnsw } + + // Reserved for future implementation of features like ban without waiting reload time etc + /*{ REALM_RECV_ACCT_MOD_INFOS, + { REALM_RECV_ACCT_ADD_BANIP, + { REALM_RECV_ACCT_RM_BANIP, + { REALM_RECV_ACCT_ADD_BANACCT, + { REALM_RECV_ACCT_RM_BANACCT, + { REALM_RECV_ACCT_MOD_REALMCHARS, + { REALM_RECV_ACCT_ADDACCOUNT, + { REALM_RECV_ACCT_DELACCOUNT,*/ +}; + #define AUTH_TOTAL_COMMANDS sizeof(table)/sizeof(AuthHandler) +#define TOTAL_SPECIAL_COMMANDS sizeof(sptable)/sizeof(SpecialCodesHandler) ///Holds the MD5 hash of client patches present on the server Patcher PatchesCache; @@ -260,6 +287,17 @@ // assert(0); size_t i; + for(i=0;i buf; + buf.resize(3); + + ibuf.Read((char *)&buf[0], 3); + + /* + Buf[0] = cmd + Buf[1] = account id + Buf[2] = account name + Buf[3] = realm id (for sending to good game server :P + */ + + Account* acct; + + if(buf[1] != 0) + acct = AcctMgr.FindAccountById(buf[1]); + else + acct = AcctMgr.FindAccountByName((char *)buf[2]); + + SendInformationRetreiveToGS(buf[3],acct->id, acct->name, acct->security, acct->locale, acct->tbc, acct->banned, acct->locked, acct->I, acct->LastIp); + + return true; +} + +bool AuthSocket::_HandleBanIPAnsw() +{ + std::vector buf; + buf.resize(1); + + ibuf.Read((char *)&buf[0], 1); + + /* + Buf[0] = cmd + Buf[1] = IP + */ + + bool IpIsBanned = AcctMgr.IpBan((char *)buf[1]); + + SendIpBanStatusToGS(buf[1], IpIsBanned); + + return true; +} + /// Make the SRP6 calculation from hash in dB void AuthSocket::_SetVSFields(std::string rI) { @@ -320,6 +403,8 @@ /// Logon Challenge command handler bool AuthSocket::_HandleLogonChallenge() { + AcctMgr.ReloadEverythingIfNeed(); + DEBUG_LOG("Entering _HandleLogonChallenge"); if (ibuf.GetLength() < sizeof(sAuthLogonChallenge_C)) return false; @@ -370,6 +455,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 +571,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 - ///
  • else + ///
  • else { ///- Check if we have the apropriate patch on the disk char tmp[64]; @@ -535,7 +710,7 @@ } /// SendBuf((char const*)pkt.contents(), pkt.size()); - return true; + return true; } /// Logon Proof command handler @@ -661,9 +836,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 +851,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 +873,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;