Skip to content

Commit

Permalink
Core/Authserver: Added possibility to allow realm connections both fr…
Browse files Browse the repository at this point in the history
…om "world" and local networks.
  • Loading branch information
Shauren committed Jan 27, 2013
1 parent e1d12de commit 6e80357
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 23 deletions.
2 changes: 2 additions & 0 deletions sql/base/auth_database.sql
Expand Up @@ -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',
Expand Down
3 changes: 3 additions & 0 deletions sql/updates/auth/2013_01_27_00_auth_realmlist.sql
@@ -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`;
42 changes: 24 additions & 18 deletions src/server/authserver/Realms/RealmList.cpp
Expand Up @@ -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;
Expand All @@ -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;
}

Expand Down Expand Up @@ -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());
}
Expand Down
6 changes: 4 additions & 2 deletions src/server/authserver/Realms/RealmList.h
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
30 changes: 29 additions & 1 deletion src/server/authserver/Server/AuthSocket.cpp
Expand Up @@ -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()
{
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand All @@ -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
Expand Down
5 changes: 5 additions & 0 deletions src/server/authserver/Server/AuthSocket.h
Expand Up @@ -23,6 +23,9 @@
#include "BigNumber.h"
#include "RealmSocket.h"

class ACE_INET_Addr;
struct Realm;

// Handle login commands
class AuthSocket: public RealmSocket::Session
{
Expand All @@ -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();
Expand Down
Expand Up @@ -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);
Expand Down
16 changes: 15 additions & 1 deletion src/server/shared/Utilities/Util.cpp
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
{
Expand Down
8 changes: 8 additions & 0 deletions src/server/shared/Utilities/Util.h
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down

12 comments on commit 6e80357

@Kingswow
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does it do?

@terabyte101
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@vlad852
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good one.

@sonic3000
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Shauren awesome work 👍

Thanks

@Paradox
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think everyone got a router with loopback? :O

@Paradox
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean Most of routers.

@Shauren
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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
Copy link
Contributor

@Bezo Bezo commented on 6e80357 Jan 28, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@Paradox
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@FuriousPy
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Please sign in to comment.