Core/Authserver: Improved realmlist for multiple realms with different versions, idea from MaNGOS and allow 4.0.6a, 4.2.2 and 4.3.4 clients to use the authserver (no world connections)
This commit is contained in:
@@ -19,12 +19,32 @@
|
|||||||
|
|
||||||
namespace AuthHelper
|
namespace AuthHelper
|
||||||
{
|
{
|
||||||
|
static RealmBuildInfo const PostBcAcceptedClientBuilds[] =
|
||||||
|
{
|
||||||
|
{15595, 4, 3, 4, ' '},
|
||||||
|
{14545, 4, 2, 2, ' '},
|
||||||
|
{13623, 4, 0, 6, 'a'},
|
||||||
|
{12340, 3, 3, 5, 'a'},
|
||||||
|
{11723, 3, 3, 3, 'a'},
|
||||||
|
{11403, 3, 3, 2, ' '},
|
||||||
|
{11159, 3, 3, 0, 'a'},
|
||||||
|
{10505, 3, 2, 2, 'a'},
|
||||||
|
{9947, 3, 1, 3, ' '},
|
||||||
|
{8606, 2, 4, 3, ' '},
|
||||||
|
{0, 0, 0, 0, ' '} // terminator
|
||||||
|
};
|
||||||
|
|
||||||
|
static RealmBuildInfo const PreBcAcceptedClientBuilds[] =
|
||||||
|
{
|
||||||
|
{6005, 1, 12, 2, ' '},
|
||||||
|
{5875, 1, 12, 1, ' '},
|
||||||
|
{0, 0, 0, 0, ' '} // terminator
|
||||||
|
};
|
||||||
|
|
||||||
bool IsPreBCAcceptedClientBuild(int build)
|
bool IsPreBCAcceptedClientBuild(int build)
|
||||||
{
|
{
|
||||||
int accepted_versions[] = PRE_BC_ACCEPTED_CLIENT_BUILD;
|
for (int i = 0; PreBcAcceptedClientBuilds[i].Build; ++i)
|
||||||
|
if (PreBcAcceptedClientBuilds[i].Build == build)
|
||||||
for (int i = 0; accepted_versions[i]; ++i)
|
|
||||||
if (build == accepted_versions[i])
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -32,10 +52,8 @@ namespace AuthHelper
|
|||||||
|
|
||||||
bool IsPostBCAcceptedClientBuild(int build)
|
bool IsPostBCAcceptedClientBuild(int build)
|
||||||
{
|
{
|
||||||
int accepted_versions[] = POST_BC_ACCEPTED_CLIENT_BUILD;
|
for (int i = 0; PostBcAcceptedClientBuilds[i].Build; ++i)
|
||||||
|
if (PostBcAcceptedClientBuilds[i].Build == build)
|
||||||
for (int i = 0; accepted_versions[i]; ++i)
|
|
||||||
if (build == accepted_versions[i])
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -45,4 +63,17 @@ namespace AuthHelper
|
|||||||
{
|
{
|
||||||
return (IsPostBCAcceptedClientBuild(build) || IsPreBCAcceptedClientBuild(build));
|
return (IsPostBCAcceptedClientBuild(build) || IsPreBCAcceptedClientBuild(build));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RealmBuildInfo const* GetBuildInfo(int build)
|
||||||
|
{
|
||||||
|
for (int i = 0; PostBcAcceptedClientBuilds[i].Build; ++i)
|
||||||
|
if (PostBcAcceptedClientBuilds[i].Build == build)
|
||||||
|
return &PostBcAcceptedClientBuilds[i];
|
||||||
|
|
||||||
|
for (int i = 0; PreBcAcceptedClientBuilds[i].Build; ++i)
|
||||||
|
if (PreBcAcceptedClientBuilds[i].Build == build)
|
||||||
|
return &PreBcAcceptedClientBuilds[i];
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -65,9 +65,6 @@ enum LoginResult
|
|||||||
LOGIN_LOCKED_ENFORCED = 0x10,
|
LOGIN_LOCKED_ENFORCED = 0x10,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define POST_BC_ACCEPTED_CLIENT_BUILD {12340, 11723, 11403, 11159, 10571, 10505, 10146, 9947, 8606, 0}
|
|
||||||
#define PRE_BC_ACCEPTED_CLIENT_BUILD {5875, 6005, 0}
|
|
||||||
|
|
||||||
enum ExpansionFlags
|
enum ExpansionFlags
|
||||||
{
|
{
|
||||||
POST_BC_EXP_FLAG = 0x2,
|
POST_BC_EXP_FLAG = 0x2,
|
||||||
@@ -75,8 +72,18 @@ enum ExpansionFlags
|
|||||||
NO_VALID_EXP_FLAG = 0x0
|
NO_VALID_EXP_FLAG = 0x0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct RealmBuildInfo
|
||||||
|
{
|
||||||
|
int Build;
|
||||||
|
int MajorVersion;
|
||||||
|
int MinorVersion;
|
||||||
|
int BugfixVersion;
|
||||||
|
int HotfixVersion;
|
||||||
|
};
|
||||||
|
|
||||||
namespace AuthHelper
|
namespace AuthHelper
|
||||||
{
|
{
|
||||||
|
RealmBuildInfo const* GetBuildInfo(int build);
|
||||||
bool IsAcceptedClientBuild(int build);
|
bool IsAcceptedClientBuild(int build);
|
||||||
bool IsPostBCAcceptedClientBuild(int build);
|
bool IsPostBCAcceptedClientBuild(int build);
|
||||||
bool IsPreBCAcceptedClientBuild(int build);
|
bool IsPreBCAcceptedClientBuild(int build);
|
||||||
|
|||||||
@@ -343,7 +343,7 @@ bool AuthSocket::_HandleLogonChallenge()
|
|||||||
|
|
||||||
_login = (const char*)ch->I;
|
_login = (const char*)ch->I;
|
||||||
_build = ch->build;
|
_build = ch->build;
|
||||||
_expversion = (AuthHelper::IsPostBCAcceptedClientBuild(_build) ? POST_BC_EXP_FLAG : NO_VALID_EXP_FLAG) | (AuthHelper::IsPreBCAcceptedClientBuild(_build) ? PRE_BC_EXP_FLAG : NO_VALID_EXP_FLAG);
|
_expversion = uint8(AuthHelper::IsPostBCAcceptedClientBuild(_build) ? POST_BC_EXP_FLAG : (AuthHelper::IsPreBCAcceptedClientBuild(_build) ? PRE_BC_EXP_FLAG : NO_VALID_EXP_FLAG));
|
||||||
_os = (const char*)ch->os;
|
_os = (const char*)ch->os;
|
||||||
|
|
||||||
if (_os.size() > 4)
|
if (_os.size() > 4)
|
||||||
@@ -352,19 +352,19 @@ bool AuthSocket::_HandleLogonChallenge()
|
|||||||
// Restore string order as its byte order is reversed
|
// Restore string order as its byte order is reversed
|
||||||
std::reverse(_os.begin(), _os.end());
|
std::reverse(_os.begin(), _os.end());
|
||||||
|
|
||||||
pkt << (uint8)AUTH_LOGON_CHALLENGE;
|
pkt << uint8(AUTH_LOGON_CHALLENGE);
|
||||||
pkt << (uint8)0x00;
|
pkt << uint8(0x00);
|
||||||
|
|
||||||
// Verify that this IP is not in the ip_banned table
|
// Verify that this IP is not in the ip_banned table
|
||||||
LoginDatabase.Execute(LoginDatabase.GetPreparedStatement(LOGIN_DEL_EXPIRED_IP_BANS));
|
LoginDatabase.Execute(LoginDatabase.GetPreparedStatement(LOGIN_DEL_EXPIRED_IP_BANS));
|
||||||
|
|
||||||
const std::string& ip_address = socket().getRemoteAddress();
|
std::string const& ip_address = socket().getRemoteAddress();
|
||||||
PreparedStatement *stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_IP_BANNED);
|
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_IP_BANNED);
|
||||||
stmt->setString(0, ip_address);
|
stmt->setString(0, ip_address);
|
||||||
PreparedQueryResult result = LoginDatabase.Query(stmt);
|
PreparedQueryResult result = LoginDatabase.Query(stmt);
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
pkt << (uint8)WOW_FAIL_BANNED;
|
pkt << uint8(WOW_FAIL_BANNED);
|
||||||
sLog->outDebug(LOG_FILTER_AUTHSERVER, "'%s:%d' [AuthChallenge] Banned ip tries to login!",socket().getRemoteAddress().c_str(), socket().getRemotePort());
|
sLog->outDebug(LOG_FILTER_AUTHSERVER, "'%s:%d' [AuthChallenge] Banned ip tries to login!",socket().getRemoteAddress().c_str(), socket().getRemotePort());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -411,12 +411,12 @@ bool AuthSocket::_HandleLogonChallenge()
|
|||||||
{
|
{
|
||||||
if ((*banresult)[0].GetUInt64() == (*banresult)[1].GetUInt64())
|
if ((*banresult)[0].GetUInt64() == (*banresult)[1].GetUInt64())
|
||||||
{
|
{
|
||||||
pkt << (uint8)WOW_FAIL_BANNED;
|
pkt << uint8(WOW_FAIL_BANNED);
|
||||||
sLog->outDebug(LOG_FILTER_AUTHSERVER, "'%s:%d' [AuthChallenge] Banned account %s tried to login!", socket().getRemoteAddress().c_str(), socket().getRemotePort(), _login.c_str ());
|
sLog->outDebug(LOG_FILTER_AUTHSERVER, "'%s:%d' [AuthChallenge] Banned account %s tried to login!", socket().getRemoteAddress().c_str(), socket().getRemotePort(), _login.c_str ());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pkt << (uint8)WOW_FAIL_SUSPENDED;
|
pkt << uint8(WOW_FAIL_SUSPENDED);
|
||||||
sLog->outDebug(LOG_FILTER_AUTHSERVER, "'%s:%d' [AuthChallenge] Temporarily banned account %s tried to login!", socket().getRemoteAddress().c_str(), socket().getRemotePort(), _login.c_str ());
|
sLog->outDebug(LOG_FILTER_AUTHSERVER, "'%s:%d' [AuthChallenge] Temporarily banned account %s tried to login!", socket().getRemoteAddress().c_str(), socket().getRemotePort(), _login.c_str ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -450,7 +450,10 @@ bool AuthSocket::_HandleLogonChallenge()
|
|||||||
unk3.SetRand(16 * 8);
|
unk3.SetRand(16 * 8);
|
||||||
|
|
||||||
// Fill the response packet with the result
|
// Fill the response packet with the result
|
||||||
|
if (AuthHelper::IsAcceptedClientBuild(_build))
|
||||||
pkt << uint8(WOW_SUCCESS);
|
pkt << uint8(WOW_SUCCESS);
|
||||||
|
else
|
||||||
|
pkt << uint8(WOW_FAIL_VERSION_INVALID);
|
||||||
|
|
||||||
// B may be calculated < 32B so we force minimal length to 32B
|
// B may be calculated < 32B so we force minimal length to 32B
|
||||||
pkt.append(B.AsByteArray(32), 32); // 32 bytes
|
pkt.append(B.AsByteArray(32), 32); // 32 bytes
|
||||||
@@ -749,7 +752,7 @@ bool AuthSocket::_HandleReconnectChallenge()
|
|||||||
|
|
||||||
// Reinitialize build, expansion and the account securitylevel
|
// Reinitialize build, expansion and the account securitylevel
|
||||||
_build = ch->build;
|
_build = ch->build;
|
||||||
_expversion = (AuthHelper::IsPostBCAcceptedClientBuild(_build) ? POST_BC_EXP_FLAG : NO_VALID_EXP_FLAG) | (AuthHelper::IsPreBCAcceptedClientBuild(_build) ? PRE_BC_EXP_FLAG : NO_VALID_EXP_FLAG);
|
_expversion = uint8(AuthHelper::IsPostBCAcceptedClientBuild(_build) ? POST_BC_EXP_FLAG : (AuthHelper::IsPreBCAcceptedClientBuild(_build) ? PRE_BC_EXP_FLAG : NO_VALID_EXP_FLAG));
|
||||||
_os = (const char*)ch->os;
|
_os = (const char*)ch->os;
|
||||||
|
|
||||||
if (_os.size() > 4)
|
if (_os.size() > 4)
|
||||||
@@ -766,11 +769,11 @@ bool AuthSocket::_HandleReconnectChallenge()
|
|||||||
|
|
||||||
// Sending response
|
// Sending response
|
||||||
ByteBuffer pkt;
|
ByteBuffer pkt;
|
||||||
pkt << (uint8)AUTH_RECONNECT_CHALLENGE;
|
pkt << uint8(AUTH_RECONNECT_CHALLENGE);
|
||||||
pkt << (uint8)0x00;
|
pkt << uint8(0x00);
|
||||||
_reconnectProof.SetRand(16 * 8);
|
_reconnectProof.SetRand(16 * 8);
|
||||||
pkt.append(_reconnectProof.AsByteArray(16), 16); // 16 bytes random
|
pkt.append(_reconnectProof.AsByteArray(16), 16); // 16 bytes random
|
||||||
pkt << (uint64)0x00 << (uint64)0x00; // 16 bytes zeros
|
pkt << uint64(0x00) << uint64(0x00); // 16 bytes zeros
|
||||||
socket().send((char const*)pkt.contents(), pkt.size());
|
socket().send((char const*)pkt.contents(), pkt.size());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -800,9 +803,9 @@ bool AuthSocket::_HandleReconnectProof()
|
|||||||
{
|
{
|
||||||
// Sending response
|
// Sending response
|
||||||
ByteBuffer pkt;
|
ByteBuffer pkt;
|
||||||
pkt << (uint8)AUTH_RECONNECT_PROOF;
|
pkt << uint8(AUTH_RECONNECT_PROOF);
|
||||||
pkt << (uint8)0x00;
|
pkt << uint8(0x00);
|
||||||
pkt << (uint16)0x00; // 2 bytes zeros
|
pkt << uint16(0x00); // 2 bytes zeros
|
||||||
socket().send((char const*)pkt.contents(), pkt.size());
|
socket().send((char const*)pkt.contents(), pkt.size());
|
||||||
_authed = true;
|
_authed = true;
|
||||||
return true;
|
return true;
|
||||||
@@ -849,73 +852,87 @@ bool AuthSocket::_HandleRealmList()
|
|||||||
for (RealmList::RealmMap::const_iterator i = sRealmList->begin(); i != sRealmList->end(); ++i)
|
for (RealmList::RealmMap::const_iterator i = sRealmList->begin(); i != sRealmList->end(); ++i)
|
||||||
{
|
{
|
||||||
// don't work with realms which not compatible with the client
|
// don't work with realms which not compatible with the client
|
||||||
if ((_expversion & POST_BC_EXP_FLAG) && i->second.gamebuild != _build)
|
bool okBuild = ((_expversion & POST_BC_EXP_FLAG) && i->second.gamebuild == _build) || ((_expversion & PRE_BC_EXP_FLAG) && !AuthHelper::IsPreBCAcceptedClientBuild(i->second.gamebuild));
|
||||||
continue;
|
|
||||||
else if ((_expversion & PRE_BC_EXP_FLAG) && !AuthHelper::IsPreBCAcceptedClientBuild(i->second.gamebuild))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
uint8 AmountOfCharacters;
|
|
||||||
|
|
||||||
// No SQL injection. id of realm is controlled by the database.
|
// No SQL injection. id of realm is controlled by the database.
|
||||||
|
uint32 flag = i->second.flag;
|
||||||
|
RealmBuildInfo const* buildInfo = AuthHelper::GetBuildInfo(i->second.gamebuild);
|
||||||
|
if (!okBuild)
|
||||||
|
{
|
||||||
|
if (!buildInfo)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
flag |= REALM_FLAG_OFFLINE | REALM_FLAG_SPECIFYBUILD; // tell the client what build the realm is for
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!buildInfo)
|
||||||
|
flag &= ~REALM_FLAG_SPECIFYBUILD;
|
||||||
|
|
||||||
|
std::string name = i->first;
|
||||||
|
if (_expversion & PRE_BC_EXP_FLAG && flag & REALM_FLAG_SPECIFYBUILD)
|
||||||
|
{
|
||||||
|
std::ostringstream ss;
|
||||||
|
ss << name << " (" << buildInfo->MajorVersion << '.' << buildInfo->MinorVersion << '.' << buildInfo->BugfixVersion << ')';
|
||||||
|
name = ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 lock = (i->second.allowedSecurityLevel > _accountSecurityLevel) ? 1 : 0;
|
||||||
|
|
||||||
|
uint8 AmountOfCharacters = 0;
|
||||||
stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_NUM_CHARS_ON_REALM);
|
stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_NUM_CHARS_ON_REALM);
|
||||||
stmt->setUInt32(0, i->second.m_ID);
|
stmt->setUInt32(0, i->second.m_ID);
|
||||||
stmt->setUInt32(1, id);
|
stmt->setUInt32(1, id);
|
||||||
result = LoginDatabase.Query(stmt);
|
result = LoginDatabase.Query(stmt);
|
||||||
if (result)
|
if (result)
|
||||||
AmountOfCharacters = (*result)[0].GetUInt8();
|
AmountOfCharacters = (*result)[0].GetUInt8();
|
||||||
else
|
|
||||||
AmountOfCharacters = 0;
|
|
||||||
|
|
||||||
uint8 lock = (i->second.allowedSecurityLevel > _accountSecurityLevel) ? 1 : 0;
|
|
||||||
|
|
||||||
pkt << i->second.icon; // realm type
|
pkt << i->second.icon; // realm type
|
||||||
if ( _expversion & POST_BC_EXP_FLAG ) // only 2.x and 3.x clients
|
if (_expversion & POST_BC_EXP_FLAG) // only 2.x and 3.x clients
|
||||||
pkt << lock; // if 1, then realm locked
|
pkt << lock; // if 1, then realm locked
|
||||||
pkt << uint8(i->second.flag); // RealmFlags
|
pkt << uint8(flag); // RealmFlags
|
||||||
pkt << i->first;
|
pkt << name;
|
||||||
pkt << i->second.address;
|
pkt << i->second.address;
|
||||||
pkt << i->second.populationLevel;
|
pkt << i->second.populationLevel;
|
||||||
pkt << AmountOfCharacters;
|
pkt << AmountOfCharacters;
|
||||||
pkt << i->second.timezone; // realm category
|
pkt << i->second.timezone; // realm category
|
||||||
if (_expversion & POST_BC_EXP_FLAG) // 2.x and 3.x clients
|
if (_expversion & POST_BC_EXP_FLAG) // 2.x and 3.x clients
|
||||||
pkt << (uint8)0x2C; // unk, may be realm number/id?
|
pkt << uint8(0x2C); // unk, may be realm number/id?
|
||||||
else
|
else
|
||||||
pkt << (uint8)0x0; // 1.12.1 and 1.12.2 clients
|
pkt << uint8(0x0); // 1.12.1 and 1.12.2 clients
|
||||||
|
|
||||||
if (i->second.flag & REALM_FLAG_SPECIFYBUILD)
|
if (_expversion & POST_BC_EXP_FLAG && flag & REALM_FLAG_SPECIFYBUILD)
|
||||||
{
|
{
|
||||||
// TODO: Make this customizable
|
pkt << uint8(buildInfo->MajorVersion);
|
||||||
pkt << uint8(3);
|
pkt << uint8(buildInfo->MinorVersion);
|
||||||
pkt << uint8(3);
|
pkt << uint8(buildInfo->BugfixVersion);
|
||||||
pkt << uint8(5);
|
pkt << uint16(buildInfo->Build);
|
||||||
pkt << uint16(12340);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
++RealmListSize;
|
++RealmListSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( _expversion & POST_BC_EXP_FLAG ) // 2.x and 3.x clients
|
if (_expversion & POST_BC_EXP_FLAG) // 2.x and 3.x clients
|
||||||
{
|
{
|
||||||
pkt << (uint8)0x10;
|
pkt << uint8(0x10);
|
||||||
pkt << (uint8)0x00;
|
pkt << uint8(0x00);
|
||||||
}
|
}
|
||||||
else // 1.12.1 and 1.12.2 clients
|
else // 1.12.1 and 1.12.2 clients
|
||||||
{
|
{
|
||||||
pkt << (uint8)0x00;
|
pkt << uint8(0x00);
|
||||||
pkt << (uint8)0x02;
|
pkt << uint8(0x02);
|
||||||
}
|
}
|
||||||
|
|
||||||
// make a ByteBuffer which stores the RealmList's size
|
// make a ByteBuffer which stores the RealmList's size
|
||||||
ByteBuffer RealmListSizeBuffer;
|
ByteBuffer RealmListSizeBuffer;
|
||||||
RealmListSizeBuffer << (uint32)0;
|
RealmListSizeBuffer << uint32(0);
|
||||||
if (_expversion & POST_BC_EXP_FLAG) // only 2.x and 3.x clients
|
if (_expversion & POST_BC_EXP_FLAG) // only 2.x and 3.x clients
|
||||||
RealmListSizeBuffer << (uint16)RealmListSize;
|
RealmListSizeBuffer << uint16(RealmListSize);
|
||||||
else
|
else
|
||||||
RealmListSizeBuffer << (uint32)RealmListSize;
|
RealmListSizeBuffer << uint32(RealmListSize);
|
||||||
|
|
||||||
ByteBuffer hdr;
|
ByteBuffer hdr;
|
||||||
hdr << (uint8) REALM_LIST;
|
hdr << uint8(REALM_LIST);
|
||||||
hdr << (uint16)(pkt.size() + RealmListSizeBuffer.size());
|
hdr << uint16(pkt.size() + RealmListSizeBuffer.size());
|
||||||
hdr.append(RealmListSizeBuffer); // append RealmList's size buffer
|
hdr.append(RealmListSizeBuffer); // append RealmList's size buffer
|
||||||
hdr.append(pkt); // append realms in the realmlist
|
hdr.append(pkt); // append realms in the realmlist
|
||||||
|
|
||||||
@@ -983,7 +1000,9 @@ 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()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// Preload MD5 hashes of existing patch files on server
|
// Preload MD5 hashes of existing patch files on server
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
|||||||
Reference in New Issue
Block a user