瀏覽代碼

Some more txt/sql login server synchronization:
- removed the option to specify multiple IPs/subnets for 'ladminallowip'
- removed the @gm command and all associated management code
- removed the 'save unknown packets' code
- removed the lengthy TXT ipban code (which was essentially a copy of what's already handled by the socket layer/packet_athena.conf)
- implemented 'start_limited_time' in SQL (expiration for new accounts)
- applied some missing TXT changes from the last update

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@12446 54d463be-8e91-2dee-dedb-b68131a5f0ec

ultramage 17 年之前
父節點
當前提交
76eb9581b9
共有 14 個文件被更改,包括 161 次插入782 次删除
  1. 9 0
      Changelog-Trunk.txt
  2. 0 1
      conf/atcommand_athena.conf
  3. 0 1
      conf/help2.txt
  4. 2 46
      conf/login_athena.conf
  5. 0 32
      src/char/char.c
  6. 0 41
      src/char_sql/char.c
  7. 0 41
      src/login/admin.c
  8. 77 473
      src/login/login.c
  9. 22 21
      src/login/login.h
  10. 26 30
      src/login_sql/login.c
  11. 22 21
      src/login_sql/login.h
  12. 0 25
      src/map/atcommand.c
  13. 3 49
      src/map/chrif.c
  14. 0 1
      src/map/chrif.h

+ 9 - 0
Changelog-Trunk.txt

@@ -3,6 +3,15 @@ Date	Added
 AS OF SVN REV. 5091, WE ARE NOW USING TRUNK.  ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK.
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 
+2008/03/28
+	* Some more txt/sql login server synchronization [ultramage]
+	- removed the option to specify multiple IPs/subnets for 'ladminallowip'
+	- removed the @gm command and all associated management code
+	- removed the 'save unknown packets' code
+	- removed the lengthy TXT ipban code (which was essentially a copy of
+	  what's already handled by the socket layer/packet_athena.conf)
+	- implemented 'start_limited_time' in SQL (expiration for new accounts)
+	- applied some missing TXT changes from the last update
 2008/03/27
 	* Updated SQL Files (item & mobs) [Toms]
 	* Partial rewrite of the login server's auth system.

+ 0 - 1
conf/atcommand_athena.conf

@@ -774,7 +774,6 @@ clearweather: 99
 
 //---------------------------------------------------------------
 // 100: Disabled commands
-gm: 100
 
 //---------------------
 // OTHER: not a command

+ 0 - 1
conf/help2.txt

@@ -92,4 +92,3 @@
  99:@gat - For debugging (you inspect around gat)
  99:@packet - For debugging (packet variety)
 100:@nuke <char name> -
-100:@GM <password> - it becomes GM! (password is set in login_athena.conf)

+ 2 - 46
conf/login_athena.conf

@@ -43,12 +43,8 @@ admin_state: no
 // NOTE: ladmin only works on TXT login servers.
 admin_pass: admin
 
-// Indicate the IP that the server accepts for remote administration.
-// put: 'all', or 'xxx.xxx.' (begin of an ip finished by '.' or a complete ip),
-//      or a network and its mask (example: '123.456.789.012/24' or '123.456.789.012/255.255.255.0')
-//      or 'clear' to suppress previous parameter (use it in import file mainly)
-// Add as many IP's as you wish.
-ladminallowip: all
+// Indicate the IP/host that the server accepts for remote administration.
+admin_allowed_ip: 127.0.0.1
 
 // Console Commands
 // Allow for console commands to be used on/off
@@ -58,19 +54,6 @@ console: off
 // Are logins case sensitive? (SQL only)
 case_sensitive: yes
 
-// Gamemaster password, used with the @gm command to obtain GM commands (level of gm set with level_new_gm parameter).
-// NOTICE: You should also change this one.
-gm_pass: gm
-
-// Level of new GM created with @gm command. (default: 60)
-// If you set to 0, you disable creation of new GM with @gm.
-// To be able to create a gm with @gm, you must:
-// - give a level to this value (not 0)
-// - enable to level 0 the @gm command (atcommand_athena.conf) (default 100)
-// - enable gm commands to normal player (battle_athena.conf, atcommand_gm_only parameter)
-// - and normal player must give correct password when he use the @gm command
-level_new_gm: 60
-
 // Can you use _M/_F to make new accounts on the server?
 new_account: yes
 
@@ -93,21 +76,12 @@ gm_account_filename_check_timer: 15
 // NOTE: The login-sql server needs the login logs to enable dynamic pass failure bans.
 log_login: yes
 
-// Name of the file of that logs the unknown packets (for debug or hack check)
-login_log_unknown_packets_filename: log/login_unknown_packets.log
-
 //When set to yes, the login server will refuse connections from accounts that are considered online already. 
 //When a login attempt is rejected, the account in question is also kicked from all connected char-servers.
 //It's safe to turn this off if there's only one char-server connected, or if the char-servers don't share 
 //the same backend (ie: Multiple char servers reading from the same SQL tables)
 online_check: yes
 
-// Indicate if the unknown packets are saved or not
-//(the unknown packets coming from the char-server or ladministration does not relate to, which is always saved)
-// Be careful: if you receive an attack, your hard disk can cause lag...
-// So, active this option with a speed hard disk or for debug only.
-save_unknown_packets: 0
-
 // Indicate how to display date in logs, to players, etc.
 date_format: %Y-%m-%d %H:%M:%S
 
@@ -125,24 +99,6 @@ add_to_unlimited_account: off
 // 0 or more: new accounts was created by addition of the value (in sec) to the actual time (to set first limited time)
 start_limited_time: -1
 
-// Ipban features (TXT only):
-
-// Specify order of IP control if necessary (option: 'deny,allow', 'allow,deny', or 'mutual-failture')
-// (how to use 'allow' and 'deny' information)
-//order: allow,deny
-
-// Indicate the IP that the server accept.
-// put: 'all', or 'xxx.xxx.' (begin of an ip finished by '.' or a complete ip),
-//      or a network and its mask (example: '123.456.789.012/24' or '123.456.789.012/255.255.255.0')
-//      or 'clear' to suppress previous parameter (use it in import file mainly)
-// Add as many IP's as you wish.
-//allow: all
-
-// Indicate the IP that the server refuse.
-// Add as many IP's as you wish, as long as you put deny: before it.
-//deny: 123.123.123.123
-//deny: 234.234.234.234
-
 // Check The clientversion set in the clientinfo ?
 check_client_version: no
 

+ 0 - 32
src/char/char.c

@@ -2066,20 +2066,6 @@ int parse_fromlogin(int fd)
 			RFIFOSKIP(fd,2);
 		break;
 
-		case 0x2721:	// gm reply
-			if (RFIFOREST(fd) < 10)
-				return 0;
-		{
-			unsigned char buf[10];
-			WBUFW(buf,0) = 0x2b0b;
-			WBUFL(buf,2) = RFIFOL(fd,2); // account
-			WBUFL(buf,6) = RFIFOL(fd,6); // GM level
-			mapif_sendall(buf,10);
-
-			RFIFOSKIP(fd,10);
-		}
-		break;
-
 		case 0x2723:	// changesex reply (modified by [Yor])
 			if (RFIFOREST(fd) < 7)
 				return 0;
@@ -2905,24 +2891,6 @@ int parse_frommap(int fd)
 			RFIFOSKIP(fd,6);
 		break;
 
-		case 0x2b0a: // request to become GM
-			if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
-				return 0;
-			if (login_fd > 0) { // don't send request if no login-server
-				WFIFOHEAD(login_fd, RFIFOW(fd,2));
-				WFIFOW(login_fd,0) = 0x2720;
-				memcpy(WFIFOP(login_fd,2), RFIFOP(fd,2), RFIFOW(fd,2)-2);
-				WFIFOSET(login_fd, RFIFOW(fd,2));
-			} else {
-				WFIFOHEAD(fd,10);
-				WFIFOW(fd,0) = 0x2b0b;
-				WFIFOL(fd,2) = RFIFOL(fd,4);
-				WFIFOL(fd,6) = 0;
-				WFIFOSET(fd,10);
-			}
-			RFIFOSKIP(fd, RFIFOW(fd,2));
-		break;
-
 		case 0x2b0c: // Map server send information to change an email of an account -> login-server
 			if (RFIFOREST(fd) < 86)
 				return 0;

+ 0 - 41
src/char_sql/char.c

@@ -1762,35 +1762,6 @@ int parse_fromlogin(int fd)
 			RFIFOSKIP(fd,2);
 		break;
 
-		// gm reply. I don't want to support this function.
-		case 0x2721:
-			if (RFIFOREST(fd) < 10)
-				return 0;
-
-/*		Note that this is the code from char-txt! Even uncommenting it will not work.
-		  {
-			int oldacc, newacc;
-			unsigned char buf[64];
-			if (RFIFOREST(fd) < 10)
-				return 0;
-			oldacc = RFIFOL(fd, 2);
-			newacc = RFIFOL(fd, 6);
-			RFIFOSKIP(fd, 10);
-			if (newacc > 0) {
-				for(i=0;i<char_num;i++){
-					if(char_dat[i].account_id==oldacc)
-						char_dat[i].account_id=newacc;
-				}
-			}
-			WBUFW(buf,0)=0x2b0b;
-			WBUFL(buf,2)=oldacc;
-			WBUFL(buf,6)=newacc;
-			mapif_sendall(buf,10);
-		  }
-*/
-			RFIFOSKIP(fd, 10);
-		break;
-
 		// changesex reply
 		case 0x2723:
 			if (RFIFOREST(fd) < 7)
@@ -2502,18 +2473,6 @@ int parse_frommap(int fd)
 			RFIFOSKIP(fd,6);
 		break;
 
-		case 0x2b0a: // request to become GM
-			if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
-				return 0;
-			/*
-			memcpy(WFIFOP(login_fd,2),RFIFOP(fd,2),RFIFOW(fd,2)-2);
-			WFIFOW(login_fd,0)=0x2720;
-			WFIFOSET(login_fd,RFIFOW(fd,2));
-			*/
-			ShowWarning("packet 0x2ba (become GM) is not supported by the Char-Server.\n");
-			RFIFOSKIP(fd, RFIFOW(fd, 2));
-		break;
-
 		case 0x2b0c: // Map server send information to change an email of an account -> login-server
 			if (RFIFOREST(fd) < 86)
 				return 0;

+ 0 - 41
src/login/admin.c

@@ -22,7 +22,6 @@ extern struct mmo_char_server server[MAX_SERVERS];
 extern uint32 auth_num;
 extern int account_id_count;
 extern char GM_account_filename[1024];
-extern char login_log_unknown_packets_filename[1024];
 
 int charif_sendallwos(int sfd, unsigned char *buf, unsigned int len);
 int search_account_index(char* account_name);
@@ -894,46 +893,6 @@ int parse_admin(int fd)
 			break;
 
 		default:
-			{
-				FILE *logfp;
-				char tmpstr[24];
-				time_t raw_time;
-				logfp = fopen(login_log_unknown_packets_filename, "a");
-				if (logfp) {
-					time(&raw_time);
-					strftime(tmpstr, 23, login_config.date_format, localtime(&raw_time));
-					fprintf(logfp, "%s: receiving of an unknown packet -> disconnection\n", tmpstr);
-					fprintf(logfp, "parse_admin: connection #%d (ip: %s), packet: 0x%x (with being read: %lu).\n", fd, ip, command, (unsigned long)RFIFOREST(fd));
-					fprintf(logfp, "Detail (in hex):\n");
-					fprintf(logfp, "---- 00-01-02-03-04-05-06-07  08-09-0A-0B-0C-0D-0E-0F\n");
-					memset(tmpstr, '\0', sizeof(tmpstr));
-					for(i = 0; i < RFIFOREST(fd); i++) {
-						if ((i & 15) == 0)
-							fprintf(logfp, "%04X ",i);
-						fprintf(logfp, "%02x ", RFIFOB(fd,i));
-						if (RFIFOB(fd,i) > 0x1f)
-							tmpstr[i % 16] = RFIFOB(fd,i);
-						else
-							tmpstr[i % 16] = '.';
-						if ((i - 7) % 16 == 0) // -8 + 1
-							fprintf(logfp, " ");
-						else if ((i + 1) % 16 == 0) {
-							fprintf(logfp, " %s\n", tmpstr);
-							memset(tmpstr, '\0', sizeof(tmpstr));
-						}
-					}
-					if (i % 16 != 0) {
-						for(j = i; j % 16 != 0; j++) {
-							fprintf(logfp, "   ");
-							if ((j - 7) % 16 == 0) // -8 + 1
-								fprintf(logfp, " ");
-						}
-						fprintf(logfp, " %s\n", tmpstr);
-					}
-					fprintf(logfp, "\n");
-					fclose(logfp);
-				}
-			}
 			ShowStatus("'ladmin': End of connection, unknown packet (ip: %s)\n", ip);
 			set_eof(fd);
 			return 0;

+ 77 - 473
src/login/login.c

@@ -35,53 +35,26 @@ struct s_subnet {
 
 int subnet_count = 0;
 
+// GM account management
 struct gm_account* gm_account_db = NULL;
 unsigned int GM_num = 0; // number of gm accounts
-unsigned int GM_max = 0;
+char GM_account_filename[1024] = "conf/GM_account.txt";
+long creation_time_GM_account_file; // tracks the last-changed timestamp of the gm accounts file
+int gm_account_filename_check_timer = 15; // Timer to check if GM_account file has been changed and reload GM account automaticaly (in seconds; default: 15)
 
 //Account registration flood protection [Kevin]
 int allowed_regs = 1;
 int time_allowed = 10; //in seconds
-unsigned int new_reg_tick = 0;
-int num_regs = 0;
 
-int account_id_count = START_ACCOUNT_NUM;
 
+// data handling (TXT)
 char account_filename[1024] = "save/account.txt";
-char GM_account_filename[1024] = "conf/GM_account.txt";
-FILE *log_fp = NULL;
-char login_log_unknown_packets_filename[1024] = "log/login_unknown_packets.log";
-int save_unknown_packets = 0;
-long creation_time_GM_account_file; // tracks the last-changed timestamp of the gm accounts file
-int gm_account_filename_check_timer = 15; // Timer to check if GM_account file has been changed and reload GM account automaticaly (in seconds; default: 15)
-
-
-enum {
-	ACO_DENY_ALLOW = 0,
-	ACO_ALLOW_DENY,
-	ACO_MUTUAL_FAILTURE,
-	ACO_STRSIZE = 128,
-};
-
-int access_order = ACO_DENY_ALLOW;
-int access_allownum = 0;
-int access_denynum = 0;
-char *access_allow = NULL;
-char *access_deny = NULL;
-
-int access_ladmin_allownum = 0;
-char *access_ladmin_allow = NULL;
-
-int start_limited_time = -1; // Starting additional sec from now for the limited time at creation of accounts (-1: unlimited time, 0 or more: additional sec from now)
-
-struct login_session_data {
-	uint16 md5keylen;
-	char md5key[20];
-};
 
 // account database
 struct auth_data* auth_dat = NULL;
-uint32 auth_num = 0, auth_max = 0;
+unsigned int auth_num = 0, auth_max = 0;
+
+int account_id_count = START_ACCOUNT_NUM;
 
 // define the number of times that some players must authentify them before to save account file.
 // it's just about normal authentication. If an account is created or modified, save is immediatly done.
@@ -92,13 +65,23 @@ uint32 auth_num = 0, auth_max = 0;
 #define AUTH_SAVE_FILE_DIVIDER 50
 int auth_before_save_file = 0; // Counter. First save when 1st char-server do connection.
 
+
+// ladmin configuration
 bool admin_state = false;
 char admin_pass[24] = "";
-char gm_pass[64] = "";
-int level_new_gm = 60;
+uint32 admin_allowed_ip = 0;
 
 int parse_admin(int fd);
 
+
+//-----------------------------------------------------
+// Session data structure
+//-----------------------------------------------------
+struct login_session_data {
+	uint16 md5keylen;
+	char md5key[20];
+};
+
 //-----------------------------------------------------
 // Auth database
 //-----------------------------------------------------
@@ -169,7 +152,7 @@ void remove_online_user(int account_id)
 static int waiting_disconnect_timer(int tid, unsigned int tick, int id, int data)
 {
 	struct online_login_data* p = (struct online_login_data*)idb_get(online_db, id);
-	if( p != NULL && p->waiting_disconnect == id )
+	if( p != NULL && p->waiting_disconnect == tid && p->account_id == id )
 	{
 		p->waiting_disconnect = -1;
 		remove_online_user(id);
@@ -216,6 +199,7 @@ int isGM(int account_id)
 //----------------------------------------------------------------------
 void addGM(int account_id, int level)
 {
+	static unsigned int GM_max = 0;
 	unsigned int i;
 
 	ARR_FIND( 0, auth_num, i, auth_dat[i].account_id == account_id );
@@ -311,118 +295,6 @@ int read_gm_account(void)
 	return 0;
 }
 
-//--------------------------------------------------------------
-// Test of the IP mask
-// (ip: IP to be tested, str: mask x.x.x.x/# or x.x.x.x/y.y.y.y)
-//--------------------------------------------------------------
-int check_ipmask(uint32 ip, const unsigned char *str)
-{
-	unsigned int i = 0, m = 0;
-	uint32 ip2, mask = 0;
-	uint32 a0, a1, a2, a3;
-	uint8* p = (uint8 *)&ip2, *p2 = (uint8 *)&mask;
-
-
-	// scan ip address
-	if (sscanf((const char*)str, "%u.%u.%u.%u/%n", &a0, &a1, &a2, &a3, &i) != 4 || i == 0)
-		return 0;
-	p[0] = (uint8)a3; p[1] = (uint8)a2; p[2] = (uint8)a1; p[3] = (uint8)a0;
-
-	// scan mask
-	if (sscanf((const char*)str+i, "%u.%u.%u.%u", &a0, &a1, &a2, &a3) == 4) {
-		p2[0] = (uint8)a3; p2[1] = (uint8)a2; p2[2] = (uint8)a1; p2[3] = (uint8)a0;
-	} else if (sscanf((const char*)(str+i), "%u", &m) == 1 && m <= 32) {
-		for(i = 32 - m; i < 32; i++)
-			mask |= (1 << i);
-	} else {
-		ShowError("check_ipmask: invalid mask [%s].\n", str);
-		return 0;
-	}
-
-	return ((ip & mask) == (ip2 & mask));
-}
-
-//---------------------
-// Access control by IP
-//---------------------
-int check_ip(uint32 ip)
-{
-	int i;
-	char buf[20];
-	char * access_ip;
-	enum { ACF_DEF, ACF_ALLOW, ACF_DENY } flag = ACF_DEF;
-
-	if (access_allownum == 0 && access_denynum == 0)
-		return 1; // When there is no restriction, all IP are authorised.
-
-//	+   012.345.: front match form, or
-//	    all: all IP are matched, or
-//	    012.345.678.901/24: network form (mask with # of bits), or
-//	    012.345.678.901/255.255.255.0: network form (mask with ip mask)
-//	+   Note about the DNS resolution (like www.ne.jp, etc.):
-//	    There is no guarantee to have an answer.
-//	    If we have an answer, there is no guarantee to have a 100% correct value.
-//	    And, the waiting time (to check) can be long (over 1 minute to a timeout). That can block the software.
-//	    So, DNS notation isn't authorised for ip checking.
-	sprintf(buf, "%u.%u.%u.%u.", CONVIP(ip));
-
-	for(i = 0; i < access_allownum; i++) {
-		access_ip = access_allow + i * ACO_STRSIZE;
-		if (memcmp(access_ip, buf, strlen(access_ip)) == 0 || check_ipmask(ip, (unsigned char*)access_ip)) {
-			if(access_order == ACO_ALLOW_DENY)
-				return 1; // With 'allow, deny' (deny if not allow), allow has priority
-			flag = ACF_ALLOW;
-			break;
-		}
-	}
-
-	for(i = 0; i < access_denynum; i++) {
-		access_ip = access_deny + i * ACO_STRSIZE;
-		if (memcmp(access_ip, buf, strlen(access_ip)) == 0 || check_ipmask(ip, (unsigned char*)access_ip)) {
-			//flag = ACF_DENY; // not necessary to define flag
-			return 0; // At this point, if it's 'deny', we refuse connection.
-		}
-	}
-
-	return (flag == ACF_ALLOW || access_order == ACO_DENY_ALLOW) ? 1:0;
-		// With 'mutual-failture', only 'allow' and non 'deny' IP are authorised.
-		//   A non 'allow' (even non 'deny') IP is not authorised. It's like: if allowed and not denied, it's authorised.
-		//   So, it's disapproval if you have no description at the time of 'mutual-failture'.
-		// With 'deny,allow' (allow if not deny), because here it's not deny, we authorise.
-}
-
-//--------------------------------
-// Access control by IP for ladmin
-//--------------------------------
-int check_ladminip(uint32 ip)
-{
-	int i;
-	char buf[20];
-	char * access_ip;
-
-	if (access_ladmin_allownum == 0)
-		return 1; // When there is no restriction, all IP are authorised.
-
-//	+   012.345.: front match form, or
-//	    all: all IP are matched, or
-//	    012.345.678.901/24: network form (mask with # of bits), or
-//	    012.345.678.901/255.255.255.0: network form (mask with ip mask)
-//	+   Note about the DNS resolution (like www.ne.jp, etc.):
-//	    There is no guarantee to have an answer.
-//	    If we have an answer, there is no guarantee to have a 100% correct value.
-//	    And, the waiting time (to check) can be long (over 1 minute to a timeout). That can block the software.
-//	    So, DNS notation isn't authorised for ip checking.
-	sprintf(buf, "%u.%u.%u.%u.", CONVIP(ip));
-
-	for(i = 0; i < access_ladmin_allownum; i++) {
-		access_ip = access_ladmin_allow + i * ACO_STRSIZE;
-		if (memcmp(access_ip, buf, strlen(access_ip)) == 0 || check_ipmask(ip, (unsigned char*)access_ip)) {
-			return 1;
-		}
-	}
-
-	return 0;
-}
 
 //-----------------------------------------------
 // Search an account id
@@ -947,6 +819,7 @@ int check_GM_file(int tid, unsigned int tick, int id, int data)
 bool check_encrypted(const char* str1, const char* str2, const char* passwd)
 {
 	char md5str[64], md5bin[32];
+
 	snprintf(md5str, sizeof(md5str), "%s%s", str1, str2);
 	md5str[sizeof(md5str)-1] = '\0';
 	MD5_String2binary(md5str, md5bin);
@@ -977,8 +850,7 @@ bool check_password(struct login_session_data* ld, int passwdenc, const char* pa
 //-------------------------------------
 int mmo_auth_new(struct mmo_account* account, char sex, char* email)
 {
-	time_t timestamp, timestamp_temp;
-	struct tm *tmtime;
+	time_t connect_until = 0;
 	int i = auth_num;
 
 	if (auth_num >= auth_max) {
@@ -988,6 +860,7 @@ int mmo_auth_new(struct mmo_account* account, char sex, char* email)
 
 	memset(&auth_dat[i], '\0', sizeof(struct auth_data));
 
+	// find a suitable non-gm account id
 	while (isGM(account_id_count) > 0)
 		account_id_count++;
 
@@ -1004,19 +877,9 @@ int mmo_auth_new(struct mmo_account* account, char sex, char* email)
 	safestrncpy(auth_dat[i].email, e_mail_check(email) ? email : "a@a.com", sizeof(auth_dat[i].email));
 	safestrncpy(auth_dat[i].error_message, "-", sizeof(auth_dat[i].error_message));
 	auth_dat[i].ban_until_time = 0;
-	if (start_limited_time < 0)
-		auth_dat[i].connect_until_time = 0; // unlimited
-	else { // limited time
-		timestamp = time(NULL) + start_limited_time;
-		// double conversion to be sure that it is possible
-		tmtime = localtime(&timestamp);
-		timestamp_temp = mktime(tmtime);
-		if (timestamp_temp != -1 && (timestamp_temp + 3600) >= timestamp) // check possible value and overflow (and avoid summer/winter hour)
-			auth_dat[i].connect_until_time = timestamp_temp;
-		else
-			auth_dat[i].connect_until_time = 0; // unlimited
-	}
-
+	if( login_config.start_limited_time != -1 )
+		connect_until = time(NULL) + login_config.start_limited_time;
+	auth_dat[i].connect_until_time = connect_until;
 	strncpy(auth_dat[i].last_ip, "-", 16);
 	strncpy(auth_dat[i].memo, "-", 255);
 	auth_dat[i].account_reg2_num = 0;
@@ -1031,6 +894,9 @@ int mmo_auth_new(struct mmo_account* account, char sex, char* email)
 //-----------------------------------------------------
 int mmo_auth(struct mmo_account* account, int fd)
 {
+	static int num_regs = 0; // registration counter
+	static unsigned int new_reg_tick = gettick();
+
 	unsigned int i;
 	time_t raw_time;
 	char tmpstr[256];
@@ -1104,7 +970,7 @@ int mmo_auth(struct mmo_account* account, int fd)
 		{
 			int new_id = mmo_auth_new(account, account->userid[len-1], "a@a.com");
 			unsigned int tick = gettick();
-			ShowNotice("Account creation (account %s, id: %d, pass: %s, sex: %c, connection with _F/_M, ip: %s)\n", account->userid, new_id, account->passwd, account->userid[len-1], ip);
+			ShowNotice("Account creation (account %s, id: %d, pass: %s, sex: %c, connection with _M/_F, ip: %s)\n", account->userid, new_id, account->passwd, account->userid[len-1], ip);
 			auth_before_save_file = 0; // Creation of an account -> save accounts file immediatly
 			
 			if( DIFF_TICK(tick, new_reg_tick) > 0 )
@@ -1214,7 +1080,7 @@ static int online_db_setoffline(DBKey key, void* data, va_list ap)
 //--------------------------------
 int parse_fromchar(int fd)
 {
-	uint32 i;
+	unsigned int i;
 	int j, id;
 	uint32 ipl;
 	char ip[16];
@@ -1328,9 +1194,18 @@ int parse_fromchar(int fd)
 		case 0x2714:
 			if( RFIFOREST(fd) < 6 )
 				return 0;
-			//printf("parse_fromchar: Receiving of the users number of the server '%s': %d\n", server[id].name, RFIFOL(fd,2));
-			server[id].users = RFIFOL(fd,2);
+		{
+			int users = RFIFOL(fd,2);
 			RFIFOSKIP(fd,6);
+
+			// how many users on world? (update)
+			if( server[id].users != users )
+			{
+				ShowStatus("set users %s : %d\n", server[id].name, users);
+
+				server[id].users = users;
+			}
+		}
 		break;
 
 		case 0x2715: // request from char server to change e-email from default "a@a.com"
@@ -1365,7 +1240,7 @@ int parse_fromchar(int fd)
 				return 0;
 		{
 			uint32 connect_until_time = 0;
-			char* email = "";
+			char email[40] = "";
 
 			int account_id = RFIFOL(fd,2);
 			RFIFOSKIP(fd,6);
@@ -1375,7 +1250,7 @@ int parse_fromchar(int fd)
 				ShowNotice("Char-server '%s': e-mail of the account %d NOT found (ip: %s).\n", server[id].name, RFIFOL(fd,2), ip);
 			else
 			{
-				email = auth_dat[i].email;
+				safestrncpy(email, auth_dat[i].email, sizeof(email));
 				connect_until_time = (uint32)auth_dat[i].connect_until_time;
 			}
 
@@ -1398,53 +1273,6 @@ int parse_fromchar(int fd)
 			WFIFOSET(fd,2);
 		break;
 
-		case 0x2720: // Request to become a GM
-			if( RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2) )
-				return 0;
-		{
-			int level = 0;
-			FILE *fp;
-
-			char pass[60];
-			int acc = RFIFOL(fd,4);
-			safestrncpy(pass, (char*)RFIFOP(fd,8), sizeof(pass));
-			RFIFOSKIP(fd, RFIFOW(fd,2));
-
-			if( strcmp(pass, gm_pass) != 0 ) // password check
-				ShowError("Char-server '%s': Error of GM change (account: %d, invalid password, ip: %s).\n", server[id].name, acc, ip);
-			else
-			if( isGM(acc) > 0 ) // only non-GM can become GM
-				ShowError("Char-server '%s': Error of GM change (account: %d (already GM), correct password, ip: %s).\n", server[id].name, acc, ip);
-			else
-			if( level_new_gm == 0 ) // if we autorise creation
-				ShowError("Char-server '%s': Error of GM change (account: %d, correct password, but GM creation is disable (level_new_gm = 0), ip: %s).\n", server[id].name, acc, ip);
-			else
-			if( (fp = fopen(GM_account_filename, "a")) == NULL ) // if we can open the file to add the new GM
-				ShowError("Char-server '%s': Error of GM change (account: %d, correct password, unable to add a GM account in GM accounts file, ip: %s).\n", server[id].name, acc, ip);
-			else
-			{
-				char tmpstr[24];
-				time_t raw_time;
-				time(&raw_time);
-				strftime(tmpstr, 23, login_config.date_format, localtime(&raw_time));
-				fprintf(fp, "\n// %s: @GM command on account %d\n%d %d\n", tmpstr, acc, acc, level_new_gm);
-				fclose(fp);
-				level = level_new_gm;
-				read_gm_account();
-				send_GM_accounts(-1);
-
-				ShowNotice("Char-server '%s': GM Change of the account %d: level 0 -> %d (ip: %s).\n", server[id].name, acc, level_new_gm, ip);
-			}
-
-			// announce gm level update result
-			WFIFOHEAD(fd,10);
-			WFIFOW(fd,0) = 0x2721;
-			WFIFOL(fd,2) = acc;
-			WFIFOL(fd,6) = level; // 0:failed, >0:success
-			WFIFOSET(fd,10);
-		}
-		break;
-
 		// Map server send information to change an email of an account via char-server
 		case 0x2722:	// 0x2722 <account_id>.L <actual_e-mail>.40B <new_e-mail>.40B
 			if (RFIFOREST(fd) < 86)
@@ -1459,9 +1287,9 @@ int parse_fromchar(int fd)
 
 			if( e_mail_check(actual_email) == 0 )
 				ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual email is invalid (account: %d, ip: %s)\n", server[id].name, account_id, ip);
-			else if (e_mail_check(new_email) == 0)
+			else if( e_mail_check(new_email) == 0 )
 				ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a invalid new e-mail (account: %d, ip: %s)\n", server[id].name, account_id, ip);
-			else if (strcmpi(new_email, "a@a.com") == 0)
+			else if( strcmpi(new_email, "a@a.com") == 0 )
 				ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a default e-mail (account: %d, ip: %s)\n", server[id].name, account_id, ip);
 			else {
 				ARR_FIND( 0, auth_num, i, auth_dat[i].account_id == account_id );
@@ -1737,8 +1565,8 @@ int parse_fromchar(int fd)
 			{
 				if( auth_dat[i].account_reg2[j].str[0] != '\0' )
 				{
-					off+= sprintf((char*)WFIFOP(fd,off), "%s", auth_dat[i].account_reg2[j].str)+1; //We add 1 to consider the '\0' in place.
-					off+= sprintf((char*)WFIFOP(fd,off), "%s", auth_dat[i].account_reg2[j].value)+1;
+					off += sprintf((char*)WFIFOP(fd,off), "%s", auth_dat[i].account_reg2[j].str)+1; //We add 1 to consider the '\0' in place.
+					off += sprintf((char*)WFIFOP(fd,off), "%s", auth_dat[i].account_reg2[j].value)+1;
 				}
 			}
 
@@ -1765,50 +1593,9 @@ int parse_fromchar(int fd)
 		break;
 
 		default:
-		{
-			FILE* logfp;
-			char tmpstr[24];
-			time_t raw_time;
-			logfp = fopen(login_log_unknown_packets_filename, "a");
-			if (logfp) {
-				time(&raw_time);
-				strftime(tmpstr, 23, login_config.date_format, localtime(&raw_time));
-				fprintf(logfp, "%s: receiving of an unknown packet -> disconnection\n", tmpstr);
-				fprintf(logfp, "parse_fromchar: connection #%d (ip: %s), packet: 0x%x (with being read: %lu).\n", fd, ip, command, (unsigned long)RFIFOREST(fd));
-				fprintf(logfp, "Detail (in hex):\n");
-				fprintf(logfp, "---- 00-01-02-03-04-05-06-07  08-09-0A-0B-0C-0D-0E-0F\n");
-				memset(tmpstr, '\0', sizeof(tmpstr));
-				for(i = 0; i < RFIFOREST(fd); i++) {
-					if ((i & 15) == 0)
-						fprintf(logfp, "%04X ",i);
-					fprintf(logfp, "%02x ", RFIFOB(fd,i));
-					if (RFIFOB(fd,i) > 0x1f)
-						tmpstr[i % 16] = RFIFOB(fd,i);
-					else
-						tmpstr[i % 16] = '.';
-					if ((i - 7) % 16 == 0) // -8 + 1
-						fprintf(logfp, " ");
-					else if ((i + 1) % 16 == 0) {
-						fprintf(logfp, " %s\n", tmpstr);
-						memset(tmpstr, '\0', sizeof(tmpstr));
-					}
-				}
-				if (i % 16 != 0) {
-					for(j = i; j % 16 != 0; j++) {
-						fprintf(logfp, "   ");
-						if ((j - 7) % 16 == 0) // -8 + 1
-							fprintf(logfp, " ");
-					}
-					fprintf(logfp, " %s\n", tmpstr);
-				}
-				fprintf(logfp, "\n");
-				fclose(logfp);
-			}
-
 			ShowError("parse_fromchar: Unknown packet 0x%x from a char-server! Disconnecting!\n", command);
 			set_eof(fd);
 			return 0;
-		}
 		} // switch
 	} // while
 
@@ -1869,8 +1656,8 @@ void login_auth_ok(struct mmo_account* account, int fd)
 		{// account is already marked as online!
 			if( data->char_server > -1 )
 			{// Request char servers to kick this account out. [Skotlex]
-				uint8 buf[8];
-				ShowNotice("User '%s' is already online - Rejected.\n", auth_dat[i].userid);
+				uint8 buf[6];
+				ShowNotice("User '%s' is already online - Rejected.\n", account->userid);
 				WBUFW(buf,0) = 0x2734;
 				WBUFL(buf,2) = account->account_id;
 				charif_sendallwos(-1, buf, 6);
@@ -1968,10 +1755,9 @@ void login_auth_failed(struct mmo_account* account, int fd, int result)
 // Default packet parsing (normal players or administation/char-server connection requests)
 //----------------------------------------------------------------------------------------
 int parse_login(int fd)
-{	
+{
 	struct mmo_account account;
-	int result, j;
-	unsigned int i;
+	int result;
 	uint32 ipl;
 	char ip[16];
 
@@ -2010,19 +1796,6 @@ int parse_login(int fd)
 		{
 			size_t packet_len = RFIFOREST(fd); // assume no other packet was sent
 
-			// Perform ip-ban check
-			if (!check_ip(ipl))
-			{
-				ShowStatus("Connection refused: IP isn't authorised (deny/allow, ip: %s).\n", ip);
-				WFIFOHEAD(fd,23);
-				WFIFOW(fd,0) = 0x6a;
-				WFIFOB(fd,2) = 3; // 3 = Rejected from Server
-				WFIFOSET(fd,23);
-				RFIFOSKIP(fd,packet_len);
-				set_eof(fd);
-				break;
-			}
-
 			if( (command == 0x0064 && packet_len < 55)
 			||  (command == 0x01dd && packet_len < 47)
 			||  (command == 0x0277 && packet_len < 84)
@@ -2038,17 +1811,18 @@ int parse_login(int fd)
 			account.version = RFIFOL(fd,2);
 			safestrncpy(account.userid, (char*)RFIFOP(fd,6), NAME_LENGTH); remove_control_chars(account.userid);
 			if (command != 0x01dd) {
-				ShowStatus("Request for connection (non encryption mode) of %s (ip: %s).\n", account.userid, ip);
+				ShowStatus("Request for connection of %s (ip: %s).\n", account.userid, ip);
 				safestrncpy(account.passwd, (char*)RFIFOP(fd,30), NAME_LENGTH); remove_control_chars(account.passwd);
+				account.passwdenc = 0;
 			} else {
 				ShowStatus("Request for connection (encryption mode) of %s (ip: %s).\n", account.userid, ip);
 				memcpy(account.passwd, RFIFOP(fd,30), 16); account.passwd[16] = '\0'; // raw binary data here!
+				account.passwdenc = PASSWORDENC;
 			}
 			RFIFOSKIP(fd,packet_len);
 
-			account.passwdenc = (command == 0x01dd) ? PASSWORDENC : 0;
-
 			result = mmo_auth(&account, fd);
+
 			if( result == -1 )
 				login_auth_ok(&account, fd);
 			else
@@ -2061,6 +1835,7 @@ int parse_login(int fd)
 			RFIFOSKIP(fd,2);
 		{
 			struct login_session_data* ld;
+			unsigned int i;
 			if( session[fd]->session_data )
 			{
 				ShowWarning("login: abnormal request of MD5 key (already opened session).\n");
@@ -2165,7 +1940,7 @@ int parse_login(int fd)
 				return 0;
 			WFIFOW(fd,0) = 0x7919;
 			WFIFOB(fd,2) = 1;
-			if (!check_ladminip(session[fd]->client_addr)) {
+			if( session[fd]->client_addr != admin_allowed_ip ) {
 				ShowNotice("'ladmin'-login: Connection in administration mode refused: IP isn't authorised (ladmin_allow, ip: %s).\n", ip);
 			} else {
 				struct login_session_data *ld = (struct login_session_data*)session[fd]->session_data;
@@ -2217,46 +1992,6 @@ int parse_login(int fd)
 		break;
 
 		default:
-			if (save_unknown_packets) {
-				FILE *logfp;
-				char tmpstr[24];
-				time_t raw_time;
-				logfp = fopen(login_log_unknown_packets_filename, "a");
-				if (logfp) {
-					time(&raw_time);
-					strftime(tmpstr, 23, login_config.date_format, localtime(&raw_time));
-					fprintf(logfp, "%s: receiving of an unknown packet -> disconnection\n", tmpstr);
-					fprintf(logfp, "parse_login: connection #%d (ip: %s), packet: 0x%x (with being read: %lu).\n", fd, ip, command, (unsigned long)RFIFOREST(fd));
-					fprintf(logfp, "Detail (in hex):\n");
-					fprintf(logfp, "---- 00-01-02-03-04-05-06-07  08-09-0A-0B-0C-0D-0E-0F\n");
-					memset(tmpstr, '\0', sizeof(tmpstr));
-					for(i = 0; i < RFIFOREST(fd); i++) {
-						if ((i & 15) == 0)
-							fprintf(logfp, "%04X ",i);
-						fprintf(logfp, "%02x ", RFIFOB(fd,i));
-						if (RFIFOB(fd,i) > 0x1f)
-							tmpstr[i % 16] = RFIFOB(fd,i);
-						else
-							tmpstr[i % 16] = '.';
-						if ((i - 7) % 16 == 0) // -8 + 1
-							fprintf(logfp, " ");
-						else if ((i + 1) % 16 == 0) {
-							fprintf(logfp, " %s\n", tmpstr);
-							memset(tmpstr, '\0', sizeof(tmpstr));
-						}
-					}
-					if (i % 16 != 0) {
-						for(j = i; j % 16 != 0; j++) {
-							fprintf(logfp, "   ");
-							if ((j - 7) % 16 == 0) // -8 + 1
-								fprintf(logfp, " ");
-						}
-						fprintf(logfp, " %s\n", tmpstr);
-					}
-					fprintf(logfp, "\n");
-					fclose(logfp);
-				}
-			}
 			ShowNotice("Abnormal end of connection (ip: %s): Unknown packet 0x%x\n", ip, command);
 			set_eof(fd);
 			return 0;
@@ -2393,43 +2128,6 @@ int login_config_read(const char* cfgName)
 			ShowInfo("Console Silent Setting: %d\n", atoi(w2));
 			msg_silent = atoi(w2);
 		}
-		else if (strcmpi(w1, "admin_state") == 0) {
-			admin_state = (bool)config_switch(w2);
-		} else if (strcmpi(w1, "admin_pass") == 0) {
-			memset(admin_pass, 0, sizeof(admin_pass));
-			strncpy(admin_pass, w2, sizeof(admin_pass));
-			admin_pass[sizeof(admin_pass)-1] = '\0';
-		} else if (strcmpi(w1, "ladminallowip") == 0) {
-			if (strcmpi(w2, "clear") == 0) {
-				if (access_ladmin_allow)
-					aFree(access_ladmin_allow);
-				access_ladmin_allow = NULL;
-				access_ladmin_allownum = 0;
-			} else {
-				if (strcmpi(w2, "all") == 0) {
-					// reset all previous values
-					if (access_ladmin_allow)
-						aFree(access_ladmin_allow);
-					// set to all
-					access_ladmin_allow = (char*)aCalloc(ACO_STRSIZE, sizeof(char));
-					access_ladmin_allownum = 1;
-					access_ladmin_allow[0] = '\0';
-				} else if (w2[0] && !(access_ladmin_allownum == 1 && access_ladmin_allow[0] == '\0')) { // don't add IP if already 'all'
-					if (access_ladmin_allow)
-						access_ladmin_allow = (char*)aRealloc(access_ladmin_allow, (access_ladmin_allownum+1) * ACO_STRSIZE);
-					else
-						access_ladmin_allow = (char*)aCalloc(ACO_STRSIZE, sizeof(char));
-					strncpy(access_ladmin_allow + (access_ladmin_allownum++) * ACO_STRSIZE, w2, ACO_STRSIZE);
-					access_ladmin_allow[access_ladmin_allownum * ACO_STRSIZE - 1] = '\0';
-				}
-			}
-		} else if (strcmpi(w1, "gm_pass") == 0) {
-			memset(gm_pass, 0, sizeof(gm_pass));
-			strncpy(gm_pass, w2, sizeof(gm_pass));
-			gm_pass[sizeof(gm_pass)-1] = '\0';
-		} else if (strcmpi(w1, "level_new_gm") == 0) {
-			level_new_gm = atoi(w2);
-		}
 		else if( !strcmpi(w1, "bind_ip") ) {
 			char ip_str[16];
 			login_config.login_ip = host2ip(w2);
@@ -2440,6 +2138,17 @@ int login_config_read(const char* cfgName)
 			login_config.login_port = (uint16)atoi(w2);
 			ShowStatus("set login_port : %s\n",w2);
 		}
+		else if(!strcmpi(w1, "log_login"))
+			login_config.log_login = (bool)config_switch(w2);
+
+		else if (strcmpi(w1, "admin_state") == 0) {
+			admin_state = (bool)config_switch(w2);
+		} else if (strcmpi(w1, "admin_pass") == 0) {
+			memset(admin_pass, 0, sizeof(admin_pass));
+			strncpy(admin_pass, w2, sizeof(admin_pass));
+			admin_pass[sizeof(admin_pass)-1] = '\0';
+		} else if (strcmpi(w1, "admin_allowed_ip") == 0)
+			admin_allowed_ip = host2ip(w2);
 		else if (strcmpi(w1, "account_filename") == 0) {
 			memset(account_filename, 0, sizeof(account_filename));
 			strncpy(account_filename, w2, sizeof(account_filename));
@@ -2448,78 +2157,14 @@ int login_config_read(const char* cfgName)
 			memset(GM_account_filename, 0, sizeof(GM_account_filename));
 			strncpy(GM_account_filename, w2, sizeof(GM_account_filename));
 			GM_account_filename[sizeof(GM_account_filename)-1] = '\0';
-		} else if (strcmpi(w1, "gm_account_filename_check_timer") == 0) {
-			gm_account_filename_check_timer = atoi(w2);
-		} else if (strcmpi(w1, "log_login") == 0) {
-			login_config.log_login = (bool)config_switch(w2);
-		} else if (strcmpi(w1, "login_log_unknown_packets_filename") == 0) {
-			memset(login_log_unknown_packets_filename, 0, sizeof(login_log_unknown_packets_filename));
-			strncpy(login_log_unknown_packets_filename, w2, sizeof(login_log_unknown_packets_filename));
-			login_log_unknown_packets_filename[sizeof(login_log_unknown_packets_filename)-1] = '\0';
-		} else if (strcmpi(w1, "save_unknown_packets") == 0) {
-			save_unknown_packets = config_switch(w2);
-		} else if (strcmpi(w1, "start_limited_time") == 0) {
-			start_limited_time = atoi(w2);
-		} else if (strcmpi(w1, "order") == 0) {
-			access_order = atoi(w2);
-			if (strcmpi(w2, "deny,allow") == 0 ||
-			    strcmpi(w2, "deny, allow") == 0) access_order = ACO_DENY_ALLOW;
-			if (strcmpi(w2, "allow,deny") == 0 ||
-			    strcmpi(w2, "allow, deny") == 0) access_order = ACO_ALLOW_DENY;
-			if (strcmpi(w2, "mutual-failture") == 0 ||
-			    strcmpi(w2, "mutual-failure") == 0) access_order = ACO_MUTUAL_FAILTURE;
-		} else if (strcmpi(w1, "allow") == 0) {
-			if (strcmpi(w2, "clear") == 0) {
-				if (access_allow)
-					aFree(access_allow);
-				access_allow = NULL;
-				access_allownum = 0;
-			} else {
-				if (strcmpi(w2, "all") == 0) {
-					// reset all previous values
-					if (access_allow)
-						aFree(access_allow);
-					// set to all
-					access_allow = (char*)aCalloc(ACO_STRSIZE, sizeof(char));
-					access_allownum = 1;
-					access_allow[0] = '\0';
-				} else if (w2[0] && !(access_allownum == 1 && access_allow[0] == '\0')) { // don't add IP if already 'all'
-					if (access_allow)
-						access_allow = (char*)aRealloc(access_allow, (access_allownum+1) * ACO_STRSIZE);
-					else
-						access_allow = (char*)aCalloc(ACO_STRSIZE, sizeof(char));
-					strncpy(access_allow + (access_allownum++) * ACO_STRSIZE, w2, ACO_STRSIZE);
-					access_allow[access_allownum * ACO_STRSIZE - 1] = '\0';
-				}
-			}
-		} else if (strcmpi(w1, "deny") == 0) {
-			if (strcmpi(w2, "clear") == 0) {
-				if (access_deny)
-					aFree(access_deny);
-				access_deny = NULL;
-				access_denynum = 0;
-			} else {
-				if (strcmpi(w2, "all") == 0) {
-					// reset all previous values
-					if (access_deny)
-						aFree(access_deny);
-					// set to all
-					access_deny = (char*)aCalloc(ACO_STRSIZE, sizeof(char));
-					access_denynum = 1;
-					access_deny[0] = '\0';
-				} else if (w2[0] && !(access_denynum == 1 && access_deny[0] == '\0')) { // don't add IP if already 'all'
-					if (access_deny)
-						access_deny = (char*)aRealloc(access_deny, (access_denynum+1) * ACO_STRSIZE);
-					else
-						access_deny = (char*)aCalloc(ACO_STRSIZE, sizeof(char));
-					strncpy(access_deny + (access_denynum++) * ACO_STRSIZE, w2, ACO_STRSIZE);
-					access_deny[access_denynum * ACO_STRSIZE - 1] = '\0';
-				}
-			}
 		}
+		else if (strcmpi(w1, "gm_account_filename_check_timer") == 0)
+			gm_account_filename_check_timer = atoi(w2);
 
 		else if(!strcmpi(w1, "new_account"))
 			login_config.new_account_flag = (bool)config_switch(w2);
+		else if(!strcmpi(w1, "start_limited_time"))
+			login_config.start_limited_time = atoi(w2);
 		else if(!strcmpi(w1, "check_client_version"))
 			login_config.check_client_version = (bool)config_switch(w2);
 		else if(!strcmpi(w1, "client_version_to_connect"))
@@ -2568,19 +2213,6 @@ void display_conf_warnings(void)
 		}
 	}
 
-	if (gm_pass[0] == '\0') {
-		ShowWarning("'To GM become' password is void (gm_pass).\n");
-		ShowWarning("  We highly recommend that you set one password.\n");
-	} else if (strcmp(gm_pass, "gm") == 0) {
-		ShowWarning("You are using the default GM password (gm_pass).\n");
-		ShowWarning("  We highly recommend that you change it.\n");
-	}
-
-	if (level_new_gm < 0 || level_new_gm > 99) {
-		ShowWarning("Invalid value for level_new_gm parameter -> setting to 60 (default).\n");
-		level_new_gm = 60;
-	}
-
 	if (gm_account_filename_check_timer < 0) {
 		ShowWarning("Invalid value for gm_account_filename_check_timer parameter. Setting to 15 sec (default).\n");
 		gm_account_filename_check_timer = 15;
@@ -2597,30 +2229,10 @@ void display_conf_warnings(void)
 		login_config.min_level_to_connect = 99;
 	}
 
-	if (start_limited_time < -1) { // -1: create unlimited account, 0 or more: additionnal sec from now to create limited time
+	if (login_config.start_limited_time < -1) { // -1: create unlimited account, 0 or more: additionnal sec from now to create limited time
 		ShowWarning("Invalid value for start_limited_time parameter\n");
 		ShowWarning("  -> setting to -1 (new accounts are created with unlimited time).\n");
-		start_limited_time = -1;
-	}
-
-	if (access_order == ACO_DENY_ALLOW) {
-		if (access_denynum == 1 && access_deny[0] == '\0') {
-			ShowWarning("The IP security order is 'deny,allow' (allow if not deny) and you refuse ALL IP.\n");
-		}
-	} else if (access_order == ACO_ALLOW_DENY) {
-		if (access_allownum == 0) {
-			ShowWarning("The IP security order is 'allow,deny' (deny if not allow) but, NO IP IS AUTHORISED!\n");
-		}
-	} else { // ACO_MUTUAL_FAILTURE
-		if (access_allownum == 0) {
-			ShowWarning("The IP security order is 'mutual-failture'\n");
-			ShowWarning("  (allow if in the allow list and not in the deny list).\n");
-			ShowWarning("  But, NO IP IS AUTHORISED!\n");
-		} else if (access_denynum == 1 && access_deny[0] == '\0') {
-			ShowWarning("The IP security order is mutual-failture\n");
-			ShowWarning("  (allow if in the allow list and not in the deny list).\n");
-			ShowWarning("  But, you refuse ALL IP!\n");
-		}
+		login_config.start_limited_time = -1;
 	}
 
 	return;
@@ -2666,9 +2278,6 @@ void do_final(void)
 
 	if(auth_dat) aFree(auth_dat);
 	if(gm_account_db) aFree(gm_account_db);
-	if(access_ladmin_allow) aFree(access_ladmin_allow);
-	if(access_allow) aFree(access_allow);
-	if(access_deny) aFree(access_deny);
 
 	for (i = 0; i < MAX_SERVERS; i++) {
 		if ((fd = server[i].fd) >= 0) {
@@ -2679,9 +2288,6 @@ void do_final(void)
 	}
 	do_close(login_fd);
 
-	if(log_fp)
-		fclose(log_fp);
-
 	ShowStatus("Finished.\n");
 }
 
@@ -2755,8 +2361,6 @@ int do_init(int argc, char** argv)
 		//##TODO invoke a CONSOLE_START plugin event
 	}
 
-	new_reg_tick = gettick();
-
 	// server port open & binding
 	login_fd = make_listen_bind(login_config.login_ip, login_config.login_port);
 

+ 22 - 21
src/login/login.h

@@ -38,28 +38,29 @@ struct mmo_char_server {
 
 extern struct Login_Config {
 
-	uint32 login_ip;								// the address to bind to
-	uint16 login_port;								// the port to bind to
-	unsigned int ip_sync_interval;					// interval (in minutes) to execute a DNS/IP update (for dynamic IPs)
-	bool log_login;									// whether to log login server actions or not
-	char date_format[32];							// date format used in messages
-	bool console;									// console input system enabled?
-	bool new_account_flag;							// autoregistration via _M/_F ?
-//	bool case_sensitive;							// are logins case sensitive ?
-	bool use_md5_passwds;							// work with password hashes instead of plaintext passwords?
-//	bool login_gm_read;								// should the login server handle info about gm accounts?
-	int min_level_to_connect;						// minimum level of player/GM (0: player, 1-99: GM) to connect
-	bool online_check;								// reject incoming players that are already registered as online ?
-	bool check_client_version;						// check the clientversion set in the clientinfo ?
-	int client_version_to_connect;					// the client version needed to connect (if checking is enabled)
+	uint32 login_ip;                                // the address to bind to
+	uint16 login_port;                              // the port to bind to
+	unsigned int ip_sync_interval;                  // interval (in minutes) to execute a DNS/IP update (for dynamic IPs)
+	bool log_login;                                 // whether to log login server actions or not
+	char date_format[32];                           // date format used in messages
+	bool console;                                   // console input system enabled?
+	bool new_account_flag;                          // autoregistration via _M/_F ?
+	int start_limited_time;                         // new account expiration time (-1: unlimited)
+//	bool case_sensitive;                            // are logins case sensitive ?
+	bool use_md5_passwds;                           // work with password hashes instead of plaintext passwords?
+//	bool login_gm_read;                             // should the login server handle info about gm accounts?
+	int min_level_to_connect;                       // minimum level of player/GM (0: player, 1-99: GM) to connect
+	bool online_check;                              // reject incoming players that are already registered as online ?
+	bool check_client_version;                      // check the clientversion set in the clientinfo ?
+	int client_version_to_connect;                  // the client version needed to connect (if checking is enabled)
 
-//	bool ipban;										// perform IP blocking (via contents of `ipbanlist`) ?
-//	bool dynamic_pass_failure_ban;					// automatic IP blocking due to failed login attemps ?
-//	unsigned int dynamic_pass_failure_ban_interval;	// how far to scan the loginlog for password failures
-//	unsigned int dynamic_pass_failure_ban_limit;	// number of failures needed to trigger the ipban
-//	unsigned int dynamic_pass_failure_ban_duration;	// duration of the ipban
-	bool use_dnsbl;									// dns blacklist blocking ?
-	char dnsbl_servs[1024];							// comma-separated list of dnsbl servers
+//	bool ipban;                                     // perform IP blocking (via contents of `ipbanlist`) ?
+//	bool dynamic_pass_failure_ban;                  // automatic IP blocking due to failed login attemps ?
+//	unsigned int dynamic_pass_failure_ban_interval; // how far to scan the loginlog for password failures
+//	unsigned int dynamic_pass_failure_ban_limit;    // number of failures needed to trigger the ipban
+//	unsigned int dynamic_pass_failure_ban_duration; // duration of the ipban
+	bool use_dnsbl;                                 // dns blacklist blocking ?
+	char dnsbl_servs[1024];                         // comma-separated list of dnsbl servers
 
 } login_config;
 

+ 26 - 30
src/login_sql/login.c

@@ -35,15 +35,16 @@ struct s_subnet {
 
 int subnet_count = 0;
 
+// GM account management
 struct gm_account* gm_account_db = NULL;
 unsigned int GM_num = 0; // number of gm accounts
 
 //Account registration flood protection [Kevin]
 int allowed_regs = 1;
 int time_allowed = 10; //in seconds
-unsigned int new_reg_tick = 0;
-int num_regs = 0;
 
+
+// data handling (SQL)
 Sql* sql_handle;
 
 // database parameters
@@ -66,6 +67,9 @@ char login_db_user_pass[256] = "user_pass";
 char login_db_level[256] = "level";
 
 
+//-----------------------------------------------------
+// Session data structure
+//-----------------------------------------------------
 struct login_session_data {
 	uint16 md5keylen;
 	char md5key[20];
@@ -386,8 +390,12 @@ bool check_password(struct login_session_data* ld, int passwdenc, const char* pa
 //-----------------------------------------------------
 int mmo_auth_new(struct mmo_account* account, char sex)
 {
+	static int num_regs = 0; // registration counter
+	static unsigned int new_reg_tick = gettick();
+
 	unsigned int tick = gettick();
 	char md5buf[32+1];
+	time_t connect_until = 0;
 	SqlStmt* stmt;
 	int result = 0;
 
@@ -413,10 +421,13 @@ int mmo_auth_new(struct mmo_account* account, char sex)
 	if( result )
 		return result;// error or incorrect user/pass
 
+	if( login_config.start_limited_time != -1 )
+		connect_until = time(NULL) + login_config.start_limited_time;
+
 	// insert new entry into db
 	//TODO: error checking
 	stmt = SqlStmt_Malloc(sql_handle);
-	SqlStmt_Prepare(stmt, "INSERT INTO `%s` (`%s`, `%s`, `sex`, `email`) VALUES (?, ?, '%c', 'a@a.com')", login_db, login_db_userid, login_db_user_pass, TOUPPER(sex));
+	SqlStmt_Prepare(stmt, "INSERT INTO `%s` (`%s`, `%s`, `sex`, `email`, `connect_until`) VALUES (?, ?, '%c', 'a@a.com', '%d')", login_db, login_db_userid, login_db_user_pass, TOUPPER(sex), connect_until);
 	SqlStmt_BindParam(stmt, 0, SQLDT_STRING, account->userid, strnlen(account->userid, NAME_LENGTH));
 	if( login_config.use_md5_passwds )
 	{
@@ -426,9 +437,9 @@ int mmo_auth_new(struct mmo_account* account, char sex)
 	else
 		SqlStmt_BindParam(stmt, 1, SQLDT_STRING, account->passwd, strnlen(account->passwd, NAME_LENGTH));
 	SqlStmt_Execute(stmt);
-	SqlStmt_Free(stmt);
 
-	ShowInfo("New account: userid='%s' passwd='%s' sex='%c'\n", account->userid, account->passwd, TOUPPER(sex));
+	ShowNotice("Account creation (account %s, id: %d, pass: %s, sex: %c, connection with _M/_F)\n", account->userid, SqlStmt_LastInsertId(stmt), account->passwd, TOUPPER(sex));
+	SqlStmt_Free(stmt);
 
 	if( DIFF_TICK(tick, new_reg_tick) > 0 )
 	{// Update the registration check.
@@ -600,7 +611,8 @@ static int online_db_setoffline(DBKey key, void* data, va_list ap)
 //--------------------------------
 int parse_fromchar(int fd)
 {
-	int i, id;
+	unsigned int i;
+	int id;
 	uint32 ipl;
 	char ip[16];
 
@@ -786,25 +798,6 @@ int parse_fromchar(int fd)
 			WFIFOSET(fd,2);
 		break;
 
-		case 0x2720: // Request to become a GM
-			if( RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2) )
-				return 0;
-		{
-			int acc = RFIFOL(fd,4);
-			RFIFOSKIP(fd, RFIFOW(fd,2));
-
-			ShowWarning("change GM isn't supported in this login server version.\n");
-			ShowError("change GM error 0 %s\n", RFIFOP(fd,8));
-
-			// announce gm level update result
-			WFIFOHEAD(fd,10);
-			WFIFOW(fd,0) = 0x2721;
-			WFIFOL(fd,2) = acc;
-			WFIFOL(fd,6) = 0; // level
-			WFIFOSET(fd,10);
-		}
-		break;
-
 		// Map server send information to change an email of an account via char-server
 		case 0x2722:	// 0x2722 <account_id>.L <actual_e-mail>.40B <new_e-mail>.40B
 			if (RFIFOREST(fd) < 86)
@@ -1404,7 +1397,7 @@ void login_auth_failed(struct mmo_account* account, int fd, int result)
 int parse_login(int fd)
 {
 	struct mmo_account account;
-	int result, i;
+	int result;
 	uint32 ipl;
 	char ip[16];
 
@@ -1471,14 +1464,16 @@ int parse_login(int fd)
 			account.version = RFIFOL(fd,2);
 			safestrncpy(account.userid, (char*)RFIFOP(fd,6), NAME_LENGTH);//## does it have to be nul-terminated?
 			if (command != 0x01dd) {
+				ShowStatus("Request for connection of %s (ip: %s).\n", account.userid, ip);
 				safestrncpy(account.passwd, (char*)RFIFOP(fd,30), NAME_LENGTH);//## does it have to be nul-terminated?
+				account.passwdenc = 0;
 			} else {
+				ShowStatus("Request for connection (encryption mode) of %s (ip: %s).\n", account.userid, ip);
 				memcpy(account.passwd, RFIFOP(fd,30), 16); account.passwd[16] = '\0'; // raw binary data here!
+				account.passwdenc = PASSWORDENC;
 			}
 			RFIFOSKIP(fd,packet_len);
 
-			account.passwdenc = (command == 0x01dd) ? PASSWORDENC : 0;
-
 			result = mmo_auth(&account, fd);
 
 			if( result == -1 )
@@ -1492,6 +1487,7 @@ int parse_login(int fd)
 			RFIFOSKIP(fd,2);
 		{
 			struct login_session_data* ld;
+			unsigned int i;
 			if( session[fd]->session_data )
 			{
 				ShowWarning("login: abnormal request of MD5 key (already opened session).\n");
@@ -1777,6 +1773,8 @@ int login_config_read(const char* cfgName)
 
 		else if(!strcmpi(w1, "new_account"))
 			login_config.new_account_flag = (bool)config_switch(w2);
+		else if(!strcmpi(w1, "start_limited_time"))
+			login_config.start_limited_time = atoi(w2);
 		else if(!strcmpi(w1, "check_client_version"))
 			login_config.check_client_version = (bool)config_switch(w2);
 		else if(!strcmpi(w1, "client_version_to_connect"))
@@ -1980,8 +1978,6 @@ int do_init(int argc, char** argv)
 		//##TODO invoke a CONSOLE_START plugin event
 	}
 
-	new_reg_tick = gettick();
-
 	// server port open & binding
 	login_fd = make_listen_bind(login_config.login_ip, login_config.login_port);
 

+ 22 - 21
src/login_sql/login.h

@@ -39,28 +39,29 @@ struct mmo_char_server {
 
 extern struct Login_Config {
 
-	uint32 login_ip;								// the address to bind to
-	uint16 login_port;								// the port to bind to
-	unsigned int ip_sync_interval;					// interval (in minutes) to execute a DNS/IP update (for dynamic IPs)
-	bool log_login;									// whether to log login server actions or not
-	char date_format[32];							// date format used in messages
-	bool console;									// console input system enabled?
-	bool new_account_flag;							// autoregistration via _M/_F ?
-	bool case_sensitive;							// are logins case sensitive ?
-	bool use_md5_passwds;							// work with password hashes instead of plaintext passwords?
-	bool login_gm_read;								// should the login server handle info about gm accounts?
-	int min_level_to_connect;						// minimum level of player/GM (0: player, 1-99: GM) to connect
-	bool online_check;								// reject incoming players that are already registered as online ?
-	bool check_client_version;						// check the clientversion set in the clientinfo ?
-	int client_version_to_connect;					// the client version needed to connect (if checking is enabled)
+	uint32 login_ip;                                // the address to bind to
+	uint16 login_port;                              // the port to bind to
+	unsigned int ip_sync_interval;                  // interval (in minutes) to execute a DNS/IP update (for dynamic IPs)
+	bool log_login;                                 // whether to log login server actions or not
+	char date_format[32];                           // date format used in messages
+	bool console;                                   // console input system enabled?
+	bool new_account_flag;                          // autoregistration via _M/_F ?
+	int start_limited_time;                         // new account expiration time (-1: unlimited)
+	bool case_sensitive;                            // are logins case sensitive ?
+	bool use_md5_passwds;                           // work with password hashes instead of plaintext passwords?
+	bool login_gm_read;                             // should the login server handle info about gm accounts?
+	int min_level_to_connect;                       // minimum level of player/GM (0: player, 1-99: GM) to connect
+	bool online_check;                              // reject incoming players that are already registered as online ?
+	bool check_client_version;                      // check the clientversion set in the clientinfo ?
+	int client_version_to_connect;                  // the client version needed to connect (if checking is enabled)
 
-	bool ipban;										// perform IP blocking (via contents of `ipbanlist`) ?
-	bool dynamic_pass_failure_ban;					// automatic IP blocking due to failed login attemps ?
-	unsigned int dynamic_pass_failure_ban_interval;	// how far to scan the loginlog for password failures
-	unsigned int dynamic_pass_failure_ban_limit;	// number of failures needed to trigger the ipban
-	unsigned int dynamic_pass_failure_ban_duration;	// duration of the ipban
-	bool use_dnsbl;									// dns blacklist blocking ?
-	char dnsbl_servs[1024];							// comma-separated list of dnsbl servers
+	bool ipban;                                     // perform IP blocking (via contents of `ipbanlist`) ?
+	bool dynamic_pass_failure_ban;                  // automatic IP blocking due to failed login attemps ?
+	unsigned int dynamic_pass_failure_ban_interval; // how far to scan the loginlog for password failures
+	unsigned int dynamic_pass_failure_ban_limit;    // number of failures needed to trigger the ipban
+	unsigned int dynamic_pass_failure_ban_duration; // duration of the ipban
+	bool use_dnsbl;                                 // dns blacklist blocking ?
+	char dnsbl_servs[1024];                         // comma-separated list of dnsbl servers
 
 } login_config;
 

+ 0 - 25
src/map/atcommand.c

@@ -1902,30 +1902,6 @@ int atcommand_help2(const int fd, struct map_session_data* sd, const char* comma
 }
 
 
-/*==========================================
- * @gm
- *------------------------------------------*/
-int atcommand_gm(const int fd, struct map_session_data* sd, const char* command, const char* message)
-{
-	char password[100];
-	nullpo_retr(-1, sd);
-
-	memset(password, '\0', sizeof(password));
-
-	if (!message || !*message || sscanf(message, "%99[^\n]", password) < 1) {
-		clif_displaymessage(fd, "Please, enter a password (usage: @gm <password>).");
-		return -1;
-	}
-
-	if (pc_isGM(sd)) { // a GM can not use this function. only a normal player (become gm is not for gm!)
-		clif_displaymessage(fd, msg_txt(50)); // You already have some GM powers.
-		return -1;
-	} else
-		chrif_changegm(sd->status.account_id, password, strlen(password) + 1);
-
-	return 0;
-}
-
 // helper function, used in foreach calls to stop auto-attack timers
 // parameter: '0' - everyone, 'id' - only those attacking someone with that id
 static int atcommand_stopattack(struct block_list *bl,va_list ap)
@@ -8333,7 +8309,6 @@ AtCommandInfo atcommand_info[] = {
 	{ "help",              20,     atcommand_help },
 	{ "h2",                20,     atcommand_help2 },
 	{ "help2",             20,     atcommand_help2 },
-	{ "gm",               100,     atcommand_gm },
 	{ "pvpoff",            40,     atcommand_pvpoff },
 	{ "pvpon",             40,     atcommand_pvpon },
 	{ "gvgoff",            40,     atcommand_gvgoff },

+ 3 - 49
src/map/chrif.c

@@ -33,7 +33,7 @@ static DBMap* auth_db; // int id -> struct auth_node*
 static const int packet_len_table[0x3d] = { // U - used, F - free
 	60, 3,-1,27,10,-1, 6,-1,	// 2af8-2aff: U->2af8, U->2af9, U->2afa, U->2afb, U->2afc, U->2afd, U->2afe, U->2aff
 	 6,-1,18, 7,-1,35,30,10,	// 2b00-2b07: U->2b00, U->2b01, U->2b02, U->2b03, U->2b04, U->2b05, U->2b06, U->2b07
-	 6,30,-1,10,86, 7,44,34,	// 2b08-2b0f: U->2b08, U->2b09, U->2b0a, U->2b0b, U->2b0c, U->2b0d, U->2b0e, U->2b0f
+	 6,30,-1,-1,86, 7,44,34,	// 2b08-2b0f: U->2b08, U->2b09, F->2b0a, F->2b0b, U->2b0c, U->2b0d, U->2b0e, U->2b0f
 	11,10,10, 6,11,-1,266,10,	// 2b10-2b17: U->2b10, U->2b11, U->2b12, U->2b13, U->2b14, U->2b15, U->2b16, U->2b17
 	 2,10, 2,-1,-1,-1, 2, 7,	// 2b18-2b1f: U->2b18, U->2b19, U->2b1a, U->2b1b, U->2b1c, U->2b1d, U->2b1e, U->2b1f
 	-1,10, 8, 2, 2,14,-1,-1,	// 2b20-2b27: U->2b20, U->2b21, U->2b22, U->2b23, U->2b24, U->2b25, F->2b26, F->2b27
@@ -58,8 +58,8 @@ static const int packet_len_table[0x3d] = { // U - used, F - free
 //2b07: Incoming, clif_updatemaxid -> Received when updating the max account/char known
 //2b08: Outgoing, chrif_searchcharid -> '...'
 //2b09: Incoming, map_addchariddb -> 'Adds a name to the nick db'
-//2b0a: Outgoing, chrif_changegm -> 'level change of acc/char XY'
-//2b0b: Incoming, chrif_changedgm -> 'answer of 2b0a..'
+//2b0a: FREE
+//2b0b: FREE
 //2b0c: Outgoing, chrif_changeemail -> 'change mail address ...'
 //2b0d: Incoming, chrif_changedsex -> 'Change sex of acc XY'
 //2b0e: Outgoing, chrif_char_ask_name -> 'Do some operations (change sex, ban / unban etc)'
@@ -670,26 +670,6 @@ int chrif_searchcharid(int char_id)
 	return 0;
 }
 
-/*==========================================
- * GMに変化要求
- *------------------------------------------*/
-int chrif_changegm(int id, const char *pass, int len)
-{
-	if (battle_config.etc_log)
-		ShowInfo("chrif_changegm: account: %d, password: '%s'.\n", id, pass);
-
-	chrif_check(-1);
-
-	WFIFOHEAD(char_fd, len + 8);
-	WFIFOW(char_fd,0) = 0x2b0a;
-	WFIFOW(char_fd,2) = len + 8;
-	WFIFOL(char_fd,4) = id;
-	memcpy(WFIFOP(char_fd,8), pass, len);
-	WFIFOSET(char_fd, len + 8);
-
-	return 0;
-}
-
 /*==========================================
  * Change Email
  *------------------------------------------*/
@@ -795,31 +775,6 @@ static void chrif_char_ask_name_answer(int acc, const char* player_name, uint16
 	clif_displaymessage(sd->fd, output);
 }
 
-/*==========================================
- * End of GM change (@GM) (modified by Yor)
- *------------------------------------------*/
-int chrif_changedgm(int fd)
-{
-	int acc, level;
-	struct map_session_data *sd = NULL;
-
-	acc = RFIFOL(fd,2);
-	level = RFIFOL(fd,6);
-
-	sd = map_id2sd(acc);
-
-	if (battle_config.etc_log)
-		ShowNotice("chrif_changedgm: account: %d, GM level 0 -> %d.\n", acc, level);
-	if (sd != NULL) {
-		if (level > 0)
-			clif_displaymessage(sd->fd, "GM modification success.");
-		else
-			clif_displaymessage(sd->fd, "Failure of GM modification.");
-	}
-
-	return 0;
-}
-
 /*==========================================
  * 性別変化終了 (modified by Yor)
  *------------------------------------------*/
@@ -1448,7 +1403,6 @@ int chrif_parse(int fd)
 		case 0x2b06: chrif_changemapserverack(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), RFIFOW(fd,18), RFIFOW(fd,20), RFIFOW(fd,22), RFIFOL(fd,24), RFIFOW(fd,28)); break;
 		case 0x2b07: clif_updatemaxid(RFIFOL(fd,2), RFIFOL(fd,6)); break;
 		case 0x2b09: map_addnickdb(RFIFOL(fd,2), (char*)RFIFOP(fd,6)); break;
-		case 0x2b0b: chrif_changedgm(fd); break;
 		case 0x2b0d: chrif_changedsex(fd); break;
 		case 0x2b0f: chrif_char_ask_name_answer(RFIFOL(fd,2), (char*)RFIFOP(fd,6), RFIFOW(fd,30), RFIFOW(fd,32)); break;
 		case 0x2b12: chrif_divorceack(RFIFOL(fd,2), RFIFOL(fd,6)); break;

+ 0 - 1
src/map/chrif.h

@@ -42,7 +42,6 @@ int chrif_charselectreq(struct map_session_data* sd, uint32 s_ip);
 int chrif_changemapserver(struct map_session_data* sd, uint32 ip, uint16 port);
 
 int chrif_searchcharid(int char_id);
-int chrif_changegm(int id,const char *pass,int len);
 int chrif_changeemail(int id, const char *actual_email, const char *new_email);
 int chrif_char_ask_name(int acc, const char* character_name, unsigned short operation_type, int year, int month, int day, int hour, int minute, int second);
 int chrif_reloadGMdb(void);