Skip to content
Permalink
Browse files

Core/Authserver: Added possibility to allow realm connections both fr…

…om "world" and local networks.
  • Loading branch information...
Shauren committed Jan 27, 2013
1 parent e1d12de commit 6e80357f8e8b4e820bab8bd05fb8457c3cb46d11
@@ -193,6 +193,8 @@ CREATE TABLE `realmlist` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(32) NOT NULL DEFAULT '',
`address` varchar(255) NOT NULL DEFAULT '127.0.0.1',
`localAddress` varchar(255) NOT NULL DEFAULT '127.0.0.1',
`localSubnetMask` varchar(255) NOT NULL DEFAULT '255.255.255.0',
`port` smallint(5) unsigned NOT NULL DEFAULT '8085',
`icon` tinyint(3) unsigned NOT NULL DEFAULT '0',
`flag` tinyint(3) unsigned NOT NULL DEFAULT '2',
@@ -0,0 +1,3 @@
ALTER TABLE `realmlist`
ADD `localAddress` varchar(255) NOT NULL DEFAULT '127.0.0.1' AFTER `address`,
ADD `localSubnetMask` varchar(255) NOT NULL DEFAULT '255.255.255.0' AFTER `localAddress`;
@@ -31,12 +31,12 @@ void RealmList::Initialize(uint32 updateInterval)
UpdateRealms(true);
}

void RealmList::UpdateRealm(uint32 ID, const std::string& name, ACE_INET_Addr const& address, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float popu, uint32 build)
void RealmList::UpdateRealm(uint32 id, const std::string& name, ACE_INET_Addr const& address, ACE_INET_Addr const& localAddr, ACE_INET_Addr const& localSubmask, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float popu, uint32 build)
{
// Create new if not exist or update existed
Realm& realm = m_realms[name];

realm.m_ID = ID;
realm.m_ID = id;
realm.name = name;
realm.icon = icon;
realm.flag = flag;
@@ -45,7 +45,9 @@ void RealmList::UpdateRealm(uint32 ID, const std::string& name, ACE_INET_Addr co
realm.populationLevel = popu;

// Append port to IP address.
address.addr_to_string(realm.address, ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 16);
realm.ExternalAddress = address;
realm.LocalAddress = localAddr;
realm.LocalSubnetMask = localSubmask;
realm.gamebuild = build;
}

@@ -77,23 +79,27 @@ void RealmList::UpdateRealms(bool init)
do
{
Field* fields = result->Fetch();
uint32 realmId = fields[0].GetUInt32();
std::string name = fields[1].GetString();
std::string address = fields[2].GetString();
uint16 port = fields[3].GetUInt16();
uint8 icon = fields[4].GetUInt8();
RealmFlags flag = RealmFlags(fields[5].GetUInt8());
uint8 timezone = fields[6].GetUInt8();
uint8 allowedSecurityLevel = fields[7].GetUInt8();
float pop = fields[8].GetFloat();
uint32 build = fields[9].GetUInt32();

ACE_INET_Addr addr(port, address.c_str(), AF_INET);

UpdateRealm(realmId, name, addr, icon, flag, timezone, (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop, build);
uint32 realmId = fields[0].GetUInt32();
std::string name = fields[1].GetString();
std::string externalAddress = fields[2].GetString();
std::string localAddress = fields[3].GetString();
std::string localSubmask = fields[4].GetString();
uint16 port = fields[5].GetUInt16();
uint8 icon = fields[6].GetUInt8();
RealmFlags flag = RealmFlags(fields[7].GetUInt8());
uint8 timezone = fields[8].GetUInt8();
uint8 allowedSecurityLevel = fields[9].GetUInt8();
float pop = fields[10].GetFloat();
uint32 build = fields[11].GetUInt32();

ACE_INET_Addr externalAddr(port, externalAddress.c_str(), AF_INET);
ACE_INET_Addr localAddr(port, localAddress.c_str(), AF_INET);
ACE_INET_Addr submask(0, localSubmask.c_str(), AF_INET);

UpdateRealm(realmId, name, externalAddr, localAddr, submask, icon, flag, timezone, (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop, build);

if (init)
sLog->outInfo(LOG_FILTER_AUTHSERVER, "Added realm \"%s\" at %s.", name.c_str(), m_realms[name].address);
sLog->outInfo(LOG_FILTER_AUTHSERVER, "Added realm \"%s\" at %s:%u.", name.c_str(), m_realms[name].ExternalAddress.get_host_addr(), port);
}
while (result->NextRow());
}
@@ -40,7 +40,9 @@ enum RealmFlags
// Storage object for a realm
struct Realm
{
char address[ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 16];
ACE_INET_Addr ExternalAddress;
ACE_INET_Addr LocalAddress;
ACE_INET_Addr LocalSubnetMask;
std::string name;
uint8 icon;
RealmFlags flag;
@@ -72,7 +74,7 @@ class RealmList

private:
void UpdateRealms(bool init=false);
void UpdateRealm(uint32 ID, const std::string& name, ACE_INET_Addr const& address, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float popu, uint32 build);
void UpdateRealm(uint32 id, const std::string& name, ACE_INET_Addr const& address, ACE_INET_Addr const& localAddr, ACE_INET_Addr const& localSubmask, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float popu, uint32 build);

RealmMap m_realms;
uint32 m_UpdateInterval;
@@ -818,6 +818,28 @@ bool AuthSocket::_HandleReconnectProof()
}
}

ACE_INET_Addr const& AuthSocket::GetAddressForClient(Realm const& realm, ACE_INET_Addr const& clientAddr)
{
// Attempt to send best address for client
if (clientAddr.is_loopback())
{
// Try guessing if realm is also connected locally
if (realm.LocalAddress.is_loopback() || realm.ExternalAddress.is_loopback())
return clientAddr;

// Assume that user connecting from the machine that authserver is located on
// has all realms available in his local network
return realm.LocalAddress;
}

// Check if connecting client is in the same network
if (IsIPAddrInNetwork(realm.LocalAddress, clientAddr, realm.LocalSubnetMask))
return realm.LocalAddress;

// Return external IP
return realm.ExternalAddress;
}

// Realm List command handler
bool AuthSocket::_HandleRealmList()
{
@@ -845,6 +867,9 @@ bool AuthSocket::_HandleRealmList()
// Update realm list if need
sRealmList->UpdateIfNeed();

ACE_INET_Addr clientAddr;
socket().peer().get_remote_addr(clientAddr);

// Circle through realms in the RealmList and construct the return packet (including # of user characters in each realm)
ByteBuffer pkt;

@@ -876,6 +901,9 @@ bool AuthSocket::_HandleRealmList()
name = ss.str();
}

// We don't need the port number from which client connects with but the realm's port
clientAddr.set_port_number(i->second.ExternalAddress.get_port_number());

uint8 lock = (i->second.allowedSecurityLevel > _accountSecurityLevel) ? 1 : 0;

uint8 AmountOfCharacters = 0;
@@ -891,7 +919,7 @@ bool AuthSocket::_HandleRealmList()
pkt << lock; // if 1, then realm locked
pkt << uint8(flag); // RealmFlags
pkt << name;
pkt << i->second.address;
pkt << GetAddressString(GetAddressForClient(i->second, clientAddr));
pkt << i->second.populationLevel;
pkt << AmountOfCharacters;
pkt << i->second.timezone; // realm category
@@ -23,6 +23,9 @@
#include "BigNumber.h"
#include "RealmSocket.h"

class ACE_INET_Addr;
struct Realm;

// Handle login commands
class AuthSocket: public RealmSocket::Session
{
@@ -36,6 +39,8 @@ class AuthSocket: public RealmSocket::Session
virtual void OnAccept(void);
virtual void OnClose(void);

static ACE_INET_Addr const& GetAddressForClient(Realm const& realm, ACE_INET_Addr const& clientAddr);

bool _HandleLogonChallenge();
bool _HandleLogonProof();
bool _HandleReconnectChallenge();
@@ -22,7 +22,7 @@ void LoginDatabaseConnection::DoPrepareStatements()
if (!m_reconnecting)
m_stmts.resize(MAX_LOGINDATABASE_STATEMENTS);

PrepareStatement(LOGIN_SEL_REALMLIST, "SELECT id, name, address, port, icon, flag, timezone, allowedSecurityLevel, population, gamebuild FROM realmlist WHERE flag <> 3 ORDER BY name", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_REALMLIST, "SELECT id, name, address, localAddress, localSubnetMask, port, icon, flag, timezone, allowedSecurityLevel, population, gamebuild FROM realmlist WHERE flag <> 3 ORDER BY name", CONNECTION_SYNCH);
PrepareStatement(LOGIN_DEL_EXPIRED_IP_BANS, "DELETE FROM ip_banned WHERE unbandate<>bandate AND unbandate<=UNIX_TIMESTAMP()", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_EXPIRED_ACCOUNT_BANS, "UPDATE account_banned SET active = 0 WHERE active = 1 AND unbandate<>bandate AND unbandate<=UNIX_TIMESTAMP()", CONNECTION_ASYNC);
PrepareStatement(LOGIN_SEL_IP_BANNED, "SELECT * FROM ip_banned WHERE ip = ?", CONNECTION_SYNCH);
@@ -22,7 +22,6 @@
#include "SFMT.h"
#include "Errors.h" // for ASSERT
#include <ace/TSS_T.h>
#include <ace/INET_Addr.h>

typedef ACE_TSS<SFMTRand> SFMTRandTSS;
static SFMTRandTSS sfmtRand;
@@ -239,6 +238,21 @@ bool IsIPAddress(char const* ipaddress)
return inet_addr(ipaddress) != INADDR_NONE;
}

std::string GetAddressString(ACE_INET_Addr const& addr)
{
char buf[ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 16];
addr.addr_to_string(buf, ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 16);
return buf;
}

bool IsIPAddrInNetwork(ACE_INET_Addr const& net, ACE_INET_Addr const& addr, ACE_INET_Addr const& subnetMask)
{
uint32 mask = subnetMask.get_ip_address();
if ((net.get_ip_address() & mask) == (addr.get_ip_address() & mask))
return true;
return false;
}

/// create PID file
uint32 CreatePIDFile(const std::string& filename)
{
@@ -25,6 +25,7 @@
#include <string>
#include <vector>
#include <list>
#include <ace/INET_Addr.h>

// Searcher for map of structs
template<typename T, class S> struct Finder
@@ -343,6 +344,13 @@ void utf8printf(FILE* out, const char *str, ...);
void vutf8printf(FILE* out, const char *str, va_list* ap);

bool IsIPAddress(char const* ipaddress);

/// Checks if address belongs to the a network with specified submask
bool IsIPAddrInNetwork(ACE_INET_Addr const& net, ACE_INET_Addr const& addr, ACE_INET_Addr const& subnetMask);

/// Transforms ACE_INET_Addr address into string format "dotted_ip:port"
std::string GetAddressString(ACE_INET_Addr const& addr);

uint32 CreatePIDFile(const std::string& filename);

std::string ByteArrayToHexStr(uint8 const* bytes, uint32 length, bool reverse = false);

12 comments on commit 6e80357

@Kingswow

This comment has been minimized.

Copy link

Kingswow replied Jan 27, 2013

What does it do?

@terabyte101

This comment has been minimized.

Copy link

terabyte101 replied Jan 27, 2013

allowes localhost to join the server and players from over the internet

@vlad852

This comment has been minimized.

Copy link
Contributor

vlad852 replied Jan 27, 2013

Good one.

@sonic3000

This comment has been minimized.

Copy link
Contributor

sonic3000 replied Jan 27, 2013

@Shauren awesome work 👍

Thanks

@Paradox

This comment has been minimized.

Copy link
Contributor

Paradox replied Jan 27, 2013

I don't recall ever having a problem doing this (probably because my router accepts "loopback" connections) but, I have seen many who have, so, good job.

@Lillecarl

This comment has been minimized.

Copy link

Lillecarl replied Jan 27, 2013

I think everyone got a router with loopback? :O

@Paradox

This comment has been minimized.

Copy link
Contributor

Paradox replied Jan 28, 2013

no. local loopback has nothing to do with your router, it happens locally, the "loopback" (notice the quotes) I'm speaking of, is, some routers will not allow you to connect to your own external (Internet) address, for some retarded reason.

@Aokromes

This comment has been minimized.

Copy link
Member

Aokromes replied Jan 28, 2013

You mean Most of routers.

@Shauren

This comment has been minimized.

Copy link
Member Author

Shauren replied Jan 28, 2013

@Paradox - this a security feature (firewall, but not really configurable), connections coming from your own address will be always dropped (imagine me being the attacker, sending packets to you with your own IP) - if networks are configured properly, such situation should never take place (which is why it's a security thing).

@Bezo

This comment has been minimized.

Copy link
Contributor

Bezo replied Jan 28, 2013

i guess they do that to prevent from this happen again : http://www.frihost.com/forums/vt-51466.html

@Paradox

This comment has been minimized.

Copy link
Contributor

Paradox replied Jan 28, 2013

Once again, local loopback (127.0.0.1) has nothing at all to do with what I'm talking about.

@FuriousPy

This comment has been minimized.

Copy link

FuriousPy replied Jan 31, 2013

TKSSSSSSSSS i doing a hack to join into my server... no more hack :D

Please sign in to comment.
You can’t perform that action at this time.