From feea52f79ed0aec52a3d97c117568b5226f2e739 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Fri, 5 Jul 2019 03:38:12 -0500 Subject: [PATCH] Make loginserver intelligently determine if the client is requesting from a RFC 1918 network instead of using a config string match --- common/CMakeLists.txt | 2 + common/data_verification.h | 68 +++++++++++++++++--------------- common/ip_util.cpp | 72 ++++++++++++++++++++++++++++++++++ common/ip_util.h | 36 +++++++++++++++++ loginserver/main.cpp | 1 - loginserver/options.h | 10 ----- loginserver/server_manager.cpp | 6 ++- loginserver/world_server.cpp | 12 +++--- 8 files changed, 155 insertions(+), 52 deletions(-) create mode 100644 common/ip_util.cpp create mode 100644 common/ip_util.h diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 2c94d618a..a1c2c51a2 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -35,6 +35,7 @@ SET(common_sources inventory_profile.cpp inventory_slot.cpp ipc_mutex.cpp + ip_util.cpp item_data.cpp item_instance.cpp json_config.cpp @@ -159,6 +160,7 @@ SET(common_headers inventory_profile.h inventory_slot.h ipc_mutex.h + ip_util.h item_data.h item_fieldlist.h item_instance.h diff --git a/common/data_verification.h b/common/data_verification.h index 27ad017a9..c56f3ce04 100644 --- a/common/data_verification.h +++ b/common/data_verification.h @@ -1,53 +1,57 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ +/** + * EQEmulator: Everquest Server Emulator + * Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY except by those people which sell it, which + * are required to give you total support for your newly bought product; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ #pragma once #include #include -namespace EQEmu -{ - template - T Clamp(const T& value, const T& lower, const T& upper) { +namespace EQEmu { + template + T Clamp(const T &value, const T &lower, const T &upper) + { return std::max(lower, std::min(value, upper)); } - template - T ClampLower(const T& value, const T& lower) { + template + T ClampLower(const T &value, const T &lower) + { return std::max(lower, value); } - template - T ClampUpper(const T& value, const T& upper) { + template + T ClampUpper(const T &value, const T &upper) + { return std::min(value, upper); } - template - bool ValueWithin(const T& value, const T& lower, const T& upper) { + template + bool ValueWithin(const T &value, const T &lower, const T &upper) + { return value >= lower && value <= upper; } - template - bool ValueWithin(const T1& value, const T2& lower, const T3& upper) { - return value >= (T1)lower && value <= (T1)upper; + template + bool ValueWithin(const T1 &value, const T2 &lower, const T3 &upper) + { + return value >= (T1) lower && value <= (T1) upper; } - } /*EQEmu*/ diff --git a/common/ip_util.cpp b/common/ip_util.cpp new file mode 100644 index 000000000..e1f5d0794 --- /dev/null +++ b/common/ip_util.cpp @@ -0,0 +1,72 @@ +/** + * EQEmulator: Everquest Server Emulator + * Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY except by those people which sell it, which + * are required to give you total support for your newly bought product; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "ip_util.h" + +/** + * @param ip + * @return + */ +uint32_t IpUtil::IPToUInt(const std::string &ip) +{ + int a, b, c, d; + uint32_t addr = 0; + + if (sscanf(ip.c_str(), "%d.%d.%d.%d", &a, &b, &c, &d) != 4) { + return 0; + } + + addr = a << 24; + addr |= b << 16; + addr |= c << 8; + addr |= d; + return addr; +} + +/** + * @param ip + * @param network + * @param mask + * @return + */ +bool IpUtil::IsIpInRange(const std::string &ip, const std::string &network, const std::string &mask) +{ + uint32_t ip_addr = IpUtil::IPToUInt(ip); + uint32_t network_addr = IpUtil::IPToUInt(network); + uint32_t mask_addr = IpUtil::IPToUInt(mask); + + uint32_t net_lower = (network_addr & mask_addr); + uint32_t net_upper = (net_lower | (~mask_addr)); + + return ip_addr >= net_lower && ip_addr <= net_upper; +} + +/** + * @param ip + * @return + */ +bool IpUtil::IsIpInPrivateRfc1918(const std::string &ip) +{ + return ( + IpUtil::IsIpInRange(ip, "10.0.0.0", "255.0.0.0") || + IpUtil::IsIpInRange(ip, "172.16.0.0", "255.240.0.0") || + IpUtil::IsIpInRange(ip, "192.168.0.0", "255.255.0.0") + ); +} diff --git a/common/ip_util.h b/common/ip_util.h new file mode 100644 index 000000000..76ea33fdb --- /dev/null +++ b/common/ip_util.h @@ -0,0 +1,36 @@ +/** + * EQEmulator: Everquest Server Emulator + * Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY except by those people which sell it, which + * are required to give you total support for your newly bought product; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef EQEMU_IP_UTIL_H +#define EQEMU_IP_UTIL_H + +#include "types.h" +#include "iostream" + +class IpUtil { +public: + + static uint32_t IPToUInt(const std::string &ip); + static bool IsIpInRange(const std::string &ip, const std::string &network, const std::string &mask); + static bool IsIpInPrivateRfc1918(const std::string &ip); + +}; + +#endif //EQEMU_IP_UTIL_H \ No newline at end of file diff --git a/loginserver/main.cpp b/loginserver/main.cpp index 26a32578f..3a9accbd8 100644 --- a/loginserver/main.cpp +++ b/loginserver/main.cpp @@ -68,7 +68,6 @@ int main() server.options.WorldTrace(server.config.GetVariableBool("general", "world_trace", false)); server.options.DumpInPackets(server.config.GetVariableBool("general", "dump_packets_in", false)); server.options.DumpOutPackets(server.config.GetVariableBool("general", "dump_packets_out", false)); - server.options.LocalNetwork(server.config.GetVariableString("general", "local_network", "192.168.1.")); server.options.RejectDuplicateServers(server.config.GetVariableBool("general", "reject_duplicate_servers", false)); server.options.AutoCreateAccounts(server.config.GetVariableBool("general", "auto_create_accounts", true)); server.options.AutoLinkAccounts(server.config.GetVariableBool("general", "auto_link_accounts", true)); diff --git a/loginserver/options.h b/loginserver/options.h index aeeed6731..00abd7abf 100644 --- a/loginserver/options.h +++ b/loginserver/options.h @@ -103,16 +103,6 @@ public: */ inline int GetEncryptionMode() const { return encryption_mode; } - /** - * Sets local_network. - */ - inline void LocalNetwork(std::string n) { local_network = n; } - - /** - * Return the value of local_network. - */ - inline std::string GetLocalNetwork() const { return local_network; } - /** * Sets account table. */ diff --git a/loginserver/server_manager.cpp b/loginserver/server_manager.cpp index df0428feb..9b584e2fe 100644 --- a/loginserver/server_manager.cpp +++ b/loginserver/server_manager.cpp @@ -25,6 +25,7 @@ #include "../common/eqemu_logsys.h" #include "../common/eqemu_logsys_fmt.h" +#include "../common/ip_util.h" extern LoginServer server; extern bool run_server; @@ -137,7 +138,8 @@ EQApplicationPacket *ServerManager::CreateServerListPacket(Client *client, uint3 if (world_ip.compare(client_ip) == 0) { packet_size += (*iter)->GetLongName().size() + (*iter)->GetLocalIP().size() + 24; } - else if (client_ip.find(server.options.GetLocalNetwork()) != std::string::npos) { + else if (IpUtil::IsIpInPrivateRfc1918(client_ip)) { + LogLoginserver("Client is requesting server list from a local address [{0}]", client_ip); packet_size += (*iter)->GetLongName().size() + (*iter)->GetLocalIP().size() + 24; } else { @@ -177,7 +179,7 @@ EQApplicationPacket *ServerManager::CreateServerListPacket(Client *client, uint3 memcpy(data_pointer, (*iter)->GetLocalIP().c_str(), (*iter)->GetLocalIP().size()); data_pointer += ((*iter)->GetLocalIP().size() + 1); } - else if (client_ip.find(server.options.GetLocalNetwork()) != std::string::npos) { + else if (IpUtil::IsIpInPrivateRfc1918(client_ip)) { memcpy(data_pointer, (*iter)->GetLocalIP().c_str(), (*iter)->GetLocalIP().size()); data_pointer += ((*iter)->GetLocalIP().size() + 1); } diff --git a/loginserver/world_server.cpp b/loginserver/world_server.cpp index f8c848123..d50cf6ccc 100644 --- a/loginserver/world_server.cpp +++ b/loginserver/world_server.cpp @@ -24,6 +24,7 @@ #include "config.h" #include "../common/eqemu_logsys.h" #include "../common/eqemu_logsys_fmt.h" +#include "../common/ip_util.h" extern LoginServer server; @@ -556,17 +557,13 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct *new_world_server_info if (server.options.IsRejectingDuplicateServers()) { if (server.server_manager->ServerExists(long_name, short_name, this)) { - Log(Logs::General, - Logs::Error, - "World tried to login but there already exists a server that has that name."); + Error("World tried to login but there already exists a server that has that name"); return; } } else { if (server.server_manager->ServerExists(long_name, short_name, this)) { - Log(Logs::General, - Logs::Error, - "World tried to login but there already exists a server that has that name."); + Error("World tried to login but there already exists a server that has that name"); server.server_manager->DestroyServerByName(long_name, short_name, this); } } @@ -783,7 +780,8 @@ void WorldServer::SendClientAuth( if (client_address.compare(world_address) == 0) { client_auth.local = 1; } - else if (client_address.find(server.options.GetLocalNetwork()) != std::string::npos) { + else if (IpUtil::IsIpInPrivateRfc1918(client_address)) { + LogLoginserver("Client is authenticating from a local address [{0}]", client_address); client_auth.local = 1; } else {