diff options
-rw-r--r-- | Changelog-Trunk.txt | 7 | ||||
-rw-r--r-- | sql-files/main.sql | 8 | ||||
-rw-r--r-- | sql-files/upgrade_svn12043.sql | 5 | ||||
-rw-r--r-- | src/char/char.c | 5 | ||||
-rw-r--r-- | src/char_sql/char.c | 5 | ||||
-rw-r--r-- | src/login/admin.c | 6 | ||||
-rw-r--r-- | src/login/login.c | 499 | ||||
-rw-r--r-- | src/login_sql/login.c | 308 | ||||
-rw-r--r-- | src/map/itemdb.c | 10 | ||||
-rw-r--r-- | src/map/itemdb.h | 1 | ||||
-rw-r--r-- | src/map/skill.c | 7 |
11 files changed, 412 insertions, 449 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index dbabe4264..9129294c5 100644 --- a/Changelog-Trunk.txt +++ b/Changelog-Trunk.txt @@ -4,6 +4,13 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK. 2008/01/10 + * Another round of login server cleaning [ultramage] + - fixed passwordencrypt on SQL not behaving correctly (since r10753) + - corrected some column lengths in the login db (username, password,...) + - fixed some places which used wfifo without first reallocating it + - removed interserver packet 0x7532 (Request to end connection), as + there was no code that actually sent this packet + - moved RFIFOSKIP actions to execute as soon as possible * Corrected @slaveclone/@clone behaving as @evilclone when you change the @ symbol. * Modified SC_ARMOR_ELEMENT so it grants elemental resist as if it they diff --git a/sql-files/main.sql b/sql-files/main.sql index e19b7567f..5c5a7a0e6 100644 --- a/sql-files/main.sql +++ b/sql-files/main.sql @@ -93,7 +93,7 @@ CREATE TABLE `charlog` ( `char_msg` varchar(255) NOT NULL default 'char select', `account_id` int(11) NOT NULL default '0', `char_num` tinyint(4) NOT NULL default '0', - `name` varchar(255) NOT NULL default '', + `name` varchar(23) NOT NULL default '', `str` int(11) unsigned NOT NULL default '0', `agi` int(11) unsigned NOT NULL default '0', `vit` int(11) unsigned NOT NULL default '0', @@ -392,8 +392,8 @@ CREATE TABLE `ipbanlist` ( DROP TABLE IF EXISTS `login`; CREATE TABLE `login` ( `account_id` int(11) unsigned NOT NULL auto_increment, - `userid` varchar(255) NOT NULL default '', - `user_pass` varchar(32) NOT NULL default '', + `userid` varchar(23) NOT NULL default '', + `user_pass` varchar(23) NOT NULL default '', `lastlogin` datetime NOT NULL default '0000-00-00 00:00:00', `sex` enum('M','F','S') NOT NULL default 'M', `logincount` mediumint(9) unsigned NOT NULL default '0', @@ -453,7 +453,7 @@ DROP TABLE IF EXISTS `loginlog`; CREATE TABLE `loginlog` ( `time` datetime NOT NULL default '0000-00-00 00:00:00', `ip` int(10) unsigned NOT NULL default '0', - `user` varchar(32) NOT NULL default '', + `user` varchar(23) NOT NULL default '', `rcode` tinyint(4) NOT NULL default '0', `log` varchar(255) NOT NULL default '', INDEX (`ip`) diff --git a/sql-files/upgrade_svn12043.sql b/sql-files/upgrade_svn12043.sql new file mode 100644 index 000000000..c811bab91 --- /dev/null +++ b/sql-files/upgrade_svn12043.sql @@ -0,0 +1,5 @@ +ALTER TABLE `login` MODIFY COLUMN `userid` VARCHAR(23) NOT NULL default ''; +ALTER TABLE `login` MODIFY COLUMN `user_pass` VARCHAR(23) NOT NULL default ''; + +ALTER TABLE `loginlog` MODIFY COLUMN `user` VARCHAR(23) NOT NULL default ''; +ALTER TABLE `charlog` MODIFY COLUMN `name` VARCHAR(23) NOT NULL default ''; diff --git a/src/char/char.c b/src/char/char.c index 42f5b83b0..d853a72ba 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -3681,11 +3681,6 @@ int parse_char(int fd) RFIFOSKIP(fd,2); break; - // disconnect request from login server - case 0x7532: - set_eof(fd); - return 0; - // unknown packet received default: ShowError("parse_char: Received unknown packet "CL_WHITE"0x%x"CL_RESET" from ip '"CL_WHITE"%s"CL_RESET"'! Disconnecting!\n", RFIFOW(fd,0), ip2str(ipl, NULL)); diff --git a/src/char_sql/char.c b/src/char_sql/char.c index 8dd8738b2..30e33f011 100644 --- a/src/char_sql/char.c +++ b/src/char_sql/char.c @@ -3229,11 +3229,6 @@ int parse_char(int fd) RFIFOSKIP(fd,2); break; - // disconnect request from login server - case 0x7532: - set_eof(fd); - return 0; - // unknown packet received default: ShowError("parse_char: Received unknown packet "CL_WHITE"0x%x"CL_RESET" from ip '"CL_WHITE"%s"CL_RESET"'! Disconnecting!\n", RFIFOW(fd,0), ip2str(ipl, NULL)); diff --git a/src/login/admin.c b/src/login/admin.c index 152c9e84d..32b89fc4d 100644 --- a/src/login/admin.c +++ b/src/login/admin.c @@ -74,12 +74,6 @@ int parse_admin(int fd) RFIFOSKIP(fd,2); break; - case 0x7532: // Request of end of connection - ShowStatus("'ladmin': End of connection (ip: %s)\n", ip); - RFIFOSKIP(fd,2); - set_eof(fd); - break; - case 0x7920: // Request of an accounts list if (RFIFOREST(fd) < 10) return 0; diff --git a/src/login/login.c b/src/login/login.c index 0fb728ff2..6ed9fdb6a 100644 --- a/src/login/login.c +++ b/src/login/login.c @@ -1052,8 +1052,7 @@ int mmo_auth(struct mmo_account* account, int fd) } //Client Version check - if( login_config.check_client_version && account->version != 0 && - account->version != login_config.client_version_to_connect ) + if( login_config.check_client_version && account->version != login_config.client_version_to_connect ) return 5; len = strnlen(account->userid, NAME_LENGTH); @@ -1251,11 +1250,11 @@ int parse_fromchar(int fd) { case 0x2709: // request from map-server via char-server to reload GM accounts + RFIFOSKIP(fd,2); ShowStatus("Char-server '%s': Request to re-load GM configuration file (ip: %s).\n", server[id].name, ip); read_gm_account(); // send GM accounts to all char-servers send_GM_accounts(-1); - RFIFOSKIP(fd,2); break; case 0x2712: // request from char-server to authenticate an account @@ -1263,25 +1262,43 @@ int parse_fromchar(int fd) return 0; { int account_id = RFIFOL(fd,2); + int login_id1 = RFIFOL(fd,6); + int login_id2 = RFIFOL(fd,10); + char sex = RFIFOB(fd,14); + uint32 ip_ = ntohl(RFIFOL(fd,15)); + RFIFOSKIP(fd,19); + ARR_FIND( 0, AUTH_FIFO_SIZE, i, - auth_fifo[i].account_id == RFIFOL(fd,2) && - auth_fifo[i].login_id1 == RFIFOL(fd,6) && - auth_fifo[i].login_id2 == RFIFOL(fd,10) && - auth_fifo[i].sex == RFIFOB(fd,14) && - auth_fifo[i].ip == ntohl(RFIFOL(fd,15)) && + auth_fifo[i].account_id == account_id && + auth_fifo[i].login_id1 == login_id1 && + auth_fifo[i].login_id2 == login_id2 && + auth_fifo[i].sex == sex && + auth_fifo[i].ip == ip_ && !auth_fifo[i].delflag ); - if( i < AUTH_FIFO_SIZE ) - auth_fifo[i].delflag = 1; - - if( i < AUTH_FIFO_SIZE && account_id > 0 ) - {// send ack + if( i == AUTH_FIFO_SIZE || account_id <= 0 ) + {// authentication not found + ShowStatus("Char-server '%s': authentication of the account %d REFUSED (ip: %s).\n", server[id].name, account_id, ip); + WFIFOHEAD(fd,51); + WFIFOW(fd,0) = 0x2713; + WFIFOL(fd,2) = account_id; + WFIFOB(fd,6) = 1; + // It is unnecessary to send email + // It is unnecessary to send validity date of the account + WFIFOSET(fd,51); + } + else + {// found time_t connect_until_time; char email[40]; unsigned int k; //ShowStatus("Char-server '%s': authentication of the account %d accepted (ip: %s).\n", server[id].name, account_id, ip); + // each auth entry can only be used once + auth_fifo[i].delflag = 1; + + // retrieve email and account expiration time ARR_FIND( 0, auth_num, k, auth_dat[k].account_id == account_id ); if( k < auth_num ) { @@ -1294,6 +1311,7 @@ int parse_fromchar(int fd) connect_until_time = 0; } + // send ack WFIFOHEAD(fd,51); WFIFOW(fd,0) = 0x2713; WFIFOL(fd,2) = account_id; @@ -1302,19 +1320,6 @@ int parse_fromchar(int fd) WFIFOL(fd,47) = (unsigned long)connect_until_time; WFIFOSET(fd,51); } - else - {// authentication not found - ShowStatus("Char-server '%s': authentication of the account %d REFUSED (ip: %s).\n", server[id].name, account_id, ip); - WFIFOHEAD(fd,51); - WFIFOW(fd,0) = 0x2713; - WFIFOL(fd,2) = account_id; - WFIFOB(fd,6) = 1; - // It is unnecessary to send email - // It is unnecessary to send validity date of the account - WFIFOSET(fd,51); - } - - RFIFOSKIP(fd,19); } break; @@ -1323,7 +1328,6 @@ int parse_fromchar(int fd) 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); - RFIFOSKIP(fd,6); break; @@ -1333,8 +1337,9 @@ int parse_fromchar(int fd) { char email[40]; int acc = RFIFOL(fd,2); - safestrncpy(email, (char*)RFIFOP(fd,6), 40); - remove_control_chars(email); + safestrncpy(email, (char*)RFIFOP(fd,6), 40); remove_control_chars(email); + RFIFOSKIP(fd,46); + if( e_mail_check(email) == 0 ) ShowNotice("Char-server '%s': Attempt to create an e-mail on an account with a default e-mail REFUSED - e-mail is invalid (account: %d, ip: %s)\n", server[id].name, acc, ip); else @@ -1350,64 +1355,70 @@ int parse_fromchar(int fd) mmo_auth_sync(); } } - - RFIFOSKIP(fd,46); } break; case 0x2716: // received an e-mail/limited time request, because a player comes back from a map-server to the char-server if( RFIFOREST(fd) < 6 ) return 0; + { + uint32 connect_until_time = 0; + char* email = ""; + + int account_id = RFIFOL(fd,2); + RFIFOSKIP(fd,6); - ARR_FIND( 0, auth_num, i, auth_dat[i].account_id == (int)RFIFOL(fd,2) ); + ARR_FIND( 0, auth_num, i, auth_dat[i].account_id == account_id ); if( i == auth_num ) ShowNotice("Char-server '%s': e-mail of the account %d NOT found (ip: %s).\n", server[id].name, RFIFOL(fd,2), ip); else { - //ShowNotice("Char-server '%s': e-mail of the account %d found (ip: %s).\n", server[id].name, RFIFOL(fd,2), ip); - WFIFOW(fd,0) = 0x2717; - WFIFOL(fd,2) = RFIFOL(fd,2); - safestrncpy((char*)WFIFOP(fd, 6), auth_dat[i].email, 40); - WFIFOL(fd,46) = (unsigned long)auth_dat[i].connect_until_time; - WFIFOSET(fd,50); + email = auth_dat[i].email; + connect_until_time = (uint32)auth_dat[i].connect_until_time; } - RFIFOSKIP(fd,6); + WFIFOHEAD(fd,50); + WFIFOW(fd,0) = 0x2717; + WFIFOL(fd,2) = account_id; + safestrncpy((char*)WFIFOP(fd,6), email, 40); + WFIFOL(fd,46) = connect_until_time; + WFIFOSET(fd,50); + } break; case 0x2719: // ping request from charserver if( RFIFOREST(fd) < 2 ) return 0; + RFIFOSKIP(fd,2); WFIFOHEAD(fd,2); WFIFOW(fd,0) = 0x2718; WFIFOSET(fd,2); - - RFIFOSKIP(fd,2); break; case 0x2720: // Request to become a GM if( RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2) ) return 0; { - unsigned char buf[10]; + int level = 0; FILE *fp; + + char pass[60]; int acc = RFIFOL(fd,4); - WBUFW(buf,0) = 0x2721; - WBUFL(buf,2) = acc; - WBUFL(buf,6) = 0; + safestrncpy(pass, (char*)RFIFOP(fd,8), sizeof(pass)); + RFIFOSKIP(fd, RFIFOW(fd,2)); - if( strcmp((char*)RFIFOP(fd,8), gm_pass) != 0 ) // password check - ShowError("Char-server '%s': Error of GM change (suggested account: %d, invalid password, ip: %s).\n", server[id].name, acc, ip); + 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 (suggested account: %d (already GM), correct password, ip: %s).\n", server[id].name, acc, ip); + 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 (suggested account: %d, correct password, but GM creation is disable (level_new_gm = 0), ip: %s).\n", server[id].name, acc, ip); + 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 (suggested account: %d, correct password, unable to add a GM account in GM accounts file, ip: %s).\n", server[id].name, acc, ip); + 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]; @@ -1416,51 +1427,54 @@ int parse_fromchar(int fd) 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); - WBUFL(buf,6) = level_new_gm; + 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 - charif_sendallwos(-1, buf, 10); - RFIFOSKIP(fd, RFIFOW(fd,2)); - return 0; + // 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) return 0; { - char actual_email[40], new_email[40]; - int acc = RFIFOL(fd,2); - memcpy(actual_email, RFIFOP(fd,6), 40); actual_email[39] = '\0'; remove_control_chars(actual_email); - memcpy(new_email, RFIFOP(fd,46), 40); new_email[39] = '\0'; remove_control_chars(new_email); - 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, acc, ip); + char actual_email[40]; + char new_email[40]; + int account_id = RFIFOL(fd,2); + safestrncpy(actual_email, RFIFOP(fd,6), 40); remove_control_chars(actual_email); + safestrncpy(new_email, RFIFOP(fd,46), 40); remove_control_chars(new_email); + RFIFOSKIP(fd, 86); + + 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) - 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, acc, ip); + 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) - 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, acc, ip); + 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 == acc ); + ARR_FIND( 0, auth_num, i, auth_dat[i].account_id == account_id ); if( i == auth_num ) - ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but account doesn't exist (account: %d, ip: %s).\n", server[id].name, acc, ip); + ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but account doesn't exist (account: %d, ip: %s).\n", server[id].name, account_id, ip); else if( strcmpi(auth_dat[i].email, actual_email) != 0 ) - ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual e-mail is incorrect (account: %d (%s), actual e-mail: %s, proposed e-mail: %s, ip: %s).\n", server[id].name, acc, auth_dat[i].userid, auth_dat[i].email, actual_email, ip); + ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual e-mail is incorrect (account: %d (%s), actual e-mail: %s, proposed e-mail: %s, ip: %s).\n", server[id].name, account_id, auth_dat[i].userid, auth_dat[i].email, actual_email, ip); else { - memcpy(auth_dat[i].email, new_email, 40); - ShowNotice("Char-server '%s': Modify an e-mail on an account (@email GM command) (account: %d (%s), new e-mail: %s, ip: %s).\n", server[id].name, acc, auth_dat[i].userid, new_email, ip); + safestrncpy(auth_dat[i].email, new_email, 40); + ShowNotice("Char-server '%s': Modify an e-mail on an account (@email GM command) (account: %d (%s), new e-mail: %s, ip: %s).\n", server[id].name, account_id, auth_dat[i].userid, new_email, ip); // Save mmo_auth_sync(); } } - - RFIFOSKIP(fd, 86); } break; @@ -1470,6 +1484,7 @@ int parse_fromchar(int fd) { int account_id = RFIFOL(fd,2); uint32 state = RFIFOL(fd,6); + RFIFOSKIP(fd,10); ARR_FIND( 0, auth_num, i, auth_dat[i].account_id == account_id ); if( i == auth_num ) @@ -1494,19 +1509,25 @@ int parse_fromchar(int fd) // Save mmo_auth_sync(); } - - RFIFOSKIP(fd,10); - return 0; } + break; case 0x2725: // Receiving of map-server via char-server a ban request if (RFIFOREST(fd) < 18) return 0; { - int acc = RFIFOL(fd,2); - ARR_FIND( 0, auth_num, i, auth_dat[i].account_id == acc ); + int account_id = RFIFOL(fd,2); + int year = (short)RFIFOW(fd,6); + int month = (short)RFIFOW(fd,8); + int mday = (short)RFIFOW(fd,10); + int hour = (short)RFIFOW(fd,12); + int min = (short)RFIFOW(fd,14); + int sec = (short)RFIFOW(fd,16); + RFIFOSKIP(fd,18); + + ARR_FIND( 0, auth_num, i, auth_dat[i].account_id == account_id ); if( i == auth_num ) - ShowNotice("Char-server '%s': Error of ban request (account: %d not found, ip: %s).\n", server[id].name, acc, ip); + ShowNotice("Char-server '%s': Error of ban request (account: %d not found, ip: %s).\n", server[id].name, account_id, ip); else { time_t timestamp; @@ -1516,152 +1537,133 @@ int parse_fromchar(int fd) else timestamp = auth_dat[i].ban_until_time; tmtime = localtime(×tamp); - tmtime->tm_year = tmtime->tm_year + (short)RFIFOW(fd,6); - tmtime->tm_mon = tmtime->tm_mon + (short)RFIFOW(fd,8); - tmtime->tm_mday = tmtime->tm_mday + (short)RFIFOW(fd,10); - tmtime->tm_hour = tmtime->tm_hour + (short)RFIFOW(fd,12); - tmtime->tm_min = tmtime->tm_min + (short)RFIFOW(fd,14); - tmtime->tm_sec = tmtime->tm_sec + (short)RFIFOW(fd,16); + tmtime->tm_year = tmtime->tm_year + year; + tmtime->tm_mon = tmtime->tm_mon + month; + tmtime->tm_mday = tmtime->tm_mday + mday; + tmtime->tm_hour = tmtime->tm_hour + hour; + tmtime->tm_min = tmtime->tm_min + min; + tmtime->tm_sec = tmtime->tm_sec + sec; timestamp = mktime(tmtime); if (timestamp == -1) - ShowNotice("Char-server '%s': Error of ban request (account: %d, invalid date, ip: %s).\n", server[id].name, acc, ip); + ShowNotice("Char-server '%s': Error of ban request (account: %d, invalid date, ip: %s).\n", server[id].name, account_id, ip); + else + if( timestamp <= time(NULL) || timestamp == 0 ) + ShowNotice("Char-server '%s': Error of ban request (account: %d, new date unbans the account, ip: %s).\n", server[id].name, account_id, ip); else { - if (timestamp <= time(NULL)) - timestamp = 0; - else - { - if (timestamp == 0) - ShowNotice("Char-server '%s': Error of ban request (account: %d, new date unbans the account, ip: %s).\n", server[id].name, acc, ip); - else - { - unsigned char buf[16]; - char tmpstr[2048]; - strftime(tmpstr, 24, login_config.date_format, localtime(×tamp)); - ShowNotice("Char-server '%s': Ban request (account: %d, new final date of banishment: %d (%s), ip: %s).\n", server[id].name, acc, timestamp, (timestamp == 0 ? "no banishment" : tmpstr), ip); - WBUFW(buf,0) = 0x2731; - WBUFL(buf,2) = auth_dat[i].account_id; - WBUFB(buf,6) = 1; // 0: change of statut, 1: ban - WBUFL(buf,7) = (unsigned int)timestamp; // status or final date of a banishment - charif_sendallwos(-1, buf, 11); - ARR_FIND( 0, AUTH_FIFO_SIZE, j, auth_fifo[j].account_id == acc ); - if( j < AUTH_FIFO_SIZE ) - auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentication) - } - auth_dat[i].ban_until_time = timestamp; - // Save - mmo_auth_sync(); - } + unsigned char buf[16]; + char tmpstr[2048]; + strftime(tmpstr, 24, login_config.date_format, localtime(×tamp)); + ShowNotice("Char-server '%s': Ban request (account: %d, new final date of banishment: %d (%s), ip: %s).\n", server[id].name, account_id, timestamp, tmpstr, ip); + WBUFW(buf,0) = 0x2731; + WBUFL(buf,2) = auth_dat[i].account_id; + WBUFB(buf,6) = 1; // 0: change of status, 1: ban + WBUFL(buf,7) = (unsigned int)timestamp; // status or final date of a banishment + charif_sendallwos(-1, buf, 11); + ARR_FIND( 0, AUTH_FIFO_SIZE, j, auth_fifo[j].account_id == account_id ); + if( j < AUTH_FIFO_SIZE ) + auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentication) + + auth_dat[i].ban_until_time = timestamp; + // Save + mmo_auth_sync(); } } - - RFIFOSKIP(fd,18); - return 0; } + break; case 0x2727: // Change of sex (sex is reversed) if( RFIFOREST(fd) < 6 ) return 0; { - uint8 sex; - int acc = RFIFOL(fd,2); - for(i = 0; i < auth_num; i++) { - if (auth_dat[i].account_id == acc) { - if (auth_dat[i].sex == 2) - ShowNotice("Char-server '%s': Error of sex change - Server account (suggested account: %d, actual sex %d (Server), ip: %s).\n", server[id].name, acc, auth_dat[i].sex, ip); - else { - unsigned char buf[16]; - if (auth_dat[i].sex == 0) - sex = 1; - else - sex = 0; - ShowNotice("Char-server '%s': Sex change (account: %d, new sex %c, ip: %s).\n", server[id].name, acc, (sex == 2) ? 'S' : (sex == 1 ? 'M' : 'F'), ip); - for(j = 0; j < AUTH_FIFO_SIZE; j++) - if (auth_fifo[j].account_id == acc) - auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentication) - auth_dat[i].sex = sex; - WBUFW(buf,0) = 0x2723; - WBUFL(buf,2) = acc; - WBUFB(buf,6) = sex; - charif_sendallwos(-1, buf, 7); - // Save - mmo_auth_sync(); - } - break; - } - } - if (i == auth_num) - ShowNotice("Char-server '%s': Error of sex change (account: %d not found, sex would be reversed, ip: %s).\n", server[id].name, acc, ip); - + int account_id = RFIFOL(fd,2); RFIFOSKIP(fd,6); - return 0; + + ARR_FIND( 0, auth_num, i, auth_dat[i].account_id == account_id ); + if( i == auth_num ) + ShowNotice("Char-server '%s': Error of sex change (account: %d not found, ip: %s).\n", server[id].name, account_id, ip); + else + if( auth_dat[i].sex == 2 ) + ShowNotice("Char-server '%s': Error of sex change - account to change is a Server account (account: %d, ip: %s).\n", server[id].name, account_id, ip); + else + { + unsigned char buf[7]; + uint8 sex = ( auth_dat[i].sex == 0 ) ? 1 : 0; // invert sex + auth_dat[i].sex = sex; + ShowNotice("Char-server '%s': Sex change (account: %d, new sex %c, ip: %s).\n", server[id].name, account_id, (sex == 1 ? 'M' : 'F'), ip); + + ARR_FIND( 0, AUTH_FIFO_SIZE, j, auth_fifo[j].account_id == account_id ); + if( j < AUTH_FIFO_SIZE ) + auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentication) + + WBUFW(buf,0) = 0x2723; + WBUFL(buf,2) = account_id; + WBUFB(buf,6) = sex; + charif_sendallwos(-1, buf, 7); + // Save + mmo_auth_sync(); + } } + break; case 0x2728: // We receive account_reg2 from a char-server, and we send them to other map-servers. - if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) + if( RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2) ) return 0; + { + int acc = RFIFOL(fd,4); + + ARR_FIND( 0, auth_num, i, auth_dat[i].account_id == acc ); + if( i == auth_num ) + ShowStatus("Char-server '%s': receiving (from the char-server) of account_reg2 (account: %d not found, ip: %s).\n", server[id].name, acc, ip); + else { + int len; int p; - int acc = RFIFOL(fd,4); - for(i = 0; i < auth_num; i++) { - if (auth_dat[i].account_id == acc) { - //unsigned char buf[rfifow(fd,2)+1]; - uint8* buf; - int len; - CREATE(buf, uint8, RFIFOW(fd,2)+1); - ShowNotice("char-server '%s': receiving (from the char-server) of account_reg2 (account: %d, ip: %s).\n", server[id].name, acc, ip); - for(j=0,p=13;j<ACCOUNT_REG2_NUM && p<RFIFOW(fd,2);j++){ - sscanf((char*)RFIFOP(fd,p), "%31c%n",auth_dat[i].account_reg2[j].str,&len); - auth_dat[i].account_reg2[j].str[len]='\0'; - p +=len+1; //+1 to skip the '\0' between strings. - sscanf((char*)RFIFOP(fd,p), "%255c%n",auth_dat[i].account_reg2[j].value,&len); - auth_dat[i].account_reg2[j].value[len]='\0'; - p +=len+1; - remove_control_chars(auth_dat[i].account_reg2[j].str); - remove_control_chars(auth_dat[i].account_reg2[j].value); - } - auth_dat[i].account_reg2_num = j; - // Sending information towards the other char-servers. - memcpy(WBUFP(buf,0), RFIFOP(fd,0), RFIFOW(fd,2)); - WBUFW(buf,0) = 0x2729; - charif_sendallwos(fd, buf, WBUFW(buf,2)); - // Save - mmo_auth_sync(); - if (buf) aFree(buf); - break; - } - } - if (i == auth_num) { - ShowStatus("Char-server '%s': receiving (from the char-server) of account_reg2 (account: %d not found, ip: %s).\n", server[id].name, acc, ip); + ShowNotice("char-server '%s': receiving (from the char-server) of account_reg2 (account: %d, ip: %s).\n", server[id].name, acc, ip); + for(j=0,p=13;j<ACCOUNT_REG2_NUM && p<RFIFOW(fd,2);j++){ + sscanf((char*)RFIFOP(fd,p), "%31c%n",auth_dat[i].account_reg2[j].str,&len); + auth_dat[i].account_reg2[j].str[len]='\0'; + p +=len+1; //+1 to skip the '\0' between strings. + sscanf((char*)RFIFOP(fd,p), "%255c%n",auth_dat[i].account_reg2[j].value,&len); + auth_dat[i].account_reg2[j].value[len]='\0'; + p +=len+1; + remove_control_chars(auth_dat[i].account_reg2[j].str); + remove_control_chars(auth_dat[i].account_reg2[j].value); } + auth_dat[i].account_reg2_num = j; + + // Sending information towards the other char-servers. + RFIFOW(fd,0) = 0x2729;// reusing read buffer + charif_sendallwos(fd, RFIFOP(fd,0), RFIFOW(fd,2)); + RFIFOSKIP(fd,RFIFOW(fd,2)); + + // Save + mmo_auth_sync(); } - RFIFOSKIP(fd,RFIFOW(fd,2)); + } break; case 0x272a: // Receiving of map-server via char-server an unban request if( RFIFOREST(fd) < 6 ) return 0; { - int acc = RFIFOL(fd,2); - for(i = 0; i < auth_num; i++) { - if (auth_dat[i].account_id == acc) { - if (auth_dat[i].ban_until_time != 0) { - auth_dat[i].ban_until_time = 0; - ShowNotice("Char-server '%s': UnBan request (account: %d, ip: %s).\n", server[id].name, acc, ip); - } else { - ShowNotice("Char-server '%s': Error of UnBan request (account: %d, no change for unban date, ip: %s).\n", - server[id].name, acc, ip); - } - break; - } - } - if (i == auth_num) - ShowNotice("Char-server '%s': Error of UnBan request (account: %d not found, ip: %s).\n", server[id].name, acc, ip); - + int account_id = RFIFOL(fd,2); RFIFOSKIP(fd,6); - return 0; + + ARR_FIND( 0, auth_num, i, auth_dat[i].account_id == account_id ); + if( i == auth_num ) + ShowNotice("Char-server '%s': Error of UnBan request (account: %d not found, ip: %s).\n", server[id].name, account_id, ip); + else + if( auth_dat[i].ban_until_time == 0 ) + ShowNotice("Char-server '%s': Error of UnBan request (account: %d, no change for unban date, ip: %s).\n", server[id].name, account_id, ip); + else + { + auth_dat[i].ban_until_time = 0; + ShowNotice("Char-server '%s': UnBan request (account: %d, ip: %s).\n", server[id].name, account_id, ip); + } } + break; case 0x272b: // Set account_id to online [Wizputer] if( RFIFOREST(fd) < 6 ) @@ -1705,30 +1707,41 @@ int parse_fromchar(int fd) if (RFIFOREST(fd) < 10) return 0; { - int account_id = RFIFOL(fd, 2); - int char_id = RFIFOL(fd, 6); - int p; + size_t off; + + int account_id = RFIFOL(fd,2); + int char_id = RFIFOL(fd,6); + RFIFOSKIP(fd,10); + + WFIFOHEAD(fd,10000); WFIFOW(fd,0) = 0x2729; WFIFOL(fd,4) = account_id; WFIFOL(fd,8) = char_id; WFIFOB(fd,12) = 1; //Type 1 for Account2 registry - for(i = 0; i < auth_num && auth_dat[i].account_id != account_id; i++); - if (i == auth_num) { + + ARR_FIND( 0, auth_num, i, auth_dat[i].account_id == account_id ); + if( i == auth_num ) + { //Account not found? Send at least empty data, map servers need a reply! WFIFOW(fd,2) = 13; WFIFOSET(fd,WFIFOW(fd,2)); break; } - for(p = 13, j = 0; j < auth_dat[i].account_reg2_num; j++) { - if (auth_dat[i].account_reg2[j].str[0]) { - p+= sprintf((char*)WFIFOP(fd,p), "%s", auth_dat[i].account_reg2[j].str)+1; //We add 1 to consider the '\0' in place. - p+= sprintf((char*)WFIFOP(fd,p), "%s", auth_dat[i].account_reg2[j].value)+1; + + for( off = 13, j = 0; j < auth_dat[i].account_reg2_num && off < 9000; j++ ) + { + 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; } } - WFIFOW(fd,2) = (uint16) p; - WFIFOSET(fd,WFIFOW(fd,2)); - RFIFOSKIP(fd,10); + if( off >= 9000 ) + ShowWarning("Too many account2 registries for AID %d. Some registries were not sent.\n", account_id); + + WFIFOW(fd,2) = (uint16)off; + WFIFOSET(fd,WFIFOW(fd,2)); } break; @@ -1834,6 +1847,7 @@ int parse_login(int fd) switch( command ) { + case 0x0200: // New alive packet: structure: 0x200 <account.userid>.24B. used to verify if client is always alive. if (RFIFOREST(fd) < 26) return 0; @@ -1879,18 +1893,16 @@ int parse_login(int fd) memset(&account, 0, sizeof(account)); account.version = RFIFOL(fd,2); - if( !account.version ) - account.version = 1; //Force some version... - memcpy(account.userid,RFIFOP(fd,6),NAME_LENGTH); account.userid[23] = '\0'; - remove_control_chars(account.userid); + 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); - memcpy(account.passwd, RFIFOP(fd,30), NAME_LENGTH); account.passwd[23] = '\0'; - remove_control_chars(account.passwd); + safestrncpy(account.passwd, (char*)RFIFOP(fd,30), NAME_LENGTH); remove_control_chars(account.passwd); } 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'; // binary data here + memcpy(account.passwd, RFIFOP(fd,30), 16); account.passwd[16] = '\0'; // raw binary data here! } + RFIFOSKIP(fd,packet_len); + account.passwdenc = (command == 0x01dd) ? PASSWORDENC : 0; result = mmo_auth(&account, fd); @@ -1986,13 +1998,12 @@ int parse_login(int fd) } WFIFOSET(fd,23); } - - RFIFOSKIP(fd,packet_len); } break; case 0x01db: // Sending request of the coding key case 0x791a: // Sending request of the coding key (administration packet) + RFIFOSKIP(fd,2); { struct login_session_data* ld; if( session[fd]->session_data ) @@ -2016,8 +2027,6 @@ int parse_login(int fd) WFIFOW(fd,2) = 4 + ld->md5keylen; memcpy(WFIFOP(fd,4), ld->md5key, ld->md5keylen); WFIFOSET(fd,WFIFOW(fd,2)); - - RFIFOSKIP(fd,2); } break; @@ -2025,17 +2034,22 @@ int parse_login(int fd) if (RFIFOREST(fd) < 86) return 0; { - char* server_name; + char server_name[20]; uint32 server_ip; uint16 server_port; + uint16 maintenance; + uint16 new_; memset(&account, 0, sizeof(account)); + account.passwdenc = 0; safestrncpy(account.userid, (char*)RFIFOP(fd,2), NAME_LENGTH); remove_control_chars(account.userid); safestrncpy(account.passwd, (char*)RFIFOP(fd,26), NAME_LENGTH); remove_control_chars(account.passwd); - account.passwdenc = 0; - server_name = (char*)RFIFOP(fd,60); server_name[20] = '\0'; remove_control_chars(server_name); - server_ip = ntohl(RFIFOL(fd, 54)); - server_port = ntohs(RFIFOW(fd, 58)); + server_ip = ntohl(RFIFOL(fd,54)); + server_port = ntohs(RFIFOW(fd,58)); + safestrncpy(server_name, (char*)RFIFOP(fd,60), 20); remove_control_chars(server_name); + maintenance = RFIFOW(fd,82); + new_ = RFIFOW(fd,84); + RFIFOSKIP(fd,86); ShowInfo("Connection request of the char-server '%s' @ %d.%d.%d.%d:%d (account: '%s', pass: '%s', ip: '%s')\n", server_name, CONVIP(server_ip), server_port, account.userid, account.passwd, ip); @@ -2043,25 +2057,26 @@ int parse_login(int fd) if( result == -1 && account.sex == 2 && account.account_id < MAX_SERVERS && server[account.account_id].fd == -1 ) { ShowStatus("Connection of the char-server '%s' accepted.\n", server_name); - memset(&server[account.account_id], 0, sizeof(struct mmo_char_server)); - server[account.account_id].ip = ntohl(RFIFOL(fd,54)); - server[account.account_id].port = ntohs(RFIFOW(fd,58)); safestrncpy(server[account.account_id].name, server_name, sizeof(server[account.account_id].name)); - server[account.account_id].users = 0; - server[account.account_id].maintenance = RFIFOW(fd,82); - server[account.account_id].new_ = RFIFOW(fd,84); server[account.account_id].fd = fd; + server[account.account_id].ip = server_ip; + server[account.account_id].port = server_port; + server[account.account_id].users = 0; + server[account.account_id].maintenance = maintenance; + server[account.account_id].new_ = new_; + + session[fd]->func_parse = parse_fromchar; + session[fd]->flag.server = 1; + realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); + // send connection success WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x2711; WFIFOB(fd,2) = 0; WFIFOSET(fd,3); - session[fd]->func_parse = parse_fromchar; - session[fd]->flag.server = 1; - realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); - - send_GM_accounts(fd); // send GM account to char-server + // send GM account to char-server + send_GM_accounts(fd); } else { @@ -2072,12 +2087,11 @@ int parse_login(int fd) WFIFOSET(fd,3); } } - - RFIFOSKIP(fd,86); - return 0; + return 0; // processing will continue elsewhere case 0x7530: // Server version information request ShowStatus("Sending server version information to ip: %s\n", ip); + RFIFOSKIP(fd,2); WFIFOHEAD(fd,10); WFIFOW(fd,0) = 0x7531; WFIFOB(fd,2) = ATHENA_MAJOR_VERSION; @@ -2088,15 +2102,8 @@ int parse_login(int fd) WFIFOB(fd,7) = ATHENA_SERVER_LOGIN; WFIFOW(fd,8) = ATHENA_MOD_VERSION; WFIFOSET(fd,10); - - RFIFOSKIP(fd,2); break; - case 0x7532: // Request to end connection - ShowStatus("End of connection (ip: %s)\n", ip); - set_eof(fd); - return 0; - case 0x7918: // Request for administation login if ((int)RFIFOREST(fd) < 4 || (int)RFIFOREST(fd) < ((RFIFOW(fd,2) == 0) ? 28 : 20)) return 0; @@ -2283,11 +2290,6 @@ int login_lan_config_read(const char *lancfgName) continue; } - remove_control_chars(w1); - remove_control_chars(w2); - remove_control_chars(w3); - remove_control_chars(w4); - if( strcmpi(w1, "subnet") == 0 ) { subnet[subnet_count].mask = str2ip(w2); @@ -2330,9 +2332,6 @@ int login_config_read(const char* cfgName) if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) < 2) continue; - remove_control_chars(w1); - remove_control_chars(w2); - if(!strcmpi(w1,"timestamp_format")) strncpy(timestamp_format, w2, 20); else if(!strcmpi(w1,"stdout_with_ansisequence")) diff --git a/src/login_sql/login.c b/src/login_sql/login.c index 45fc548c5..5a197ca43 100644 --- a/src/login_sql/login.c +++ b/src/login_sql/login.c @@ -468,8 +468,7 @@ int mmo_auth(struct mmo_account* account, int fd) } //Client Version check - if( login_config.check_client_version && account->version != 0 && - account->version != login_config.client_version_to_connect ) + if( login_config.check_client_version && account->version != login_config.client_version_to_connect ) return 5; len = strnlen(account->userid, NAME_LENGTH); @@ -639,6 +638,7 @@ int parse_fromchar(int fd) { case 0x2709: // request from map-server via char-server to reload GM accounts + RFIFOSKIP(fd,2); ShowStatus("Char-server '%s': Request to re-load GM configuration file (ip: %s).\n", server[id].name, ip); if( login_config.log_login ) { @@ -648,7 +648,6 @@ int parse_fromchar(int fd) read_gm_account(); // send GM accounts to all char-servers send_GM_accounts(-1); - RFIFOSKIP(fd,2); break; case 0x2712: // request from char-server to authenticate an account @@ -656,22 +655,40 @@ int parse_fromchar(int fd) return 0; { int account_id = RFIFOL(fd,2); + int login_id1 = RFIFOL(fd,6); + int login_id2 = RFIFOL(fd,10); + char sex = RFIFOB(fd,14); + uint32 ip_ = ntohl(RFIFOL(fd,15)); + RFIFOSKIP(fd,19); + ARR_FIND( 0, AUTH_FIFO_SIZE, i, - auth_fifo[i].account_id == RFIFOL(fd,2) && - auth_fifo[i].login_id1 == RFIFOL(fd,6) && - auth_fifo[i].login_id2 == RFIFOL(fd,10) && - auth_fifo[i].sex == RFIFOB(fd,14) && - auth_fifo[i].ip == ntohl(RFIFOL(fd,15)) && + auth_fifo[i].account_id == account_id && + auth_fifo[i].login_id1 == login_id1 && + auth_fifo[i].login_id2 == login_id2 && + auth_fifo[i].sex == sex && + auth_fifo[i].ip == ip_ && !auth_fifo[i].delflag ); - if( i < AUTH_FIFO_SIZE ) - auth_fifo[i].delflag = 1; - - if( i < AUTH_FIFO_SIZE && account_id > 0 ) - {// send ack + if( i == AUTH_FIFO_SIZE || account_id <= 0 ) + {// authentication not found + ShowStatus("Char-server '%s': authentication of the account %d REFUSED (ip: %s).\n", server[id].name, account_id, ip); + WFIFOHEAD(fd,51); + WFIFOW(fd,0) = 0x2713; + WFIFOL(fd,2) = account_id; + WFIFOB(fd,6) = 1; + // It is unnecessary to send email + // It is unnecessary to send validity date of the account + WFIFOSET(fd,51); + } + else + {// found uint32 connect_until_time; char email[40]; + // each auth entry can only be used once + auth_fifo[i].delflag = 1; + + // retrieve email and account expiration time if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `email`,`connect_until` FROM `%s` WHERE `%s`='%d'", login_db, login_db_account_id, account_id) ) Sql_ShowDebug(sql_handle); if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) @@ -692,6 +709,7 @@ int parse_fromchar(int fd) connect_until_time = 0; } + // send ack WFIFOHEAD(fd,51); WFIFOW(fd,0) = 0x2713; WFIFOL(fd,2) = account_id; @@ -700,48 +718,37 @@ int parse_fromchar(int fd) WFIFOL(fd,47) = connect_until_time; WFIFOSET(fd,51); } - else - {// authentication not found - ShowStatus("Char-server '%s': authentication of the account %d REFUSED (ip: %s).\n", server[id].name, account_id, ip); - WFIFOHEAD(fd,51); - WFIFOW(fd,0) = 0x2713; - WFIFOL(fd,2) = account_id; - WFIFOB(fd,6) = 1; - // It is unnecessary to send email - // It is unnecessary to send validity date of the account - WFIFOSET(fd,51); - } - - RFIFOSKIP(fd,19); } break; case 0x2714: if( RFIFOREST(fd) < 6 ) return 0; + { + int users = RFIFOL(fd,2); + RFIFOSKIP(fd,6); // how many users on world? (update) - if( server[id].users != RFIFOL(fd,2) ) + if( server[id].users != users ) { - ShowStatus("set users %s : %d\n", server[id].name, RFIFOL(fd,2)); + ShowStatus("set users %s : %d\n", server[id].name, users); - server[id].users = RFIFOL(fd,2); + server[id].users = users; if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `sstatus` SET `user` = '%d' WHERE `index` = '%d'", server[id].users, id) ) Sql_ShowDebug(sql_handle); } - RFIFOSKIP(fd,6); + } break; case 0x2716: // received an e-mail/limited time request, because a player comes back from a map-server to the char-server if( RFIFOREST(fd) < 6 ) return 0; { - int account_id; uint32 connect_until_time = 0; - char email[40]; + char email[40] = ""; - memset(email, 0, sizeof(email)); - account_id = RFIFOL(fd,2); + int account_id = RFIFOL(fd,2); + RFIFOSKIP(fd,6); if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `email`,`connect_until` FROM `%s` WHERE `%s`='%d'", login_db, login_db_account_id, account_id) ) Sql_ShowDebug(sql_handle); @@ -751,79 +758,70 @@ int parse_fromchar(int fd) size_t len; Sql_GetData(sql_handle, 0, &data, &len); - if( len > sizeof(email) ) - { -#if defined(DEBUG) - ShowDebug("parse_fromchar:0x2716: email is too long (len=%u,maxlen=%u)\n", len, sizeof(email)); -#endif - len = sizeof(email); - } - memcpy(email, data, len); + safestrncpy(email, data, sizeof(email)); Sql_GetData(sql_handle, 1, &data, NULL); connect_until_time = (uint32)strtoul(data, NULL, 10); Sql_FreeResult(sql_handle); } - //printf("parse_fromchar: E-mail/limited time request from '%s' server (concerned account: %d)\n", server[id].name, RFIFOL(fd,2)); + WFIFOHEAD(fd,50); WFIFOW(fd,0) = 0x2717; - WFIFOL(fd,2) = RFIFOL(fd,2); - memcpy(WFIFOP(fd, 6), email, 40); + WFIFOL(fd,2) = account_id; + safestrncpy((char*)WFIFOP(fd,6), email, 40); WFIFOL(fd,46) = connect_until_time; WFIFOSET(fd,50); - - RFIFOSKIP(fd,6); } break; case 0x2719: // ping request from charserver if( RFIFOREST(fd) < 2 ) return 0; + RFIFOSKIP(fd,2); WFIFOHEAD(fd,2); WFIFOW(fd,0) = 0x2718; WFIFOSET(fd,2); - - RFIFOSKIP(fd,2); break; - case 0x2720: // Request to become a GM (TXT only!) - if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) + case 0x2720: // Request to become a GM + if( RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2) ) return 0; - //oldacc = RFIFOL(fd,4); + { + 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)); + 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) = RFIFOL(fd,4); // oldacc; - WFIFOL(fd,6) = 0; // newacc; + WFIFOL(fd,2) = acc; + WFIFOL(fd,6) = 0; // level WFIFOSET(fd,10); - - RFIFOSKIP(fd, RFIFOW(fd, 2)); - return 0; + } + 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) return 0; { - int account_id; - char actual_email[40], new_email[40]; + char actual_email[40]; + char new_email[40]; + int account_id = RFIFOL(fd,2); + safestrncpy(actual_email, RFIFOP(fd,6), 40); + safestrncpy(new_email, RFIFOP(fd,46), 40); + RFIFOSKIP(fd, 86); - account_id = RFIFOL(fd,2); - memcpy(actual_email, RFIFOP(fd,6), 40); - memcpy(new_email, RFIFOP(fd,46), 40); if( e_mail_check(actual_email) == 0 ) - ShowWarning("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); + 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 ) - ShowWarning("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); + 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 ) - ShowWarning("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); + 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 if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `%s`,`email` FROM `%s` WHERE `%s` = '%d'", login_db_userid, login_db, login_db_account_id, account_id) ) Sql_ShowDebug(sql_handle); else if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) @@ -832,38 +830,21 @@ int parse_fromchar(int fd) size_t len; Sql_GetData(sql_handle, 1, &data, &len); - if( len > sizeof(actual_email) ) - { -#if defined(DEBUG) - ShowDebug("parse_fromchar:0x2722: email is too long (len=%u,maxlen=%u)\n", len, sizeof(actual_email)); -#endif - len = sizeof(actual_email); - } if( strncasecmp(data, actual_email, sizeof(actual_email)) == 0 ) { char esc_user_id[NAME_LENGTH*2+1]; char esc_new_email[sizeof(new_email)*2+1]; Sql_GetData(sql_handle, 0, &data, &len); - if( len > NAME_LENGTH ) - { -#if defined(DEBUG) - ShowDebug("parse_fromchar:0x2722: userid is too long (len=%u,maxlen=%u)\n", len, NAME_LENGTH); -#endif - len = NAME_LENGTH; - } Sql_EscapeStringLen(sql_handle, esc_user_id, data, len); Sql_EscapeStringLen(sql_handle, esc_new_email, new_email, strnlen(new_email, sizeof(new_email))); if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `email` = '%s' WHERE `%s` = '%d'", login_db, esc_new_email, login_db_account_id, account_id) ) Sql_ShowDebug(sql_handle); - ShowInfo("Char-server '%s': Modify an e-mail on an account (@email GM command) (account: %d ('%s'), new e-mail: '%s', ip: %s).\n", - server[id].name, account_id, esc_user_id, esc_new_email, ip); + ShowInfo("Char-server '%s': Modify an e-mail on an account (@email GM command) (account: %d ('%s'), new e-mail: '%s', ip: %s).\n", server[id].name, account_id, esc_user_id, esc_new_email, ip); } Sql_FreeResult(sql_handle); } - - RFIFOSKIP(fd, 86); } break; @@ -873,6 +854,8 @@ int parse_fromchar(int fd) { int account_id = RFIFOL(fd,2); int state = RFIFOL(fd,6); + RFIFOSKIP(fd,10); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `state` FROM `%s` WHERE `%s` = '%d'", login_db, login_db_account_id, account_id) ) Sql_ShowDebug(sql_handle); else if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) @@ -894,8 +877,6 @@ int parse_fromchar(int fd) if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `state` = '%d' WHERE `%s` = '%d'", login_db, state, login_db_account_id, account_id) ) Sql_ShowDebug(sql_handle); - - RFIFOSKIP(fd,10); } break; @@ -903,12 +884,19 @@ int parse_fromchar(int fd) if (RFIFOREST(fd) < 18) return 0; { - int account_id; struct tm *tmtime; time_t tmptime = 0; time_t timestamp = time(NULL); - account_id = RFIFOL(fd,2); + int account_id = RFIFOL(fd,2); + int year = (short)RFIFOW(fd,6); + int month = (short)RFIFOW(fd,8); + int mday = (short)RFIFOW(fd,10); + int hour = (short)RFIFOW(fd,12); + int min = (short)RFIFOW(fd,14); + int sec = (short)RFIFOW(fd,16); + RFIFOSKIP(fd,18); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `ban_until` FROM `%s` WHERE `%s` = '%d'", login_db, login_db_account_id, account_id) ) Sql_ShowDebug(sql_handle); else if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) @@ -921,12 +909,12 @@ int parse_fromchar(int fd) timestamp = tmptime; } tmtime = localtime(×tamp); - tmtime->tm_year = tmtime->tm_year + (int16)RFIFOW(fd,6); - tmtime->tm_mon = tmtime->tm_mon + (int16)RFIFOW(fd,8); - tmtime->tm_mday = tmtime->tm_mday + (int16)RFIFOW(fd,10); - tmtime->tm_hour = tmtime->tm_hour + (int16)RFIFOW(fd,12); - tmtime->tm_min = tmtime->tm_min + (int16)RFIFOW(fd,14); - tmtime->tm_sec = tmtime->tm_sec + (int16)RFIFOW(fd,16); + tmtime->tm_year = tmtime->tm_year + year; + tmtime->tm_mon = tmtime->tm_mon + month; + tmtime->tm_mday = tmtime->tm_mday + mday; + tmtime->tm_hour = tmtime->tm_hour + hour; + tmtime->tm_min = tmtime->tm_min + min; + tmtime->tm_sec = tmtime->tm_sec + sec; timestamp = mktime(tmtime); if( timestamp != (time_t)-1 ) { @@ -948,8 +936,6 @@ int parse_fromchar(int fd) Sql_ShowDebug(sql_handle); } } - - RFIFOSKIP(fd,18); } break; @@ -957,15 +943,15 @@ int parse_fromchar(int fd) if( RFIFOREST(fd) < 6 ) return 0; { - int account_id; - int sex; - uint8 buf[16]; + int account_id = RFIFOL(fd,2); + RFIFOSKIP(fd,6); - account_id = RFIFOL(fd,2); if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `sex` FROM `%s` WHERE `%s` = '%d'", login_db, login_db_account_id, account_id) ) Sql_ShowDebug(sql_handle); else if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) { + unsigned char buf[7]; + int sex; char* data; Sql_GetData(sql_handle, 0, &data, NULL); @@ -982,8 +968,6 @@ int parse_fromchar(int fd) WBUFB(buf,6) = sex; charif_sendallwos(-1, buf, 7); } - - RFIFOSKIP(fd,6); } break; @@ -1028,28 +1012,20 @@ int parse_fromchar(int fd) } SqlStmt_Free(stmt); - {// Send to char - //uint8* buf; - //CREATE(buf, uint8, RFIFOW(fd,2)); - //memcpy(WBUFP(buf,0), RFIFOP(fd,0), RFIFOW(fd,2)); - //WBUFW(buf,0)=0x2729; - //charif_sendallwos(fd, buf, WBUFW(buf,2)); - //aFree(buf); - - RFIFOW(fd,0) = 0x2729;// reusing read buffer - charif_sendallwos(fd, RFIFOP(fd,0), RFIFOW(fd,2)); - } + // Sending information towards the other char-servers. + RFIFOW(fd,0) = 0x2729;// reusing read buffer + charif_sendallwos(fd, RFIFOP(fd,0), RFIFOW(fd,2)); + RFIFOSKIP(fd,RFIFOW(fd,2)); } - RFIFOSKIP(fd,RFIFOW(fd,2)); break; case 0x272a: // Receiving of map-server via char-server an unban request if( RFIFOREST(fd) < 6 ) return 0; { - int account_id; + int account_id = RFIFOL(fd,2); + RFIFOSKIP(fd,6); - account_id = RFIFOL(fd,2); if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `ban_until` FROM `%s` WHERE `%s` = '%d'", login_db, login_db_account_id, account_id) ) Sql_ShowDebug(sql_handle); else if( Sql_NumRows(sql_handle) > 0 ) @@ -1057,10 +1033,8 @@ int parse_fromchar(int fd) if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `ban_until` = '0' WHERE `%s` = '%d'", login_db, login_db_account_id, account_id) ) Sql_ShowDebug(sql_handle); } - - RFIFOSKIP(fd,6); - return 0; } + break; case 0x272b: // Set account_id to online [Wizputer] if( RFIFOREST(fd) < 6 ) @@ -1104,18 +1078,21 @@ int parse_fromchar(int fd) if (RFIFOREST(fd) < 10) return 0; { - int account_id = RFIFOL(fd, 2); - int char_id = RFIFOL(fd, 6); size_t off; - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `str`,`value` FROM `%s` WHERE `type`='1' AND `account_id`='%d'", reg_db, account_id) ) - Sql_ShowDebug(sql_handle); + int account_id = RFIFOL(fd,2); + int char_id = RFIFOL(fd,6); + RFIFOSKIP(fd,10); WFIFOHEAD(fd,10000); WFIFOW(fd,0) = 0x2729; WFIFOL(fd,4) = account_id; WFIFOL(fd,8) = char_id; WFIFOB(fd,12) = 1; //Type 1 for Account2 registry + + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `str`,`value` FROM `%s` WHERE `type`='1' AND `account_id`='%d'", reg_db, account_id) ) + Sql_ShowDebug(sql_handle); + off = 13; while( SQL_SUCCESS == Sql_NextRow(sql_handle) && off < 9000 ) { @@ -1133,12 +1110,12 @@ int parse_fromchar(int fd) } } Sql_FreeResult(sql_handle); + if( off >= 9000 ) ShowWarning("Too many account2 registries for AID %d. Some registries were not sent.\n", account_id); + WFIFOW(fd,2) = (uint16)off; WFIFOSET(fd,WFIFOW(fd,2)); - - RFIFOSKIP(fd,10); } break; @@ -1235,6 +1212,7 @@ int parse_login(int fd) switch( command ) { + case 0x0200: // New alive packet: structure: 0x200 <account.userid>.24B. used to verify if client is always alive. if (RFIFOREST(fd) < 26) return 0; @@ -1280,10 +1258,14 @@ int parse_login(int fd) memset(&account, 0, sizeof(account)); account.version = RFIFOL(fd,2); - if( !account.version ) - account.version = 1; //Force some version... safestrncpy(account.userid, (char*)RFIFOP(fd,6), NAME_LENGTH);//## does it have to be nul-terminated? - safestrncpy(account.passwd, (char*)RFIFOP(fd,30), NAME_LENGTH);//## does it have to be nul-terminated? + if (command != 0x01dd) { + safestrncpy(account.passwd, (char*)RFIFOP(fd,30), NAME_LENGTH);//## does it have to be nul-terminated? + } else { + memcpy(account.passwd, RFIFOP(fd,30), 16); account.passwd[16] = '\0'; // raw binary data here! + } + RFIFOSKIP(fd,packet_len); + account.passwdenc = (command == 0x01dd) ? PASSWORDENC : 0; Sql_EscapeStringLen(sql_handle, esc_userid, account.userid, strlen(account.userid)); @@ -1444,12 +1426,11 @@ int parse_login(int fd) } WFIFOSET(fd,23); } - - RFIFOSKIP(fd,packet_len); } break; case 0x01db: // Sending request of the coding key + RFIFOSKIP(fd,2); { struct login_session_data* ld; if( session[fd]->session_data ) @@ -1473,8 +1454,6 @@ int parse_login(int fd) WFIFOW(fd,2) = 4 + ld->md5keylen; memcpy(WFIFOP(fd,4), ld->md5key, ld->md5keylen); WFIFOSET(fd,WFIFOW(fd,2)); - - RFIFOSKIP(fd,2); } break; @@ -1482,23 +1461,28 @@ int parse_login(int fd) if (RFIFOREST(fd) < 86) return 0; { + char server_name[20]; char esc_server_name[20*2+1]; - char* server_name; uint32 server_ip; uint16 server_port; + uint16 maintenance; + uint16 new_; memset(&account, 0, sizeof(account)); + account.passwdenc = 0; safestrncpy(account.userid, (char*)RFIFOP(fd,2), NAME_LENGTH); safestrncpy(account.passwd, (char*)RFIFOP(fd,26), NAME_LENGTH); - account.passwdenc = 0; server_ip = ntohl(RFIFOL(fd,54)); server_port = ntohs(RFIFOW(fd,58)); - server_name = (char*)RFIFOP(fd,60); + safestrncpy(server_name, (char*)RFIFOP(fd,60), 20); + maintenance = RFIFOW(fd,82); + new_ = RFIFOW(fd,84); + RFIFOSKIP(fd,86); Sql_EscapeStringLen(sql_handle, esc_server_name, server_name, strnlen(server_name, 20)); Sql_EscapeStringLen(sql_handle, esc_userid, account.userid, strnlen(account.userid, NAME_LENGTH)); - ShowInfo("Connection request of the char-server '%s' @ %d.%d.%d.%d:%d (account: '%s', pass: '%s', ip: '%s')\n", esc_server_name, CONVIP(server_ip), server_port, account.userid, account.passwd, ip); + ShowInfo("Connection request of the char-server '%s' @ %d.%d.%d.%d:%d (account: '%s', pass: '%s', ip: '%s')\n", server_name, CONVIP(server_ip), server_port, account.userid, account.passwd, ip); if( login_config.log_login && SQL_ERROR == Sql_Query(sql_handle, "INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', '%s@%s','100', 'charserver - %s@%u.%u.%u.%u:%d')", loginlog_db, ipl, esc_userid, esc_server_name, esc_server_name, CONVIP(server_ip), server_port) ) @@ -1507,44 +1491,45 @@ int parse_login(int fd) result = mmo_auth(&account, fd); if( result == -1 && account.sex == 2 && account.account_id < MAX_SERVERS && server[account.account_id].fd == -1 ) { - ShowStatus("Connection of the char-server '%s' accepted.\n", esc_server_name); - memset(&server[account.account_id], 0, sizeof(struct mmo_char_server)); - server[account.account_id].ip = ntohl(RFIFOL(fd,54)); - server[account.account_id].port = ntohs(RFIFOW(fd,58)); + ShowStatus("Connection of the char-server '%s' accepted.\n", server_name); safestrncpy(server[account.account_id].name, server_name, sizeof(server[account.account_id].name)); - server[account.account_id].users = 0; - server[account.account_id].maintenance = RFIFOW(fd,82); - server[account.account_id].new_ = RFIFOW(fd,84); server[account.account_id].fd = fd; + server[account.account_id].ip = server_ip; + server[account.account_id].port = server_port; + server[account.account_id].users = 0; + server[account.account_id].maintenance = maintenance; + server[account.account_id].new_ = new_; + + session[fd]->func_parse = parse_fromchar; + session[fd]->flag.server = 1; + realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); + // send connection success WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x2711; WFIFOB(fd,2) = 0; WFIFOSET(fd,3); - session[fd]->func_parse = parse_fromchar; - session[fd]->flag.server = 1; - realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); - - send_GM_accounts(fd); // send GM account to char-server + // send GM account to char-server + send_GM_accounts(fd); if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `sstatus`(`index`,`name`,`user`) VALUES ( '%d', '%s', '%d')", account.account_id, esc_server_name, 0) ) Sql_ShowDebug(sql_handle); } else { - ShowNotice("Connection of the char-server '%s' REFUSED.\n", esc_server_name); + ShowNotice("Connection of the char-server '%s' REFUSED.\n", server_name); WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x2711; WFIFOB(fd,2) = 3; WFIFOSET(fd,3); } } - RFIFOSKIP(fd,86); - return 0; + return 0; // processing will continue elsewhere case 0x7530: // Server version information request ShowStatus("Sending server version information to ip: %s\n", ip); + RFIFOSKIP(fd,2); WFIFOHEAD(fd,10); WFIFOW(fd,0) = 0x7531; WFIFOB(fd,2) = ATHENA_MAJOR_VERSION; @@ -1555,13 +1540,6 @@ int parse_login(int fd) WFIFOB(fd,7) = ATHENA_SERVER_LOGIN; WFIFOW(fd,8) = ATHENA_MOD_VERSION; WFIFOSET(fd,10); - - RFIFOSKIP(fd,2); - break; - - case 0x7532: // Request to end connection - ShowStatus("End of connection (ip: %s)\n", ip); - set_eof(fd); break; default: @@ -1654,11 +1632,6 @@ int login_lan_config_read(const char *lancfgName) continue; } - remove_control_chars(w1); - remove_control_chars(w2); - remove_control_chars(w3); - remove_control_chars(w4); - if( strcmpi(w1, "subnet") == 0 ) { subnet[subnet_count].mask = str2ip(w2); @@ -1712,9 +1685,6 @@ int login_config_read(const char* cfgName) if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) < 2) continue; - remove_control_chars(w1); - remove_control_chars(w2); - if(!strcmpi(w1,"timestamp_format")) strncpy(timestamp_format, w2, 20); else if(!strcmpi(w1,"stdout_with_ansisequence")) diff --git a/src/map/itemdb.c b/src/map/itemdb.c index b27074866..fcd6c804d 100644 --- a/src/map/itemdb.c +++ b/src/map/itemdb.c @@ -161,13 +161,9 @@ int itemdb_group_bonus(struct map_session_data* sd, int itemid) for (i=0; i < MAX_ITEMGROUP; i++) { if (!sd->itemgrouphealrate[i]) continue; - for (j=0; j < itemgroup_db[i].qty; j++) { - if (itemgroup_db[i].nameid[j] == itemid) - { - bonus += sd->itemgrouphealrate[i]; - break; - } - } + ARR_FIND( 0, itemgroup_db[i].qty, j, itemgroup_db[i].nameid[j] == itemid ); + if( j < itemgroup_db[i].qty ) + bonus += sd->itemgrouphealrate[i]; } return bonus; } diff --git a/src/map/itemdb.h b/src/map/itemdb.h index 507478196..865ceaf9d 100644 --- a/src/map/itemdb.h +++ b/src/map/itemdb.h @@ -36,6 +36,7 @@ enum item_types { //The only item group required by the code to be known. See const.txt for the full list. #define IG_FINDINGORE 6 +#define IG_POTION 37 //The max. item group count (increase this when needed). #define MAX_ITEMGROUP 40 diff --git a/src/map/skill.c b/src/map/skill.c index 33368da97..fe2fff2a5 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -4082,10 +4082,11 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in sp = sp * (100 + pc_checkskill(dstsd,MG_SRECOVERY)*10) / 100; } } - if (sd->itemgrouphealrate[37]>0) + + if (sd->itemgrouphealrate[IG_POTION]>0) { - hp += hp * sd->itemgrouphealrate[37] / 100; - sp += sp * sd->itemgrouphealrate[37] / 100; + hp += hp * sd->itemgrouphealrate[IG_POTION] / 100; + sp += sp * sd->itemgrouphealrate[IG_POTION] / 100; } if ((i = pc_skillheal_bonus(sd, skillid))) |