diff options
Diffstat (limited to 'src/login_sql')
-rw-r--r-- | src/login_sql/login.c | 250 | ||||
-rw-r--r-- | src/login_sql/login.h | 43 |
2 files changed, 154 insertions, 139 deletions
diff --git a/src/login_sql/login.c b/src/login_sql/login.c index f72590bac..f63961f82 100644 --- a/src/login_sql/login.c +++ b/src/login_sql/login.c @@ -20,36 +20,10 @@ #include <string.h> #include <sys/stat.h> // for stat/lstat/fstat -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) - - 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; +struct Login_Config login_config; int login_fd; // login server socket #define MAX_SERVERS 30 -int server_fd[MAX_SERVERS]; // char server sockets struct mmo_char_server server[MAX_SERVERS]; // char server data // Advanced subnet check [LuzZza] @@ -98,25 +72,22 @@ struct login_session_data { char md5key[20]; }; -#define AUTH_FIFO_SIZE 256 -struct _auth_fifo { - int account_id; - uint32 login_id1, login_id2; - uint32 ip; - uint8 sex; - bool delflag; -} auth_fifo[AUTH_FIFO_SIZE]; +// auth information of incoming clients +struct _auth_fifo auth_fifo[AUTH_FIFO_SIZE]; int auth_fifo_pos = 0; +//----------------------------------------------------- +// Online User Database [Wizputer] +//----------------------------------------------------- + struct online_login_data { int account_id; int waiting_disconnect; int char_server; }; -//----------------------------------------------------- - static DBMap* online_db; // int account_id -> struct online_login_data* +static int waiting_disconnect_timer(int tid, unsigned int tick, int id, int data); static void* create_online_user(DBKey key, va_list args) { @@ -128,13 +99,6 @@ static void* create_online_user(DBKey key, va_list args) return p; } -int charif_sendallwos(int sfd, uint8* buf, size_t len); -static int waiting_disconnect_timer(int tid, unsigned int tick, int id, int data); - -//----------------------------------------------------- -// Online User Database [Wizputer] -//----------------------------------------------------- - void add_online_user(int char_server, int account_id) { struct online_login_data* p; @@ -172,13 +136,26 @@ static int waiting_disconnect_timer(int tid, unsigned int tick, int id, int data return 0; } -static int sync_ip_addresses(int tid, unsigned int tick, int id, int data) +//-------------------------------------------------------------------- +// Packet send to all char-servers, except one (wos: without our self) +//-------------------------------------------------------------------- +int charif_sendallwos(int sfd, uint8* buf, size_t len) { - uint8 buf[2]; - ShowInfo("IP Sync in progress...\n"); - WBUFW(buf,0) = 0x2735; - charif_sendallwos(-1, buf, 2); - return 0; + int i, c; + + for( i = 0, c = 0; i < MAX_SERVERS; ++i ) + { + int fd = server[i].fd; + if( session_isValid(fd) && fd != sfd ) + { + WFIFOHEAD(fd,len); + memcpy(WFIFOP(fd,0), buf, len); + WFIFOSET(fd,len); + ++c; + } + } + + return c; } //----------------------------------------------------- @@ -331,7 +308,7 @@ void mmo_db_close(void) for( i = 0; i < MAX_SERVERS; ++i ) { - fd = server_fd[i]; + fd = server[i].fd; if( session_isValid(fd) ) {// Clean only data related to servers we are connected to. [Skotlex] if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `sstatus` WHERE `index` = '%d'", i) ) @@ -346,30 +323,18 @@ void mmo_db_close(void) do_close(login_fd); } - -//-------------------------------------------------------------------- -// Packet send to all char-servers, except one (wos: without our self) -//-------------------------------------------------------------------- -int charif_sendallwos(int sfd, uint8* buf, size_t len) +//----------------------------------------------------- +// periodic ip address synchronization +//----------------------------------------------------- +static int sync_ip_addresses(int tid, unsigned int tick, int id, int data) { - int i, c; - - for( i = 0, c = 0; i < MAX_SERVERS; ++i ) - { - int fd = server_fd[i]; - if( session_isValid(fd) && fd != sfd ) - { - WFIFOHEAD(fd,len); - memcpy(WFIFOP(fd,0), buf, len); - WFIFOSET(fd,len); - ++c; - } - } - - return c; + uint8 buf[2]; + ShowInfo("IP Sync in progress...\n"); + WBUFW(buf,0) = 0x2735; + charif_sendallwos(-1, buf, 2); + return 0; } - //----------------------------------------------------- // encrypted/unencrypted password check //----------------------------------------------------- @@ -645,7 +610,7 @@ int parse_fromchar(int fd) char ip[16]; ip2str(ipl, ip); - ARR_FIND( 0, MAX_SERVERS, id, server_fd[id] == fd ); + ARR_FIND( 0, MAX_SERVERS, id, server[id].fd == fd ); if( id == MAX_SERVERS ) {// not a char server set_eof(fd); @@ -656,7 +621,7 @@ int parse_fromchar(int fd) if( session[fd]->eof ) { ShowStatus("Char-server '%s' has disconnected.\n", server[id].name); - server_fd[id] = -1; + server[id].fd = -1; memset(&server[id], 0, sizeof(struct mmo_char_server)); online_db->foreach(online_db, online_db_setoffline, id); //Set all chars from this char server to offline. if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `sstatus` WHERE `index`='%d'", id) ) @@ -673,6 +638,7 @@ int parse_fromchar(int fd) { case 0x2709: // request from map-server via char-server to reload GM accounts + ShowStatus("Char-server '%s': Request to re-load GM configuration file (ip: %s).\n", server[id].name, ip); if( login_config.log_login ) { if( SQL_ERROR == Sql_Query(sql_handle, "INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`log`) VALUES (NOW(), '%u', '%s', 'GM reload request')", loginlog_db, ipl, server[id].name) ) @@ -689,21 +655,18 @@ int parse_fromchar(int fd) return 0; { int account_id = RFIFOL(fd,2); - for( i = 0; i < AUTH_FIFO_SIZE; ++i ) - { - if( 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].delflag) - { - auth_fifo[i].delflag = 1; - break; - } - } - - if( i != AUTH_FIFO_SIZE && account_id > 0 ) + 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].delflag ); + + if( i < AUTH_FIFO_SIZE ) + auth_fifo[i].delflag = 1; + + if( i < AUTH_FIFO_SIZE && account_id > 0 ) {// send ack uint32 connect_until_time; char email[40]; @@ -737,7 +700,8 @@ int parse_fromchar(int fd) WFIFOSET(fd,51); } else - {// authentification not found + {// 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; @@ -752,7 +716,7 @@ int parse_fromchar(int fd) break; case 0x2714: - if (RFIFOREST(fd) < 6) + if( RFIFOREST(fd) < 6 ) return 0; // how many users on world? (update) @@ -906,9 +870,8 @@ int parse_fromchar(int fd) if (RFIFOREST(fd) < 10) return 0; { - int account_id, state; - account_id = RFIFOL(fd,2); - state = RFIFOL(fd,6); + int account_id = RFIFOL(fd,2); + int state = RFIFOL(fd,6); 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) ) @@ -990,7 +953,7 @@ int parse_fromchar(int fd) break; case 0x2727: // Change of sex (sex is reversed) - if (RFIFOREST(fd) < 6) + if( RFIFOREST(fd) < 6 ) return 0; { int account_id; @@ -1099,14 +1062,14 @@ int parse_fromchar(int fd) } case 0x272b: // Set account_id to online [Wizputer] - if (RFIFOREST(fd) < 6) + if( RFIFOREST(fd) < 6 ) return 0; add_online_user(id, RFIFOL(fd,2)); RFIFOSKIP(fd,6); break; case 0x272c: // Set account_id to offline [Wizputer] - if (RFIFOREST(fd) < 6) + if( RFIFOREST(fd) < 6 ) return 0; remove_online_user(RFIFOL(fd,2)); RFIFOSKIP(fd,6); @@ -1179,7 +1142,7 @@ int parse_fromchar(int fd) break; case 0x2736: // WAN IP update from char-server - if (RFIFOREST(fd) < 6) + if( RFIFOREST(fd) < 6 ) return 0; server[id].ip = ntohl(RFIFOL(fd,2)); ShowInfo("Updated IP of Server #%d to %d.%d.%d.%d.\n",id, CONVIP(server[id].ip)); @@ -1256,14 +1219,14 @@ int parse_login(int fd) uint32 ipl = session[fd]->client_addr; char ip[16]; - ip2str(ipl, ip); - if( session[fd]->eof ) { do_close(fd); return 0; } + ip2str(ipl, ip); + while( RFIFOREST(fd) >= 2 ) { uint16 command = RFIFOW(fd,0); @@ -1287,11 +1250,12 @@ int parse_login(int fd) case 0x0277: // New login packet (kRO 2006-04-24aSakexe langtype 0) case 0x02b0: // New login packet (kRO 2007-05-14aSakexe langtype 0) { - size_t packet_len = RFIFOREST(fd); + size_t packet_len = RFIFOREST(fd); // assume no other packet was sent // Perform ip-ban check if( login_config.ipban && login_ip_ban_check(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 @@ -1326,6 +1290,7 @@ int parse_login(int fd) { // auth success if( login_config.min_level_to_connect > account.level ) { + ShowStatus("Connection refused: the minimum GM level for connection is %d (account: %s, GM level: %d, ip: %s).\n", login_config.min_level_to_connect, account.userid, account.level, ip); WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x81; WFIFOB(fd,2) = 1; // 01 = Server closed @@ -1333,32 +1298,24 @@ int parse_login(int fd) } else { - uint8 server_num = 0; + uint8 server_num, n; + uint32 subnet_char_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','100', 'login ok')", loginlog_db, ipl, esc_userid) ) - Sql_ShowDebug(sql_handle); - if( account.level ) - ShowStatus("Connection of the GM (level:%d) account '%s' accepted.\n", account.level, account.userid); - else - ShowStatus("Connection of the account '%s' accepted.\n", account.userid); - - WFIFOHEAD(fd,47+32*MAX_SERVERS); + server_num = 0; for( i = 0; i < MAX_SERVERS; ++i ) - { - if( session_isValid(server_fd[i]) ) - { - // Advanced subnet check [LuzZza] - uint32 subnet_char_ip = lan_subnetcheck(ipl); - WFIFOL(fd,47+server_num*32) = htonl((subnet_char_ip) ? subnet_char_ip : server[i].ip); - WFIFOW(fd,47+server_num*32+4) = ntows(htons(server[i].port)); // [!] LE byte order here [!] - memcpy(WFIFOP(fd,47+server_num*32+6), server[i].name, 20); - WFIFOW(fd,47+server_num*32+26) = server[i].users; - WFIFOW(fd,47+server_num*32+28) = server[i].maintenance; - WFIFOW(fd,47+server_num*32+30) = server[i].new_; + if( session_isValid(server[i].fd) ) server_num++; - } - } - if (server_num > 0) { // if at least 1 char-server + + if( server_num > 0 ) + {// if at least 1 char-server + if( login_config.log_login && SQL_ERROR == Sql_Query(sql_handle, "INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', '%s','100', 'login ok')", loginlog_db, ipl, esc_userid) ) + Sql_ShowDebug(sql_handle); + if( account.level ) + ShowStatus("Connection of the GM (level:%d) account '%s' accepted.\n", account.level, account.userid); + else + ShowStatus("Connection of the account '%s' accepted.\n", account.userid); + + WFIFOHEAD(fd,47+32*server_num); WFIFOW(fd,0) = 0x69; WFIFOW(fd,2) = 47+32*server_num; WFIFOL(fd,4) = account.login_id1; @@ -1366,8 +1323,24 @@ int parse_login(int fd) WFIFOL(fd,12) = account.login_id2; WFIFOL(fd,16) = 0; // in old version, that was for ip (not more used) //memcpy(WFIFOP(fd,20), account.lastlogin, 24); // in old version, that was for name (not more used) + WFIFOW(fd,44) = 0; // unknown WFIFOB(fd,46) = account.sex; + for( i = 0, n = 0; i < MAX_SERVERS; ++i ) + { + if( !session_isValid(server[i].fd) ) + continue; + + subnet_char_ip = lan_subnetcheck(ipl); // Advanced subnet check [LuzZza] + WFIFOL(fd,47+n*32) = htonl((subnet_char_ip) ? subnet_char_ip : server[i].ip); + WFIFOW(fd,47+n*32+4) = ntows(htons(server[i].port)); // [!] LE byte order here [!] + memcpy(WFIFOP(fd,47+n*32+6), server[i].name, 20); + WFIFOW(fd,47+n*32+26) = server[i].users; + WFIFOW(fd,47+n*32+28) = server[i].maintenance; + WFIFOW(fd,47+n*32+30) = server[i].new_; + n++; + } WFIFOSET(fd,47+32*server_num); + if (auth_fifo_pos >= AUTH_FIFO_SIZE) auth_fifo_pos = 0; auth_fifo[auth_fifo_pos].account_id = account.account_id; @@ -1377,7 +1350,11 @@ int parse_login(int fd) auth_fifo[auth_fifo_pos].delflag = 0; auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr; auth_fifo_pos++; - } else { // if no char-server, don't send void list of servers, just disconnect the player with proper message + } + else + {// if no char-server, don't send void list of servers, just disconnect the player with proper message + ShowStatus("Connection refused: there is no char-server online (account: %s, ip: %s).\n", account.userid, ip); + WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x81; WFIFOB(fd,2) = 1; // 01 = Server closed WFIFOSET(fd,3); @@ -1445,7 +1422,9 @@ int parse_login(int fd) WFIFOHEAD(fd,23); WFIFOW(fd,0) = 0x6a; WFIFOB(fd,2) = (uint8)result; - if( result == 6 ) + if( result != 6 ) + memset(WFIFOP(fd,3), '\0', 20); + else {// 6 = Your are Prohibited to log in until %s if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `ban_until` FROM `%s` WHERE `%s` = %s '%s'", login_db, login_db_userid, (login_config.case_sensitive ? "BINARY" : ""), esc_userid) ) Sql_ShowDebug(sql_handle); @@ -1461,8 +1440,6 @@ int parse_login(int fd) strftime((char*)WFIFOP(fd,3), 20, login_config.date_format, localtime(&ban_until_time)); } } - else - memset(WFIFOP(fd,3), '\0', 20); WFIFOSET(fd,23); } @@ -1526,7 +1503,7 @@ int parse_login(int fd) Sql_ShowDebug(sql_handle); result = mmo_auth(&account, fd); - if( result == -1 && account.sex == 2 && account.account_id < MAX_SERVERS && server_fd[account.account_id] == -1 ) + 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)); @@ -1536,7 +1513,7 @@ int parse_login(int fd) server[account.account_id].users = 0; server[account.account_id].maintenance = RFIFOW(fd,82); server[account.account_id].new_ = RFIFOW(fd,84); - server_fd[account.account_id] = fd; + server[account.account_id].fd = fd; WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x2711; @@ -1560,14 +1537,12 @@ int parse_login(int fd) WFIFOB(fd,2) = 3; WFIFOSET(fd,3); } - + } RFIFOSKIP(fd,86); return 0; - } case 0x7530: // Server version information request - { - ShowInfo ("Athena version check...\n"); + ShowStatus("Sending server version information to ip: %s\n", ip); WFIFOHEAD(fd,10); WFIFOW(fd,0) = 0x7531; WFIFOB(fd,2) = ATHENA_MAJOR_VERSION; @@ -1580,7 +1555,6 @@ int parse_login(int fd) WFIFOSET(fd,10); RFIFOSKIP(fd,2); - } break; case 0x7532: // Request to end connection @@ -1589,7 +1563,7 @@ int parse_login(int fd) break; default: - ShowStatus("Abnormal end of connection (ip: %s): Unknown packet 0x%x\n", ip, RFIFOW(fd,0)); + ShowNotice("Abnormal end of connection (ip: %s): Unknown packet 0x%x\n", ip, command); set_eof(fd); return 0; } @@ -1618,7 +1592,7 @@ int parse_console(char* buf) strcmpi("end", command) == 0 ) runflag = 0; else - if( strcmpi("alive", command) == 0 || + if( strcmpi("alive", command) == 0 || strcmpi("status", command) == 0 ) ShowInfo(CL_CYAN"Console: "CL_BOLD"I'm Alive."CL_RESET"\n"); else @@ -1931,7 +1905,7 @@ int do_init(int argc, char** argv) auth_fifo[i].delflag = 1; for( i = 0; i < MAX_SERVERS; i++ ) - server_fd[i] = -1; + server[i].fd = -1; // Online user database init online_db = idb_alloc(DB_OPT_RELEASE_DATA); diff --git a/src/login_sql/login.h b/src/login_sql/login.h index bc6337f42..b67d202cb 100644 --- a/src/login_sql/login.h +++ b/src/login_sql/login.h @@ -4,6 +4,8 @@ #ifndef _LOGIN_SQL_H_ #define _LOGIN_SQL_H_ +#include "../common/mmo.h" // NAME_LENGTH + #define LOGIN_CONF_NAME "conf/login_athena.conf" #define SQL_CONF_NAME "conf/inter_athena.conf" #define LAN_CONF_NAME "conf/subnet_athena.conf" @@ -18,9 +20,9 @@ struct mmo_account { int passwdenc; int account_id; - int char_id; long login_id1; long login_id2; + int char_id; char lastlogin[24]; int sex; uint8 level; @@ -28,6 +30,7 @@ struct mmo_account { struct mmo_char_server { char name[20]; + int fd; uint32 ip; uint16 port; int users; @@ -35,4 +38,42 @@ struct mmo_char_server { int new_; }; +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) + + 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; + +// stores auth information of incoming clients +// used during charserver auth validation process +#define AUTH_FIFO_SIZE 256 +extern struct _auth_fifo { + int account_id; + uint32 login_id1, login_id2; + uint32 ip; + uint8 sex; + bool delflag; +} auth_fifo[AUTH_FIFO_SIZE]; + #endif /* _LOGIN_SQL_H_ */ |