mirror of
https://github.com/mangosfour/server.git
synced 2025-12-16 13:37:00 +00:00
[9010] Implement realmd support realms for different client versions
* Supported 1.12.1, 1.12.2, 2.4.3, 3.2.2a in same time as relams in same realmlist * mangosd by self check correct for it client build and reject all incorrect cases * realmd know from mangosd what builds supported each realm and if realm not support it then in relamlist for specific client this relam show as offline. Not need any manual settings for this. Signed-off-by: VladimirMangos <vladimir@getmangos.com>
This commit is contained in:
parent
41b0b88674
commit
022524c1bb
13 changed files with 239 additions and 73 deletions
|
|
@ -22,14 +22,12 @@
|
|||
|
||||
#include "Common.h"
|
||||
#include "Database/DatabaseEnv.h"
|
||||
#include "ByteBuffer.h"
|
||||
#include "Config/ConfigEnv.h"
|
||||
#include "Log.h"
|
||||
#include "RealmList.h"
|
||||
#include "AuthSocket.h"
|
||||
#include "AuthCodes.h"
|
||||
#include <openssl/md5.h>
|
||||
#include "Auth/Sha1.h"
|
||||
//#include "Util.h" -- for commented utf8ToUpperOnlyLatin
|
||||
|
||||
extern DatabaseType loginDatabase;
|
||||
|
|
@ -129,6 +127,16 @@ typedef struct AUTH_LOGON_PROOF_S
|
|||
uint16 unk3;
|
||||
} sAuthLogonProof_S;
|
||||
|
||||
typedef struct AUTH_LOGON_PROOF_S_BUILD_6005
|
||||
{
|
||||
uint8 cmd;
|
||||
uint8 error;
|
||||
uint8 M2[20];
|
||||
//uint32 unk1;
|
||||
uint32 unk2;
|
||||
//uint16 unk3;
|
||||
} sAuthLogonProof_S_BUILD_6005;
|
||||
|
||||
typedef struct AUTH_RECONNECT_PROOF_C
|
||||
{
|
||||
uint8 cmd;
|
||||
|
|
@ -321,6 +329,40 @@ void AuthSocket::_SetVSFields(const std::string& rI)
|
|||
OPENSSL_free((void*)s_hex);
|
||||
}
|
||||
|
||||
void AuthSocket::SendProof(Sha1Hash sha)
|
||||
{
|
||||
switch(_build)
|
||||
{
|
||||
case 5875: // 1.12.1
|
||||
case 6005: // 1.12.2
|
||||
{
|
||||
sAuthLogonProof_S_BUILD_6005 proof;
|
||||
memcpy(proof.M2, sha.GetDigest(), 20);
|
||||
proof.cmd = AUTH_LOGON_PROOF;
|
||||
proof.error = 0;
|
||||
proof.unk2 = 0x00;
|
||||
|
||||
SendBuf((char *)&proof, sizeof(proof));
|
||||
break;
|
||||
}
|
||||
case 8606: // 2.4.3
|
||||
case 10505: // 3.2.2a
|
||||
default: // or later
|
||||
{
|
||||
sAuthLogonProof_S proof;
|
||||
memcpy(proof.M2, sha.GetDigest(), 20);
|
||||
proof.cmd = AUTH_LOGON_PROOF;
|
||||
proof.error = 0;
|
||||
proof.unk1 = 0x00800000;
|
||||
proof.unk2 = 0x00;
|
||||
proof.unk3 = 0x00;
|
||||
|
||||
SendBuf((char *)&proof, sizeof(proof));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Logon Challenge command handler
|
||||
bool AuthSocket::_HandleLogonChallenge()
|
||||
{
|
||||
|
|
@ -346,6 +388,11 @@ bool AuthSocket::_HandleLogonChallenge()
|
|||
buf[buf.size() - 1] = 0;
|
||||
sAuthLogonChallenge_C *ch = (sAuthLogonChallenge_C*)&buf[0];
|
||||
|
||||
///- Read the remaining of the packet
|
||||
ibuf.Read((char *)&buf[4], remaining);
|
||||
DEBUG_LOG("[AuthChallenge] got full packet, %#04x bytes", ch->size);
|
||||
DEBUG_LOG("[AuthChallenge] name(%d): '%s'", ch->I_len, ch->I);
|
||||
|
||||
// BigEndian code, nop in little endian case
|
||||
// size already converted
|
||||
EndianConvert(*((uint32*)(&ch->gamename[0])));
|
||||
|
|
@ -356,11 +403,6 @@ bool AuthSocket::_HandleLogonChallenge()
|
|||
EndianConvert(ch->timezone_bias);
|
||||
EndianConvert(ch->ip);
|
||||
|
||||
///- Read the remaining of the packet
|
||||
ibuf.Read((char *)&buf[4], remaining);
|
||||
DEBUG_LOG("[AuthChallenge] got full packet, %#04x bytes", ch->size);
|
||||
DEBUG_LOG("[AuthChallenge] name(%d): '%s'", ch->I_len, ch->I);
|
||||
|
||||
ByteBuffer pkt;
|
||||
|
||||
_login = (const char*)ch->I;
|
||||
|
|
@ -536,13 +578,19 @@ bool AuthSocket::_HandleLogonProof()
|
|||
|
||||
///- 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)
|
||||
int accepted_versions[] = EXPECTED_REALMD_CLIENT_BUILD;
|
||||
if (_build >= accepted_versions[0]) // first build is low bound of always accepted range
|
||||
valid_version = true;
|
||||
else
|
||||
{
|
||||
if(_build == accepted_versions[i])
|
||||
// continue from 1 with explict equal check
|
||||
for(int i = 1; accepted_versions[i]; ++i)
|
||||
{
|
||||
valid_version = true;
|
||||
break;
|
||||
if(_build == accepted_versions[i])
|
||||
{
|
||||
valid_version = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -690,16 +738,8 @@ bool AuthSocket::_HandleLogonProof()
|
|||
sha.Initialize();
|
||||
sha.UpdateBigNumbers(&A, &M, &K, NULL);
|
||||
sha.Finalize();
|
||||
|
||||
sAuthLogonProof_S proof;
|
||||
memcpy(proof.M2, sha.GetDigest(), 20);
|
||||
proof.cmd = AUTH_LOGON_PROOF;
|
||||
proof.error = 0;
|
||||
proof.unk1 = 0x00800000;
|
||||
proof.unk2 = 0x00;
|
||||
proof.unk3 = 0x00;
|
||||
|
||||
SendBuf((char *)&proof, sizeof(proof));
|
||||
|
||||
SendProof(sha);
|
||||
|
||||
///- Set _authed to true!
|
||||
_authed = true;
|
||||
|
|
@ -882,39 +922,8 @@ bool AuthSocket::_HandleRealmList()
|
|||
|
||||
///- Circle through realms in the RealmList and construct the return packet (including # of user characters in each realm)
|
||||
ByteBuffer pkt;
|
||||
pkt << (uint32) 0;
|
||||
pkt << (uint16) sRealmList.size();
|
||||
RealmList::RealmMap::const_iterator i;
|
||||
for( i = sRealmList.begin(); i != sRealmList.end(); ++i )
|
||||
{
|
||||
uint8 AmountOfCharacters;
|
||||
|
||||
// No SQL injection. id of realm is controlled by the database.
|
||||
result = loginDatabase.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;
|
||||
|
||||
uint8 lock = (i->second.allowedSecurityLevel > _accountSecurityLevel) ? 1 : 0;
|
||||
|
||||
pkt << i->second.icon; // realm type
|
||||
pkt << lock; // if 1, then realm locked
|
||||
pkt << i->second.color; // if 2, then realm is offline
|
||||
pkt << i->first;
|
||||
pkt << i->second.address;
|
||||
pkt << i->second.populationLevel;
|
||||
pkt << AmountOfCharacters;
|
||||
pkt << i->second.timezone; // realm category
|
||||
pkt << (uint8) 0x2C; // unk, may be realm number/id?
|
||||
}
|
||||
pkt << (uint8) 0x10;
|
||||
pkt << (uint8) 0x00;
|
||||
|
||||
LoadRealmlist(pkt, id);
|
||||
|
||||
ByteBuffer hdr;
|
||||
hdr << (uint8) REALM_LIST;
|
||||
hdr << (uint16)pkt.size();
|
||||
|
|
@ -925,6 +934,95 @@ bool AuthSocket::_HandleRealmList()
|
|||
return true;
|
||||
}
|
||||
|
||||
void AuthSocket::LoadRealmlist(ByteBuffer &pkt, uint32 acctid)
|
||||
{
|
||||
switch(_build)
|
||||
{
|
||||
case 5875: // 1.12.1
|
||||
case 6005: // 1.12.2
|
||||
{
|
||||
pkt << uint32(0);
|
||||
pkt << uint8(sRealmList.size());
|
||||
|
||||
for(RealmList::RealmMap::const_iterator i = sRealmList.begin(); i != sRealmList.end(); ++i)
|
||||
{
|
||||
uint8 AmountOfCharacters;
|
||||
|
||||
// No SQL injection. id of realm is controlled by the database.
|
||||
QueryResult *result = loginDatabase.PQuery( "SELECT numchars FROM realmcharacters WHERE realmid = '%d' AND acctid='%u'", i->second.m_ID, acctid);
|
||||
if( result )
|
||||
{
|
||||
Field *fields = result->Fetch();
|
||||
AmountOfCharacters = fields[0].GetUInt8();
|
||||
delete result;
|
||||
}
|
||||
else
|
||||
AmountOfCharacters = 0;
|
||||
|
||||
// Show offline state for unsupported client builds
|
||||
uint8 color = (std::find(i->second.realmbuilds.begin(), i->second.realmbuilds.end(), _build) != i->second.realmbuilds.end()) ? i->second.color : 2;
|
||||
color = (i->second.allowedSecurityLevel > _accountSecurityLevel) ? 2 : color;
|
||||
|
||||
pkt << uint32(i->second.icon); // realm type
|
||||
pkt << uint8(color); // if 2, then realm is offline
|
||||
pkt << i->first; // name
|
||||
pkt << i->second.address; // address
|
||||
pkt << float(i->second.populationLevel);
|
||||
pkt << uint8(AmountOfCharacters);
|
||||
pkt << uint8(i->second.timezone); // realm category
|
||||
pkt << uint8(0x00); // unk, may be realm number/id?
|
||||
}
|
||||
|
||||
pkt << uint8(0x00);
|
||||
pkt << uint8(0x02);
|
||||
break;
|
||||
}
|
||||
|
||||
case 8606: // 2.4.3
|
||||
case 10505: // 3.2.2a
|
||||
default: // and later
|
||||
{
|
||||
pkt << uint32(0);
|
||||
pkt << uint16(sRealmList.size());
|
||||
|
||||
for(RealmList::RealmMap::const_iterator i = sRealmList.begin(); i != sRealmList.end(); ++i)
|
||||
{
|
||||
uint8 AmountOfCharacters;
|
||||
|
||||
// No SQL injection. id of realm is controlled by the database.
|
||||
QueryResult *result = loginDatabase.PQuery( "SELECT numchars FROM realmcharacters WHERE realmid = '%d' AND acctid='%u'", i->second.m_ID, acctid);
|
||||
if( result )
|
||||
{
|
||||
Field *fields = result->Fetch();
|
||||
AmountOfCharacters = fields[0].GetUInt8();
|
||||
delete result;
|
||||
}
|
||||
else
|
||||
AmountOfCharacters = 0;
|
||||
|
||||
uint8 lock = (i->second.allowedSecurityLevel > _accountSecurityLevel) ? 1 : 0;
|
||||
|
||||
// Show offline state for unsupported client builds
|
||||
uint8 color = (std::find(i->second.realmbuilds.begin(), i->second.realmbuilds.end(), _build) != i->second.realmbuilds.end()) ? i->second.color : 2;
|
||||
|
||||
pkt << uint8(i->second.icon); // realm type
|
||||
pkt << uint8(lock); // if 1, then realm locked
|
||||
pkt << uint8(color); // if 2, then realm is offline
|
||||
pkt << i->first; // name
|
||||
pkt << i->second.address; // address
|
||||
pkt << float(i->second.populationLevel);
|
||||
pkt << uint8(AmountOfCharacters);
|
||||
pkt << uint8(i->second.timezone); // realm category
|
||||
pkt << uint8(0x2C); // unk, may be realm number/id?
|
||||
}
|
||||
|
||||
pkt << uint8(0x10);
|
||||
pkt << uint8(0x00);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Resume patch transfer
|
||||
bool AuthSocket::_HandleXferResume()
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue