summaryrefslogtreecommitdiff
path: root/src/login
diff options
context:
space:
mode:
authorHaru <haru@dotalux.com>2015-08-10 21:48:48 +0200
committerHaru <haru@dotalux.com>2015-08-11 15:17:11 +0200
commite13f1f782a9d8d25cc622d050644c7f29c1bfd5e (patch)
tree34e7565fe11ead41519428143b3dc44b752b6e4b /src/login
parenta8e54e5688bd3d7b8e9073274ff611040c3178ab (diff)
downloadhercules-e13f1f782a9d8d25cc622d050644c7f29c1bfd5e.tar.gz
hercules-e13f1f782a9d8d25cc622d050644c7f29c1bfd5e.tar.bz2
hercules-e13f1f782a9d8d25cc622d050644c7f29c1bfd5e.tar.xz
hercules-e13f1f782a9d8d25cc622d050644c7f29c1bfd5e.zip
subnet.conf overhaul
The subnet.conf system has been rewritten to offer greater flexibility, and to fix some issues that appeared with 838321a36c79e71117320154c9b611c99e93af03. It is now possible to enter, separately, LAN subnets: - `lan_subnets`: This is essentially the same feature present in the old subnet.conf. Each entry in this list defines a (LAN, private) subnet the server is in. Clients connecting from the same subnet, will be redirected to the LAN IP rather than the default public IP. The format has been simplified, and it only requires one IP and one subnet mask (as opposed to a character and a map server IP). - `allowed`: Allowed IPs are IP ranges a server (char to login or map to char) can connect from. Any attempt to connect as a server from an IP not included here, will fail. For convenience, a wildcard range (matching all possible IP addresses) has been provided (`0.0.0.0:0.0.0.0`), but it is very advisable to edit it to a more restrictive set. - `trusted`: Trusted IPs are IP ranges excluded from the IPban checks. This may be useful, for example, to exclude the server's own IP from ipbans, in case of false positives. Any IP ranges added to this list are also implicitly included in the allowed IP ranges.
Diffstat (limited to 'src/login')
-rw-r--r--src/login/login.c103
-rw-r--r--src/login/login.h13
2 files changed, 29 insertions, 87 deletions
diff --git a/src/login/login.c b/src/login/login.c
index caace34da..141ab5e2b 100644
--- a/src/login/login.c
+++ b/src/login/login.c
@@ -12,6 +12,7 @@
#include "login/loginlog.h"
#include "common/HPM.h"
#include "common/cbasetypes.h"
+#include "common/conf.h"
#include "common/core.h"
#include "common/db.h"
#include "common/malloc.h"
@@ -238,65 +239,17 @@ bool login_check_password(const char* md5key, int passwdenc, const char* passwd,
}
}
-//--------------------------------------------
-// Test to know if an IP come from LAN or WAN.
-//--------------------------------------------
-int login_lan_subnetcheck(uint32 ip)
-{
- int i;
- ARR_FIND( 0, login_config.subnet_count, i, (login_config.subnet[i].char_ip & login_config.subnet[i].mask) == (ip & login_config.subnet[i].mask) );
- return ( i < login_config.subnet_count ) ? login_config.subnet[i].char_ip : 0;
-}
-//----------------------------------
-// Reading LAN Support configuration
-//----------------------------------
-int login_lan_config_read(const char *lancfgName)
+/**
+ * Checks whether the given IP comes from LAN or WAN.
+ *
+ * @param ip IP address to check.
+ * @retval 0 if it is a WAN IP.
+ * @return the appropriate LAN server address to send, if it is a LAN IP.
+ */
+uint32 login_lan_subnet_check(uint32 ip)
{
- FILE *fp;
- int line_num = 0;
- char line[1024], w1[64], w2[64], w3[64], w4[64];
-
- nullpo_ret(lancfgName);
- if((fp = fopen(lancfgName, "r")) == NULL) {
- ShowWarning("LAN Support configuration file is not found: %s\n", lancfgName);
- return 1;
- }
-
- while(fgets(line, sizeof(line), fp))
- {
- line_num++;
- if ((line[0] == '/' && line[1] == '/') || line[0] == '\n' || line[1] == '\n')
- continue;
-
- if (sscanf(line, "%63[^:]: %63[^:]:%63[^:]:%63[^\r\n]", w1, w2, w3, w4) != 4) {
- ShowWarning("Error syntax of configuration file %s in line %d.\n", lancfgName, line_num);
- continue;
- }
-
- if( strcmpi(w1, "subnet") == 0 )
- {
- login_config.subnet[login_config.subnet_count].mask = str2ip(w2);
- login_config.subnet[login_config.subnet_count].char_ip = str2ip(w3);
- login_config.subnet[login_config.subnet_count].map_ip = str2ip(w4);
-
- if( (login_config.subnet[login_config.subnet_count].char_ip
- & login_config.subnet[login_config.subnet_count].mask) != (login_config.subnet[login_config.subnet_count].map_ip
- & login_config.subnet[login_config.subnet_count].mask) )
- {
- ShowError("%s: Configuration Error: The char server (%s) and map server (%s) belong to different subnetworks!\n", lancfgName, w3, w4);
- continue;
- }
-
- login_config.subnet_count++;
- }
- }
-
- if( login_config.subnet_count > 1 ) /* only useful if there is more than 1 available */
- ShowStatus("Read information about %d subnetworks.\n", login_config.subnet_count);
-
- fclose(fp);
- return 0;
+ return sockt->lan_subnet_check(ip, NULL);
}
void login_fromchar_auth_ack(int fd, int account_id, uint32 login_id1, uint32 login_id2, uint8 sex, int request_id, struct login_auth_node* node)
@@ -1233,7 +1186,6 @@ void login_auth_ok(struct login_session_data* sd)
int fd = 0;
uint32 ip;
uint8 server_num, n;
- uint32 subnet_char_ip;
struct login_auth_node* node;
int i;
@@ -1308,12 +1260,13 @@ void login_auth_ok(struct login_session_data* sd)
memset(WFIFOP(fd,20), 0, 24);
WFIFOW(fd,44) = 0; // unknown
WFIFOB(fd,46) = sex_str2num(sd->sex);
- for( i = 0, n = 0; i < ARRAYLENGTH(server); ++i )
- {
+ for (i = 0, n = 0; i < ARRAYLENGTH(server); ++i) {
+ uint32 subnet_char_ip;
+
if( !session_isValid(server[i].fd) )
continue;
- subnet_char_ip = login->lan_subnetcheck(ip); // Advanced subnet check [LuzZza]
+ subnet_char_ip = login->lan_subnet_check(ip);
WFIFOL(fd,47+n*32) = htonl((subnet_char_ip) ? subnet_char_ip : server[i].ip);
WFIFOW(fd,47+n*32+4) = ntows(htons(server[i].port)); // [!] LE byte order here [!]
memcpy(WFIFOP(fd,47+n*32+6), server[i].name, 20);
@@ -1393,7 +1346,7 @@ void login_auth_failed(struct login_session_data* sd, int result)
login_log(ip, sd->userid, result, error); // FIXME: result can be 100, conflicting with the value 100 we use for successful login...
}
- if( result == 1 && login_config.dynamic_pass_failure_ban )
+ if (result == 1 && login_config.dynamic_pass_failure_ban && !sockt->trusted_ip_check(ip))
ipban_log(ip); // log failed password attempt
#if PACKETVER >= 20120000 /* not sure when this started */
@@ -1590,7 +1543,7 @@ void login_parse_request_connection(int fd, struct login_session_data* sd, const
sd->account_id >= 0 &&
sd->account_id < ARRAYLENGTH(server) &&
!session_isValid(server[sd->account_id].fd) &&
- login->lan_subnetcheck(ipl))
+ sockt->allowed_ip_check(ipl))
{
ShowStatus("Connection of the char-server '%s' accepted.\n", server_name);
safestrncpy(server[sd->account_id].name, server_name, sizeof(server[sd->account_id].name));
@@ -1637,7 +1590,7 @@ int login_parse_login(int fd)
if( sd == NULL )
{
// Perform ip-ban check
- if( login_config.ipban && ipban_check(ipl) )
+ if (login_config.ipban && !sockt->trusted_ip_check(ipl) && ipban_check(ipl))
{
ShowStatus("Connection refused: IP isn't authorized (deny/allow, ip: %s).\n", ip);
login_log(ipl, "unknown", -3, "ip banned");
@@ -1759,7 +1712,6 @@ void login_set_defaults()
login_config.client_hash_check = 0;
login_config.client_hash_nodes = NULL;
- login_config.subnet_count = 0;
}
//-----------------------------------
@@ -1929,7 +1881,7 @@ int do_final(void) {
HPM_login_do_final();
aFree(login->LOGIN_CONF_NAME);
- aFree(login->LAN_CONF_NAME);
+ aFree(login->NET_CONF_NAME);
HPM->event(HPET_POST_FINAL);
@@ -1984,15 +1936,15 @@ static CMDLINEARG(loginconfig)
return true;
}
/**
- * --lan-config handler
+ * --net-config handler
*
* Overrides the default subnet configuration file.
* @see cmdline->exec
*/
-static CMDLINEARG(lanconfig)
+static CMDLINEARG(netconfig)
{
- aFree(login->LAN_CONF_NAME);
- login->LAN_CONF_NAME = aStrdup(params);
+ aFree(login->NET_CONF_NAME);
+ login->NET_CONF_NAME = aStrdup(params);
return true;
}
/**
@@ -2001,7 +1953,7 @@ static CMDLINEARG(lanconfig)
void cmdline_args_init_local(void)
{
CMDLINEARG_DEF2(login-config, loginconfig, "Alternative login-server configuration.", CMDLINE_OPT_PARAM);
- CMDLINEARG_DEF2(lan-config, lanconfig, "Alternative subnet configuration.", CMDLINE_OPT_PARAM);
+ CMDLINEARG_DEF2(net-config, netconfig, "Alternative subnet configuration.", CMDLINE_OPT_PARAM);
}
//------------------------------
@@ -2025,7 +1977,7 @@ int do_init(int argc, char** argv)
login_set_defaults();
login->LOGIN_CONF_NAME = aStrdup("conf/login-server.conf");
- login->LAN_CONF_NAME = aStrdup("conf/subnet.conf");
+ login->NET_CONF_NAME = aStrdup("conf/network.conf");
HPM_login_do_init();
HPM->symbol_defaults_sub = login_hp_symbols;
@@ -2035,7 +1987,7 @@ int do_init(int argc, char** argv)
cmdline->exec(argc, argv, CMDLINE_OPT_NORMAL);
login_config_read(login->LOGIN_CONF_NAME);
- login->lan_config_read(login->LAN_CONF_NAME);
+ sockt->net_config_read(login->NET_CONF_NAME);
for( i = 0; i < ARRAYLENGTH(server); ++i )
chrif_server_init(i);
@@ -2112,8 +2064,7 @@ void login_defaults(void) {
login->sync_ip_addresses = login_sync_ip_addresses;
login->check_encrypted = login_check_encrypted;
login->check_password = login_check_password;
- login->lan_subnetcheck = login_lan_subnetcheck;
- login->lan_config_read = login_lan_config_read;
+ login->lan_subnet_check = login_lan_subnet_check;
login->fromchar_auth_ack = login_fromchar_auth_ack;
login->fromchar_accinfo = login_fromchar_accinfo;
@@ -2159,5 +2110,5 @@ void login_defaults(void) {
login->send_coding_key = login_send_coding_key;
login->LOGIN_CONF_NAME = NULL;
- login->LAN_CONF_NAME = NULL;
+ login->NET_CONF_NAME = NULL;
}
diff --git a/src/login/login.h b/src/login/login.h
index de504db07..6dc4c875b 100644
--- a/src/login/login.h
+++ b/src/login/login.h
@@ -101,14 +101,6 @@ struct Login_Config {
int client_hash_check; ///< flags for checking client md5
struct client_hash_node *client_hash_nodes; ///< linked list containg md5 hash for each gm group
-
- /// Advanced subnet check [LuzZza]
- struct s_subnet {
- uint32 mask;
- uint32 char_ip;
- uint32 map_ip;
- } subnet[16];
- int subnet_count;
};
struct login_auth_node {
@@ -163,8 +155,7 @@ struct login_interface {
int (*sync_ip_addresses) (int tid, int64 tick, int id, intptr_t data);
bool (*check_encrypted) (const char* str1, const char* str2, const char* passwd);
bool (*check_password) (const char* md5key, int passwdenc, const char* passwd, const char* refpass);
- int (*lan_subnetcheck) (uint32 ip);
- int (*lan_config_read) (const char *lancfgName);
+ uint32 (*lan_subnet_check) (uint32 ip);
void (*fromchar_accinfo) (int fd, int account_id, int u_fd, int u_aid, int u_group, int map_fd, struct mmo_account *acc);
void (*fromchar_account) (int fd, int account_id, struct mmo_account *acc);
void (*fromchar_account_update_other) (int account_id, unsigned int state);
@@ -207,7 +198,7 @@ struct login_interface {
void (*parse_request_connection) (int fd, struct login_session_data* sd, const char *ip, uint32 ipl);
int (*parse_login) (int fd);
char *LOGIN_CONF_NAME;
- char *LAN_CONF_NAME;
+ char *NET_CONF_NAME; ///< Network configuration filename
};
struct login_interface *login;