* Fixed mangos-realmds autopatching system

This commit is contained in:
arrai 2008-10-18 00:11:12 +02:00
parent a3689bfe3c
commit dbb399d808
2 changed files with 162 additions and 151 deletions

View file

@ -135,7 +135,7 @@ typedef struct XFER_INIT
{ {
uint8 cmd; // XFER_INITIATE uint8 cmd; // XFER_INITIATE
uint8 fileNameLen; // strlen(fileName); uint8 fileNameLen; // strlen(fileName);
uint8 fileName[1]; // fileName[fileNameLen] uint8 fileName[5]; // fileName[fileNameLen]
uint64 file_size; // file size (bytes) uint64 file_size; // file size (bytes)
uint8 md5[MD5_DIGEST_LENGTH]; // MD5 uint8 md5[MD5_DIGEST_LENGTH]; // MD5
}XFER_INIT; }XFER_INIT;
@ -223,6 +223,7 @@ AuthSocket::AuthSocket(ISocketHandler &h) : TcpSocket(h)
/// Close patch file descriptor before leaving /// Close patch file descriptor before leaving
AuthSocket::~AuthSocket() AuthSocket::~AuthSocket()
{ {
ZThread::Guard<ZThread::Mutex> g(patcherLock);
if(pPatch) if(pPatch)
fclose(pPatch); fclose(pPatch);
} }
@ -358,6 +359,7 @@ bool AuthSocket::_HandleLogonChallenge()
ByteBuffer pkt; ByteBuffer pkt;
_login = (const char*)ch->I; _login = (const char*)ch->I;
_build = ch->build;
///- Normalize account name ///- Normalize account name
//utf8ToUpperOnlyLatin(_login); -- client already send account in expected form //utf8ToUpperOnlyLatin(_login); -- client already send account in expected form
@ -367,19 +369,6 @@ bool AuthSocket::_HandleLogonChallenge()
_safelogin=_login; _safelogin=_login;
dbRealmServer.escape_string(_safelogin); dbRealmServer.escape_string(_safelogin);
///- Check if the client has one of the expected version numbers
bool valid_version=false;
int accepted_versions[]=EXPECTED_MANGOS_CLIENT_BUILD;
for(int i=0;accepted_versions[i];i++)
if(ch->build==accepted_versions[i])
{
valid_version=true;
break;
}
/// <ul><li> if this is a valid version
if(valid_version)
{
pkt << (uint8) AUTH_LOGON_CHALLENGE; pkt << (uint8) AUTH_LOGON_CHALLENGE;
pkt << (uint8) 0x00; pkt << (uint8) 0x00;
@ -478,14 +467,11 @@ bool AuthSocket::_HandleLogonChallenge()
uint8 secLevel = (*result)[4].GetUInt8(); uint8 secLevel = (*result)[4].GetUInt8();
_accountSecurityLevel = secLevel <= SEC_ADMINISTRATOR ? AccountTypes(secLevel) : SEC_ADMINISTRATOR; _accountSecurityLevel = secLevel <= SEC_ADMINISTRATOR ? AccountTypes(secLevel) : SEC_ADMINISTRATOR;
std::string localeName; _localizationName.resize(4);
localeName.resize(4);
for(int i = 0; i <4; ++i) for(int i = 0; i <4; ++i)
localeName[i] = ch->country[4-i-1]; _localizationName[i] = ch->country[4-i-1];
_localization = GetLocaleByName(localeName); sLog.outBasic("[AuthChallenge] account %s is using '%c%c%c%c' locale (%u)", _login.c_str (), ch->country[3],ch->country[2],ch->country[1],ch->country[0], GetLocaleByName(_localizationName));
sLog.outBasic("[AuthChallenge] account %s is using '%c%c%c%c' locale (%u)", _login.c_str (), ch->country[3],ch->country[2],ch->country[1],ch->country[0], _localization);
} }
} }
delete result; delete result;
@ -495,26 +481,57 @@ bool AuthSocket::_HandleLogonChallenge()
pkt<< (uint8) REALM_AUTH_NO_MATCH; pkt<< (uint8) REALM_AUTH_NO_MATCH;
} }
} }
} //valid version SendBuf((char const*)pkt.contents(), pkt.size());
else return true;
///<li> else }
/// Logon Proof command handler
bool AuthSocket::_HandleLogonProof()
{
DEBUG_LOG("Entering _HandleLogonProof");
///- Read the packet
if (ibuf.GetLength() < sizeof(sAuthLogonProof_C))
return false;
sAuthLogonProof_C lp;
ibuf.Read((char *)&lp, sizeof(sAuthLogonProof_C));
///- Check if the client has one of the expected version numbers
bool valid_version=false;
int accepted_versions[]=EXPECTED_MANGOS_CLIENT_BUILD;
for(int i=0;accepted_versions[i];i++)
{
if(_build==accepted_versions[i])
{
valid_version=true;
break;
}
}
/// <ul><li> If the client has no valid version
if(!valid_version)
{ {
///- Check if we have the apropriate patch on the disk ///- Check if we have the apropriate patch on the disk
char tmp[64];
// 24 = len("./patches/65535enGB.mpq")+1
char tmp[24];
// No buffer overflow (fixed length of arguments) // No buffer overflow (fixed length of arguments)
sprintf(tmp,"./patches/%d%c%c%c%c.mpq",ch->build,ch->country[3], sprintf(tmp,"./patches/%d%s.mpq",_build, _localizationName.c_str());
ch->country[2],ch->country[1],ch->country[0]);
// This will be closed at the destruction of the AuthSocket (client deconnection) // This will be closed at the destruction of the AuthSocket (client deconnection)
FILE *pFile=fopen(tmp,"rb"); FILE *pFile=fopen(tmp,"rb");
if(!pFile) if(!pFile)
{ {
ByteBuffer pkt;
pkt << (uint8) AUTH_LOGON_CHALLENGE; pkt << (uint8) AUTH_LOGON_CHALLENGE;
pkt << (uint8) 0x00; pkt << (uint8) 0x00;
pkt << (uint8) REALM_AUTH_WRONG_BUILD_NUMBER; pkt << (uint8) REALM_AUTH_WRONG_BUILD_NUMBER;
DEBUG_LOG("[AuthChallenge] %u is not a valid client version!", ch->build); DEBUG_LOG("[AuthChallenge] %u is not a valid client version!", _build);
DEBUG_LOG("[AuthChallenge] Patch %s not found",tmp); DEBUG_LOG("[AuthChallenge] Patch %s not found",tmp);
}else SendBuf((char const*)pkt.contents(), pkt.size());
{ //have patch return true;
}
else // have patch
{
pPatch=pFile; pPatch=pFile;
XFER_INIT xferh; XFER_INIT xferh;
@ -544,20 +561,6 @@ bool AuthSocket::_HandleLogonChallenge()
} }
} }
/// </ul> /// </ul>
SendBuf((char const*)pkt.contents(), pkt.size());
return true;
}
/// Logon Proof command handler
bool AuthSocket::_HandleLogonProof()
{
DEBUG_LOG("Entering _HandleLogonProof");
///- Read the packet
if (ibuf.GetLength() < sizeof(sAuthLogonProof_C))
return false;
sAuthLogonProof_C lp;
ibuf.Read((char *)&lp, sizeof(sAuthLogonProof_C));
///- Continue the SRP6 calculation based on data received from the client ///- Continue the SRP6 calculation based on data received from the client
BigNumber A; BigNumber A;
@ -636,7 +639,7 @@ bool AuthSocket::_HandleLogonProof()
///- Update the sessionkey, last_ip, last login time and reset number of failed logins in the account table for this account ///- Update the sessionkey, last_ip, last login time and reset number of failed logins in the account table for this account
// No SQL injection (escaped user name) and IP address as received by socket // No SQL injection (escaped user name) and IP address as received by socket
const char* K_hex = K.AsHexStr(); const char* K_hex = K.AsHexStr();
dbRealmServer.PExecute("UPDATE account SET sessionkey = '%s', last_ip = '%s', last_login = NOW(), locale = '%u', failed_logins = 0 WHERE username = '%s'", K_hex, GetRemoteAddress().c_str(), _localization, _safelogin.c_str() ); dbRealmServer.PExecute("UPDATE account SET sessionkey = '%s', last_ip = '%s', last_login = NOW(), locale = '%u', failed_logins = 0 WHERE username = '%s'", K_hex, GetRemoteAddress().c_str(), GetLocaleByName(_localizationName), _safelogin.c_str() );
OPENSSL_free((void*)K_hex); OPENSSL_free((void*)K_hex);
///- Finish SRP6 and send the final result to the client ///- Finish SRP6 and send the final result to the client
@ -848,6 +851,7 @@ PatcherRunnable::PatcherRunnable(class AuthSocket * as)
/// Send content of patch file to the client /// Send content of patch file to the client
void PatcherRunnable::run() void PatcherRunnable::run()
{ {
ZThread::Guard<ZThread::Mutex> g(mySocket->patcherLock);
XFER_DATA_STRUCT xfdata; XFER_DATA_STRUCT xfdata;
xfdata.opcode = XFER_DATA; xfdata.opcode = XFER_DATA;
@ -909,10 +913,11 @@ void Patcher::LoadPatchesInfo()
if(hFil==INVALID_HANDLE_VALUE) if(hFil==INVALID_HANDLE_VALUE)
return; //no patches were found return; //no patches were found
do
{
LoadPatchMD5(fil.cFileName); LoadPatchMD5(fil.cFileName);
}
while(FindNextFile(hFil,&fil)) while(FindNextFile(hFil,&fil));
LoadPatchMD5(fil.cFileName);
} }
#endif #endif

View file

@ -31,6 +31,7 @@
#include "sockets/Utility.h" #include "sockets/Utility.h"
#include "sockets/Parse.h" #include "sockets/Parse.h"
#include "sockets/Socket.h" #include "sockets/Socket.h"
#include "zthread/Mutex.h"
/// Handle login commands /// Handle login commands
class AuthSocket: public TcpSocket class AuthSocket: public TcpSocket
@ -56,6 +57,7 @@ class AuthSocket: public TcpSocket
void _SetVSFields(std::string rI); void _SetVSFields(std::string rI);
FILE *pPatch; FILE *pPatch;
ZThread::Mutex patcherLock;
bool IsLag(); bool IsLag();
private: private:
@ -68,7 +70,11 @@ class AuthSocket: public TcpSocket
std::string _login; std::string _login;
std::string _safelogin; std::string _safelogin;
uint8 _localization;
// Since GetLocaleByName() is _NOT_ bijective, we have to store the locale as a string. Otherwise we can't differ
// between enUS and enGB, which is important for the patch system
std::string _localizationName;
uint16 _build;
AccountTypes _accountSecurityLevel; AccountTypes _accountSecurityLevel;
}; };
#endif #endif