Permalink
Browse files

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

…om "world" and local networks.
  • Loading branch information...
1 parent e1d12de commit 6e80357f8e8b4e820bab8bd05fb8457c3cb46d11 @Shauren Shauren committed Jan 27, 2013
View
2 sql/base/auth_database.sql
@@ -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',
View
3 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`;
View
42 src/server/authserver/Realms/RealmList.cpp
@@ -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());
}
View
6 src/server/authserver/Realms/RealmList.h
@@ -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;
View
30 src/server/authserver/Server/AuthSocket.cpp
@@ -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
View
5 src/server/authserver/Server/AuthSocket.h
@@ -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();
View
2 src/server/shared/Database/Implementation/LoginDatabase.cpp
@@ -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);
View
16 src/server/shared/Utilities/Util.cpp
@@ -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)
{
View
8 src/server/shared/Utilities/Util.h
@@ -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

What does it do?

@terabyte101

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

@vlad852

Good one.

@sonic3000

@Shauren awesome work 👍

Thanks

@Paradox

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

I think everyone got a router with loopback? :O

@Paradox

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
TrinityCore member

You mean Most of routers.

@Shauren
TrinityCore member

@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

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

@Paradox

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

@FuriousPy

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

Please sign in to comment.