diff options
Diffstat (limited to 'src/login/login.c')
-rw-r--r-- | src/login/login.c | 458 |
1 files changed, 209 insertions, 249 deletions
diff --git a/src/login/login.c b/src/login/login.c index e8f136ba9..c8e219602 100644 --- a/src/login/login.c +++ b/src/login/login.c @@ -2,6 +2,18 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams +#define HERCULES_CORE + +#include "login.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "account.h" +#include "ipban.h" +#include "loginlog.h" +#include "../common/HPM.h" #include "../common/core.h" #include "../common/db.h" #include "../common/malloc.h" @@ -11,44 +23,20 @@ #include "../common/socket.h" #include "../common/strlib.h" #include "../common/timer.h" -#include "account.h" -#include "ipban.h" -#include "login.h" -#include "loginlog.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> +#include "../common/utils.h" struct Login_Config login_config; int login_fd; // login server socket struct mmo_char_server server[MAX_SERVERS]; // char server data -// Account engines available -static struct{ +static struct account_engine { AccountDB* (*constructor)(void); AccountDB* db; -} account_engines[] = { - {account_db_sql, NULL}, -#ifdef ACCOUNTDB_ENGINE_0 - {ACCOUNTDB_CONSTRUCTOR(ACCOUNTDB_ENGINE_0), NULL}, -#endif -#ifdef ACCOUNTDB_ENGINE_1 - {ACCOUNTDB_CONSTRUCTOR(ACCOUNTDB_ENGINE_1), NULL}, -#endif -#ifdef ACCOUNTDB_ENGINE_2 - {ACCOUNTDB_CONSTRUCTOR(ACCOUNTDB_ENGINE_2), NULL}, -#endif -#ifdef ACCOUNTDB_ENGINE_3 - {ACCOUNTDB_CONSTRUCTOR(ACCOUNTDB_ENGINE_3), NULL}, -#endif -#ifdef ACCOUNTDB_ENGINE_4 - {ACCOUNTDB_CONSTRUCTOR(ACCOUNTDB_ENGINE_4), NULL}, -#endif - // end of structure - {NULL, NULL} +} account_engine[] = { + {account_db_sql, NULL} }; + // account database AccountDB* accounts = NULL; @@ -81,6 +69,8 @@ struct auth_node { char sex; uint32 version; uint8 clienttype; + int group_id; + time_t expiration_time; }; static DBMap* auth_db; // int account_id -> struct auth_node* @@ -97,7 +87,7 @@ struct online_login_data { }; static DBMap* online_db; // int account_id -> struct online_login_data* -static int waiting_disconnect_timer(int tid, unsigned int tick, int id, intptr_t data); +static int waiting_disconnect_timer(int tid, int64 tick, int id, intptr_t data); /** * @see DBCreateData @@ -119,7 +109,7 @@ struct online_login_data* add_online_user(int char_server, int account_id) p->char_server = char_server; if( p->waiting_disconnect != INVALID_TIMER ) { - iTimer->delete_timer(p->waiting_disconnect, waiting_disconnect_timer); + timer->delete(p->waiting_disconnect, waiting_disconnect_timer); p->waiting_disconnect = INVALID_TIMER; } return p; @@ -132,13 +122,12 @@ void remove_online_user(int account_id) if( p == NULL ) return; if( p->waiting_disconnect != INVALID_TIMER ) - iTimer->delete_timer(p->waiting_disconnect, waiting_disconnect_timer); + timer->delete(p->waiting_disconnect, waiting_disconnect_timer); idb_remove(online_db, account_id); } -static int waiting_disconnect_timer(int tid, unsigned int tick, int id, intptr_t data) -{ +static int waiting_disconnect_timer(int tid, int64 tick, int id, intptr_t data) { struct online_login_data* p = (struct online_login_data*)idb_get(online_db, id); if( p != NULL && p->waiting_disconnect == tid && p->account_id == id ) { @@ -155,17 +144,17 @@ static int waiting_disconnect_timer(int tid, unsigned int tick, int id, intptr_t static int online_db_setoffline(DBKey key, DBData *data, va_list ap) { struct online_login_data* p = DB->data2ptr(data); - int server = va_arg(ap, int); - if( server == -1 ) + int server_id = va_arg(ap, int); + if( server_id == -1 ) { p->char_server = -1; if( p->waiting_disconnect != INVALID_TIMER ) { - iTimer->delete_timer(p->waiting_disconnect, waiting_disconnect_timer); + timer->delete(p->waiting_disconnect, waiting_disconnect_timer); p->waiting_disconnect = INVALID_TIMER; } } - else if( p->char_server == server ) + else if( p->char_server == server_id ) p->char_server = -2; //Char server disconnected. return 0; } @@ -181,11 +170,10 @@ static int online_data_cleanup_sub(DBKey key, DBData *data, va_list ap) return 0; } -static int online_data_cleanup(int tid, unsigned int tick, int id, intptr_t data) -{ +static int online_data_cleanup(int tid, int64 tick, int id, intptr_t data) { online_db->foreach(online_db, online_data_cleanup_sub); return 0; -} +} //-------------------------------------------------------------------- @@ -250,8 +238,7 @@ void chrif_on_disconnect(int id) //----------------------------------------------------- // periodic ip address synchronization //----------------------------------------------------- -static int sync_ip_addresses(int tid, unsigned int tick, int id, intptr_t data) -{ +static int sync_ip_addresses(int tid, int64 tick, int id, intptr_t data) { uint8 buf[2]; ShowInfo("IP Sync in progress...\n"); WBUFW(buf,0) = 0x2735; @@ -289,18 +276,6 @@ bool check_password(const char* md5key, int passwdenc, const char* passwd, const } } - -//----------------------------------------------------- -// custom timestamp formatting (from eApp) -//----------------------------------------------------- -const char* timestamp2string(char* str, size_t size, time_t timestamp, const char* format) -{ - size_t len = strftime(str, size, format, localtime(×tamp)); - memset(str + len, '\0', size - len); - return str; -} - - //-------------------------------------------- // Test to know if an IP come from LAN or WAN. //-------------------------------------------- @@ -312,7 +287,7 @@ int lan_subnetcheck(uint32 ip) } //---------------------------------- -// Reading Lan Support configuration +// Reading LAN Support configuration //---------------------------------- int login_lan_config_read(const char *lancfgName) { @@ -331,8 +306,7 @@ int login_lan_config_read(const char *lancfgName) if ((line[0] == '/' && line[1] == '/') || line[0] == '\n' || line[1] == '\n') continue; - if(sscanf(line,"%[^:]: %[^:]:%[^:]:%[^\r\n]", w1, w2, w3, w4) != 4) - { + if (sscanf(line, "%63[^:]: %63[^:]:%63[^:]:%63[^\r\n]", w1, w2, w3, w4) != 4) { ShowWarning("Error syntax of configuration file %s in line %d.\n", lancfgName, line_num); continue; } @@ -389,12 +363,17 @@ int parse_fromchar(int fd) ipl = server[id].ip; ip2str(ipl, ip); - while( RFIFOREST(fd) >= 2 ) - { + while( RFIFOREST(fd) >= 2 ) { uint16 command = RFIFOW(fd,0); - switch( command ) - { + if( HPM->packetsc[hpParse_FromChar] ) { + if( (j = HPM->parse_packets(fd,hpParse_FromChar)) ) { + if( j == 1 ) continue; + if( j == 2 ) return 0; + } + } + + switch( command ) { case 0x2712: // request from char-server to authenticate an account if( RFIFOREST(fd) < 23 ) @@ -422,7 +401,7 @@ int parse_fromchar(int fd) //ShowStatus("Char-server '%s': authentication of the account %d accepted (ip: %s).\n", server[id].name, account_id, ip); // send ack - WFIFOHEAD(fd,25); + WFIFOHEAD(fd,33); WFIFOW(fd,0) = 0x2713; WFIFOL(fd,2) = account_id; WFIFOL(fd,6) = login_id1; @@ -432,7 +411,9 @@ int parse_fromchar(int fd) WFIFOL(fd,16) = request_id; WFIFOL(fd,20) = node->version; WFIFOB(fd,24) = node->clienttype; - WFIFOSET(fd,25); + WFIFOL(fd,25) = node->group_id; + WFIFOL(fd,29) = (unsigned int)node->expiration_time; + WFIFOSET(fd,33); // each auth entry can only be used once idb_remove(auth_db, account_id); @@ -440,7 +421,7 @@ int parse_fromchar(int fd) 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,25); + WFIFOHEAD(fd,33); WFIFOW(fd,0) = 0x2713; WFIFOL(fd,2) = account_id; WFIFOL(fd,6) = login_id1; @@ -450,7 +431,9 @@ int parse_fromchar(int fd) WFIFOL(fd,16) = request_id; WFIFOL(fd,20) = 0; WFIFOB(fd,24) = 0; - WFIFOSET(fd,25); + WFIFOL(fd,25) = 0; + WFIFOL(fd,29) = 0; + WFIFOSET(fd,33); } } break; @@ -634,10 +617,9 @@ int parse_fromchar(int fd) int sec = (short)RFIFOW(fd,16); RFIFOSKIP(fd,18); - if( !accounts->load_num(accounts, &acc, account_id) ) + if (!accounts->load_num(accounts, &acc, account_id)) { ShowNotice("Char-server '%s': Error of ban request (account: %d not found, ip: %s).\n", server[id].name, account_id, ip); - else - { + } else { time_t timestamp; struct tm *tmtime; if (acc.unban_time == 0 || acc.unban_time < time(NULL)) @@ -645,24 +627,23 @@ int parse_fromchar(int fd) else timestamp = acc.unban_time; // add to existing ban tmtime = localtime(×tamp); - 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; + tmtime->tm_year += year; + tmtime->tm_mon += month; + tmtime->tm_mday += mday; + tmtime->tm_hour += hour; + tmtime->tm_min += min; + tmtime->tm_sec += sec; timestamp = mktime(tmtime); - if (timestamp == -1) + if (timestamp == -1) { 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 ) + } 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 - { + } else { uint8 buf[11]; char tmpstr[24]; timestamp2string(tmpstr, sizeof(tmpstr), timestamp, login_config.date_format); - 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); + ShowNotice("Char-server '%s': Ban request (account: %d, new final date of banishment: %ld (%s), ip: %s).\n", + server[id].name, account_id, (long)timestamp, tmpstr, ip); acc.unban_time = timestamp; @@ -723,30 +704,8 @@ int parse_fromchar(int fd) if( !accounts->load_num(accounts, &acc, account_id) ) ShowStatus("Char-server '%s': receiving (from the char-server) of account_reg2 (account: %d not found, ip: %s).\n", server[id].name, account_id, ip); - else - { - int len; - int p; - ShowNotice("char-server '%s': receiving (from the char-server) of account_reg2 (account: %d, ip: %s).\n", server[id].name, account_id, ip); - for( j = 0, p = 13; j < ACCOUNT_REG2_NUM && p < RFIFOW(fd,2); ++j ) - { - sscanf((char*)RFIFOP(fd,p), "%31c%n", acc.account_reg2[j].str, &len); - acc.account_reg2[j].str[len]='\0'; - p +=len+1; //+1 to skip the '\0' between strings. - sscanf((char*)RFIFOP(fd,p), "%255c%n", acc.account_reg2[j].value, &len); - acc.account_reg2[j].value[len]='\0'; - p +=len+1; - remove_control_chars(acc.account_reg2[j].str); - remove_control_chars(acc.account_reg2[j].value); - } - acc.account_reg2_num = j; - - // Save - accounts->save(accounts, &acc); - - // Sending information towards the other char-servers. - RFIFOW(fd,0) = 0x2729;// reusing read buffer - charif_sendallwos(fd, RFIFOP(fd,0), RFIFOW(fd,2)); + else { + mmo_save_accreg2(accounts,fd,account_id,RFIFOL(fd, 8)); } RFIFOSKIP(fd,RFIFOW(fd,2)); } @@ -762,13 +721,13 @@ int parse_fromchar(int fd) RFIFOSKIP(fd,6); if( !accounts->load_num(accounts, &acc, account_id) ) - ShowNotice("Char-server '%s': Error of UnBan request (account: %d not found, ip: %s).\n", server[id].name, account_id, ip); + ShowNotice("Char-server '%s': Error of Unban request (account: %d not found, ip: %s).\n", server[id].name, account_id, ip); else if( acc.unban_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); + 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 { - ShowNotice("Char-server '%s': UnBan request (account: %d, ip: %s).\n", server[id].name, account_id, ip); + ShowNotice("Char-server '%s': Unban request (account: %d, ip: %s).\n", server[id].name, account_id, ip); acc.unban_time = 0; accounts->save(accounts, &acc); } @@ -804,7 +763,7 @@ int parse_fromchar(int fd) p->char_server = id; if (p->waiting_disconnect != INVALID_TIMER) { - iTimer->delete_timer(p->waiting_disconnect, waiting_disconnect_timer); + timer->delete(p->waiting_disconnect, waiting_disconnect_timer); p->waiting_disconnect = INVALID_TIMER; } } @@ -816,34 +775,11 @@ int parse_fromchar(int fd) if (RFIFOREST(fd) < 10) return 0; { - struct mmo_account acc; - size_t off; - int account_id = RFIFOL(fd,2); int char_id = RFIFOL(fd,6); RFIFOSKIP(fd,10); - WFIFOHEAD(fd,ACCOUNT_REG2_NUM*sizeof(struct global_reg)); - WFIFOW(fd,0) = 0x2729; - WFIFOL(fd,4) = account_id; - WFIFOL(fd,8) = char_id; - WFIFOB(fd,12) = 1; //Type 1 for Account2 registry - - off = 13; - if( accounts->load_num(accounts, &acc, account_id) ) - { - for( j = 0; j < acc.account_reg2_num; j++ ) - { - if( acc.account_reg2[j].str[0] != '\0' ) - { - off += sprintf((char*)WFIFOP(fd,off), "%s", acc.account_reg2[j].str)+1; //We add 1 to consider the '\0' in place. - off += sprintf((char*)WFIFOP(fd,off), "%s", acc.account_reg2[j].value)+1; - } - } - } - - WFIFOW(fd,2) = (uint16)off; - WFIFOSET(fd,WFIFOW(fd,2)); + mmo_send_accreg2(accounts,fd,account_id,char_id); } break; @@ -896,6 +832,48 @@ int parse_fromchar(int fd) } break; + case 0x2740: // Accinfo request forwarded by charserver on mapserver's account + if( RFIFOREST(fd) < 22 ) + return 0; + else { + struct mmo_account acc; + int account_id = RFIFOL(fd, 2), u_fd = RFIFOL(fd, 6), u_aid = RFIFOL(fd, 10), u_group = RFIFOL(fd, 14), map_fd = RFIFOL(fd, 18); + if (accounts->load_num(accounts, &acc, account_id)) { + WFIFOHEAD(fd,183); + WFIFOW(fd,0) = 0x2737; + safestrncpy((char*)WFIFOP(fd,2), acc.userid, NAME_LENGTH); + if (u_group >= acc.group_id) + safestrncpy((char*)WFIFOP(fd,26), acc.pass, 33); + else + memset(WFIFOP(fd,26), '\0', 33); + safestrncpy((char*)WFIFOP(fd,59), acc.email, 40); + safestrncpy((char*)WFIFOP(fd,99), acc.last_ip, 16); + WFIFOL(fd,115) = acc.group_id; + safestrncpy((char*)WFIFOP(fd,119), acc.lastlogin, 24); + WFIFOL(fd,143) = acc.logincount; + WFIFOL(fd,147) = acc.state; + if (u_group >= acc.group_id) + safestrncpy((char*)WFIFOP(fd,151), acc.pincode, 5); + else + memset(WFIFOP(fd,151), '\0', 5); + safestrncpy((char*)WFIFOP(fd,156), acc.birthdate, 11); + WFIFOL(fd,167) = map_fd; + WFIFOL(fd,171) = u_fd; + WFIFOL(fd,175) = u_aid; + WFIFOL(fd,179) = account_id; + WFIFOSET(fd,183); + } else { + WFIFOHEAD(fd,18); + WFIFOW(fd,0) = 0x2736; + WFIFOL(fd,2) = map_fd; + WFIFOL(fd,6) = u_fd; + WFIFOL(fd,10) = u_aid; + WFIFOL(fd,14) = account_id; + WFIFOSET(fd,18); + } + RFIFOSKIP(fd,22); + } + break; default: ShowError("parse_fromchar: Unknown packet 0x%x from a char-server! Disconnecting!\n", command); set_eof(fd); @@ -912,13 +890,13 @@ int parse_fromchar(int fd) //------------------------------------- int mmo_auth_new(const char* userid, const char* pass, const char sex, const char* last_ip) { static int num_regs = 0; // registration counter - static unsigned int new_reg_tick = 0; - unsigned int tick = iTimer->gettick(); + static int64 new_reg_tick = 0; + int64 tick = timer->gettick(); struct mmo_account acc; //Account Registration Flood Protection by [Kevin] if( new_reg_tick == 0 ) - new_reg_tick = iTimer->gettick(); + new_reg_tick = timer->gettick(); if( DIFF_TICK(tick, new_reg_tick) < 0 && num_regs >= allowed_regs ) { ShowNotice("Account registration denied (registration limit exceeded)\n"); return 3; @@ -933,7 +911,7 @@ int mmo_auth_new(const char* userid, const char* pass, const char sex, const cha // check if the account doesn't exist already if( accounts->load_str(accounts, &acc, userid) ) { - ShowNotice("Attempt of creation of an already existant account (account: %s_%c, pass: %s, received pass: %s)\n", userid, sex, acc.pass, pass); + ShowNotice("Attempt of creation of an already existing account (account: %s_%c, pass: %s, received pass: %s)\n", userid, sex, acc.pass, pass); return 1; // 1 = Incorrect Password } @@ -970,7 +948,7 @@ int mmo_auth_new(const char* userid, const char* pass, const char sex, const cha //----------------------------------------------------- int mmo_auth(struct login_session_data* sd, bool isServer) { struct mmo_account acc; - int len; + size_t len; char ip[16]; ip2str(session[sd->fd]->client_addr, ip); @@ -1028,11 +1006,6 @@ int mmo_auth(struct login_session_data* sd, bool isServer) { return 1; // 1 = Incorrect Password } - if( acc.expiration_time != 0 && acc.expiration_time < time(NULL) ) { - ShowNotice("Connection refused (account: %s, pass: %s, expired ID, ip: %s)\n", sd->userid, sd->passwd, ip); - return 2; // 2 = This ID is expired - } - if( acc.unban_time != 0 && acc.unban_time > time(NULL) ) { char tmpstr[24]; timestamp2string(tmpstr, sizeof(tmpstr), acc.unban_time, login_config.date_format); @@ -1046,31 +1019,34 @@ int mmo_auth(struct login_session_data* sd, bool isServer) { } if( login_config.client_hash_check && !isServer ) { - struct client_hash_node *node = login_config.client_hash_nodes; + struct client_hash_node *node = NULL; bool match = false; - if( !sd->has_client_hash ) { - ShowNotice("Client doesn't sent client hash (account: %s, pass: %s, ip: %s)\n", sd->userid, sd->passwd, acc.state, ip); - return 5; - } - - while( node ) { - if( node->group_id <= acc.group_id && memcmp(node->hash, sd->client_hash, 16) == 0 ) { + for( node = login_config.client_hash_nodes; node; node = node->next ) { + if( acc.group_id < node->group_id ) + continue; + if( *node->hash == '\0' // Allowed to login without hash + || (sd->has_client_hash && memcmp(node->hash, sd->client_hash, 16) == 0 ) // Correct hash + ) { match = true; break; } - - node = node->next; } if( !match ) { char smd5[33]; int i; + if( !sd->has_client_hash ) { + ShowNotice("Client didn't send client hash (account: %s, pass: %s, ip: %s)\n", sd->userid, sd->passwd, ip); + return 5; + } + for( i = 0; i < 16; i++ ) sprintf(&smd5[i * 2], "%02x", sd->client_hash[i]); + smd5[32] = '\0'; - ShowNotice("Invalid client hash (account: %s, pass: %s, sent md5: %d, ip: %s)\n", sd->userid, sd->passwd, smd5, ip); + ShowNotice("Invalid client hash (account: %s, pass: %s, sent md5: %s, ip: %s)\n", sd->userid, sd->passwd, smd5, ip); return 5; } } @@ -1084,6 +1060,7 @@ int mmo_auth(struct login_session_data* sd, bool isServer) { safestrncpy(sd->lastlogin, acc.lastlogin, sizeof(sd->lastlogin)); sd->sex = acc.sex; sd->group_id = (uint8)acc.group_id; + sd->expiration_time = acc.expiration_time; // update account data timestamp2string(acc.lastlogin, sizeof(acc.lastlogin), time(NULL), "%Y-%m-%d %H:%M:%S"); @@ -1127,12 +1104,12 @@ void login_auth_ok(struct login_session_data* sd) WFIFOSET(fd,3); return; } else if( login_config.min_group_id_to_connect >= 0 && login_config.group_id_to_connect == -1 && sd->group_id < login_config.min_group_id_to_connect ) { - ShowStatus("Connection refused: the minium group id required for connection is %d (account: %s, group: %d).\n", login_config.min_group_id_to_connect, sd->userid, sd->group_id); + ShowStatus("Connection refused: the minimum group id required for connection is %d (account: %s, group: %d).\n", login_config.min_group_id_to_connect, sd->userid, sd->group_id); WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x81; WFIFOB(fd,2) = 1; // 01 = Server closed WFIFOSET(fd,3); - return; + return; } server_num = 0; @@ -1162,7 +1139,7 @@ void login_auth_ok(struct login_session_data* sd) WBUFL(buf,2) = sd->account_id; charif_sendallwos(-1, buf, 6); if( data->waiting_disconnect == INVALID_TIMER ) - data->waiting_disconnect = iTimer->add_timer(iTimer->gettick()+AUTH_TIMEOUT, waiting_disconnect_timer, sd->account_id, 0); + data->waiting_disconnect = timer->add(timer->gettick()+AUTH_TIMEOUT, waiting_disconnect_timer, sd->account_id, 0); WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x81; @@ -1205,7 +1182,12 @@ void login_auth_ok(struct login_session_data* sd) WFIFOW(fd,47+n*32+4) = ntows(htons(server[i].port)); // [!] LE byte order here [!] memcpy(WFIFOP(fd,47+n*32+6), server[i].name, 20); WFIFOW(fd,47+n*32+26) = server[i].users; - WFIFOW(fd,47+n*32+28) = server[i].type; + + if( server[i].type == CST_PAYING && sd->expiration_time > time(NULL) ) + WFIFOW(fd,47+n*32+28) = CST_NORMAL; + else + WFIFOW(fd,47+n*32+28) = server[i].type; + WFIFOW(fd,47+n*32+30) = server[i].new_; n++; } @@ -1220,6 +1202,8 @@ void login_auth_ok(struct login_session_data* sd) node->ip = ip; node->version = sd->version; node->clienttype = sd->clienttype; + node->group_id = sd->group_id; + node->expiration_time = sd->expiration_time; idb_put(auth_db, sd->account_id, node); { @@ -1229,7 +1213,7 @@ void login_auth_ok(struct login_session_data* sd) data = add_online_user(-1, sd->account_id); // schedule deletion of this node - data->waiting_disconnect = iTimer->add_timer(iTimer->gettick()+AUTH_TIMEOUT, waiting_disconnect_timer, sd->account_id, 0); + data->waiting_disconnect = timer->add(timer->gettick()+AUTH_TIMEOUT, waiting_disconnect_timer, sd->account_id, 0); } } @@ -1325,7 +1309,7 @@ int parse_login(int fd) // Perform ip-ban check if( login_config.ipban && ipban_check(ipl) ) { - ShowStatus("Connection refused: IP isn't authorised (deny/allow, ip: %s).\n", ip); + ShowStatus("Connection refused: IP isn't authorized (deny/allow, ip: %s).\n", ip); login_log(ipl, "unknown", -3, "ip banned"); WFIFOHEAD(fd,23); WFIFOW(fd,0) = 0x6a; @@ -1341,12 +1325,17 @@ int parse_login(int fd) sd->fd = fd; } - while( RFIFOREST(fd) >= 2 ) - { + while( RFIFOREST(fd) >= 2 ) { uint16 command = RFIFOW(fd,0); - switch( command ) - { + if( HPM->packetsc[hpParse_Login] ) { + if( (result = HPM->parse_packets(fd,hpParse_Login)) ) { + if( result == 1 ) continue; + if( result == 2 ) return 0; + } + } + + switch( command ) { case 0x0200: // New alive packet: structure: 0x200 <account.userid>.24B. used to verify if client is always alive. if (RFIFOREST(fd) < 26) @@ -1389,11 +1378,11 @@ int parse_login(int fd) { uint32 version; char username[NAME_LENGTH]; - char password[NAME_LENGTH]; + char password[PASSWD_LEN]; unsigned char passhash[16]; uint8 clienttype; bool israwpass = (command==0x0064 || command==0x0277 || command==0x02b0 || command == 0x0825); - + // Shinryo: For the time being, just use token as password. if(command == 0x0825) { @@ -1403,15 +1392,14 @@ int parse_login(int fd) size_t uTokenLen = RFIFOREST(fd) - 0x5C; version = RFIFOL(fd,4); - - if(uAccLen > NAME_LENGTH - 1 || uAccLen <= 0 || uTokenLen > NAME_LENGTH - 1 || uTokenLen <= 0) - { + + if(uAccLen <= 0 || uTokenLen <= 0) { login_auth_failed(sd, 3); return 0; } - safestrncpy(username, accname, uAccLen + 1); - safestrncpy(password, token, uTokenLen + 1); + safestrncpy(username, accname, NAME_LENGTH); + safestrncpy(password, token, min(uTokenLen+1, PASSWD_LEN)); // Variable-length field, don't copy more than necessary clienttype = RFIFOB(fd, 8); } else @@ -1437,7 +1425,7 @@ int parse_login(int fd) if( israwpass ) { ShowStatus("Request for connection of %s (ip: %s).\n", sd->userid, ip); - safestrncpy(sd->passwd, password, NAME_LENGTH); + safestrncpy(sd->passwd, password, PASSWD_LEN); if( login_config.use_md5_passwds ) MD5_String(sd->passwd, sd->passwd); sd->passwdenc = 0; @@ -1578,7 +1566,6 @@ void login_set_defaults() login_config.dynamic_pass_failure_ban_duration = 5; login_config.use_dnsbl = false; safestrncpy(login_config.dnsbl_servs, "", sizeof(login_config.dnsbl_servs)); - safestrncpy(login_config.account_engine, "auto", sizeof(login_config.account_engine)); login_config.client_hash_check = 0; login_config.client_hash_nodes = NULL; @@ -1599,7 +1586,7 @@ int login_config_read(const char* cfgName) if (line[0] == '/' && line[1] == '/') continue; - if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) < 2) + if (sscanf(line, "%1023[^:]: %1023[^\r\n]", w1, w2) < 2) continue; if(!strcmpi(w1,"timestamp_format")) @@ -1633,7 +1620,7 @@ int login_config_read(const char* cfgName) else if(!strcmpi(w1, "check_client_version")) login_config.check_client_version = (bool)config_switch(w2); else if(!strcmpi(w1, "client_version_to_connect")) - login_config.client_version_to_connect = strtoul(w2, NULL, 10); + login_config.client_version_to_connect = (unsigned int)strtoul(w2, NULL, 10); else if(!strcmpi(w1, "use_MD5_passwords")) login_config.use_md5_passwds = (bool)config_switch(w2); else if(!strcmpi(w1, "group_id_to_connect")) @@ -1665,15 +1652,19 @@ int login_config_read(const char* cfgName) int i; CREATE(nnode, struct client_hash_node, 1); - for (i = 0; i < 32; i += 2) { - char buf[3]; - unsigned int byte; + if (strcmpi(md5, "disabled") == 0) { + nnode->hash[0] = '\0'; + } else { + for (i = 0; i < 32; i += 2) { + char buf[3]; + unsigned int byte; - memcpy(buf, &md5[i], 2); - buf[2] = 0; + memcpy(buf, &md5[i], 2); + buf[2] = 0; - sscanf(buf, "%x", &byte); - nnode->hash[i / 2] = (uint8)(byte & 0xFF); + sscanf(buf, "%x", &byte); + nnode->hash[i / 2] = (uint8)(byte & 0xFF); + } } nnode->group_id = group; @@ -1685,18 +1676,10 @@ int login_config_read(const char* cfgName) else if(!strcmpi(w1, "import")) login_config_read(w2); else - if(!strcmpi(w1, "account.engine")) - safestrncpy(login_config.account_engine, w2, sizeof(login_config.account_engine)); - else - {// try the account engines - int i; - for( i = 0; account_engines[i].constructor; ++i ) - { - AccountDB* db = account_engines[i].db; - if( db && db->set_property(db, w1, w2) ) - break; - } - // try others + { + AccountDB* db = account_engine[0].db; + if( db ) + db->set_property(db, w1, w2); ipban_config_read(w1, w2); loginlog_config_read(w1, w2); } @@ -1706,61 +1689,36 @@ int login_config_read(const char* cfgName) return 0; } -/// Get the engine selected in the config settings. -/// Updates the config setting with the selected engine if 'auto'. -static AccountDB* get_account_engine(void) -{ - int i; - bool get_first = (strcmp(login_config.account_engine,"auto") == 0); - - for( i = 0; account_engines[i].constructor; ++i ) - { - char name[sizeof(login_config.account_engine)]; - AccountDB* db = account_engines[i].db; - if( db && db->get_property(db, "engine.name", name, sizeof(name)) && - (get_first || strcmp(name, login_config.account_engine) == 0) ) - { - if( get_first ) - safestrncpy(login_config.account_engine, name, sizeof(login_config.account_engine)); - return db; - } - } - return NULL; -} - //-------------------------------------- // Function called at exit of the server //-------------------------------------- -void do_final(void) -{ +int do_final(void) { int i; struct client_hash_node *hn = login_config.client_hash_nodes; - while (hn) - { + ShowStatus("Terminating...\n"); + + HPM->event(HPET_FINAL); + + while (hn) { struct client_hash_node *tmp = hn; hn = hn->next; aFree(tmp); } login_log(0, "login server", 100, "login server shutdown"); - ShowStatus("Terminating...\n"); if( login_config.log_login ) loginlog_final(); ipban_final(); - for( i = 0; account_engines[i].constructor; ++i ) - {// destroy all account engines - AccountDB* db = account_engines[i].db; - if( db ) - { - db->destroy(db); - account_engines[i].db = NULL; - } + if( account_engine[0].db ) + {// destroy account engine + account_engine[0].db->destroy(account_engine[0].db); + account_engine[0].db = NULL; } - accounts = NULL; // destroyed in account_engines + accounts = NULL; // destroyed in account_engine online_db->destroy(online_db, NULL); auth_db->destroy(auth_db, NULL); @@ -1774,6 +1732,7 @@ void do_final(void) } ShowStatus("Finished.\n"); + return EXIT_SUCCESS; } //------------------------------ @@ -1813,17 +1772,14 @@ int do_init(int argc, char** argv) { int i; - // intialize engines (to accept config settings) - for( i = 0; account_engines[i].constructor; ++i ) - account_engines[i].db = account_engines[i].constructor(); + // initialize engine (to accept config settings) + account_engine[0].db = account_engine[0].constructor(); // read login-server configuration login_set_defaults(); login_config_read((argc > 1) ? argv[1] : LOGIN_CONF_NAME); login_lan_config_read((argc > 2) ? argv[2] : LAN_CONF_NAME); - - rnd_init(); - + for( i = 0; i < ARRAYLENGTH(server); ++i ) chrif_server_init(i); @@ -1833,10 +1789,10 @@ int do_init(int argc, char** argv) // initialize static and dynamic ipban system ipban_init(); - + // Online user database init online_db = idb_alloc(DB_OPT_RELEASE_DATA); - iTimer->add_timer_func_list(waiting_disconnect_timer, "waiting_disconnect_timer"); + timer->add_func_list(waiting_disconnect_timer, "waiting_disconnect_timer"); // Interserver auth init auth_db = idb_alloc(DB_OPT_RELEASE_DATA); @@ -1845,29 +1801,33 @@ int do_init(int argc, char** argv) set_defaultparse(parse_login); // every 10 minutes cleanup online account db. - iTimer->add_timer_func_list(online_data_cleanup, "online_data_cleanup"); - iTimer->add_timer_interval(iTimer->gettick() + 600*1000, online_data_cleanup, 0, 0, 600*1000); + timer->add_func_list(online_data_cleanup, "online_data_cleanup"); + timer->add_interval(timer->gettick() + 600*1000, online_data_cleanup, 0, 0, 600*1000); // add timer to detect ip address change and perform update if (login_config.ip_sync_interval) { - iTimer->add_timer_func_list(sync_ip_addresses, "sync_ip_addresses"); - iTimer->add_timer_interval(iTimer->gettick() + login_config.ip_sync_interval, sync_ip_addresses, 0, 0, login_config.ip_sync_interval); + timer->add_func_list(sync_ip_addresses, "sync_ip_addresses"); + timer->add_interval(timer->gettick() + login_config.ip_sync_interval, sync_ip_addresses, 0, 0, login_config.ip_sync_interval); } // Account database init - accounts = get_account_engine(); + accounts = account_engine[0].db; if( accounts == NULL ) { - ShowFatalError("do_init: account engine '%s' not found.\n", login_config.account_engine); + ShowFatalError("do_init: account engine 'sql' not found.\n"); exit(EXIT_FAILURE); } else { if(!accounts->init(accounts)) { - ShowFatalError("do_init: Failed to initialize account engine '%s'.\n", login_config.account_engine); + ShowFatalError("do_init: Failed to initialize account engine 'sql'.\n"); exit(EXIT_FAILURE); } } - // server port open & binding + HPM->share(account_db_sql_up(accounts),"sql_handle"); + HPM->config_read(NULL, 0); + HPM->event(HPET_INIT); + + // server port open & binding if( (login_fd = make_listen_bind(login_config.login_ip,login_config.login_port)) == -1 ) { ShowFatalError("Failed to bind to port '"CL_WHITE"%d"CL_RESET"'\n",login_config.login_port); exit(EXIT_FAILURE); @@ -1877,11 +1837,11 @@ int do_init(int argc, char** argv) shutdown_callback = do_shutdown; runflag = LOGINSERVER_ST_RUNNING; } - - account_db_sql_up(accounts); ShowStatus("The login-server is "CL_GREEN"ready"CL_RESET" (Server is listening on the port %u).\n\n", login_config.login_port); login_log(0, "login server", 100, "login server started"); - + + HPM->event(HPET_READY); + return 0; } |