diff options
-rw-r--r-- | conf/log_athena.conf | 2 | ||||
-rw-r--r-- | conf/login_athena.conf | 3 | ||||
-rw-r--r-- | src/login/login.c | 7 | ||||
-rw-r--r-- | src/login/login_sql.c | 77 | ||||
-rw-r--r-- | src/login/login_txt.c | 59 |
5 files changed, 105 insertions, 43 deletions
diff --git a/conf/log_athena.conf b/conf/log_athena.conf index 043b28da9..ccad43221 100644 --- a/conf/log_athena.conf +++ b/conf/log_athena.conf @@ -99,7 +99,7 @@ log_chat: 0 // Dead Branch Log Table log_branch_db: branchlog -// Drops & Pickups Table +// Drops & Pickups Table log_pick_db: picklog // Zeny Table diff --git a/conf/login_athena.conf b/conf/login_athena.conf index 280c3717c..d632c224c 100644 --- a/conf/login_athena.conf +++ b/conf/login_athena.conf @@ -69,6 +69,9 @@ gm_account_filename: conf/GM_account.txt // (in seconds; default: 15; value: 0 (disabled), or 2 or more) gm_account_filename_check_timer: 15 +// Log Filename. All operations received by the server are logged in this file. +login_log_filename: log/login.log + // To log the login server? // NOTE: The login-sql server needs the login logs to enable dynamic pass failure bans. log_login: yes diff --git a/src/login/login.c b/src/login/login.c index c2faa6613..4a7a1707b 100644 --- a/src/login/login.c +++ b/src/login/login.c @@ -22,6 +22,7 @@ extern struct gm_account* gm_account_db; int read_gm_account(void); int mmo_auth_init(void); int parse_login(int fd); +void login_log(uint32 ip, const char* username, int rcode, const char* message); #ifdef TXT_ONLY extern struct mmo_account* auth_dat; @@ -35,6 +36,7 @@ int parse_login(int fd); extern char account_txt[1024]; extern char GM_account_filename[1024]; extern int gm_account_filename_check_timer; + extern char login_log_filename[1024]; #else void mmo_db_close(void); void sql_config_read(const char* cfgName); @@ -396,6 +398,8 @@ int login_config_read(const char* cfgName) login_config.log_login = (bool)config_switch(w2); #ifdef TXT_ONLY + else if(!strcmpi(w1, "login_log_filename") == 0) + safestrncpy(login_log_filename, w2, sizeof(login_log_filename)); else if(!strcmpi(w1, "admin_state") == 0) admin_state = (bool)config_switch(w2); else if(!strcmpi(w1, "admin_pass") == 0) @@ -466,6 +470,8 @@ int login_config_read(const char* cfgName) void do_final(void) { int i, fd; + + login_log(0, "login server", 100, "login server shutdown"); ShowStatus("Terminating...\n"); #ifdef TXT_ONLY @@ -585,6 +591,7 @@ int do_init(int argc, char** argv) login_fd = make_listen_bind(login_config.login_ip, login_config.login_port); 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"); return 0; } diff --git a/src/login/login_sql.c b/src/login/login_sql.c index 04d5deb39..0bff53799 100644 --- a/src/login/login_sql.c +++ b/src/login/login_sql.c @@ -150,6 +150,29 @@ void send_GM_accounts(int fd) } /*============================================= + * Records an event in the login log + *---------------------------------------------*/ +void login_log(uint32 ip, const char* username, int rcode, const char* message) +{ + char esc_username[NAME_LENGTH*2+1]; + char esc_message[255*2+1]; + int retcode; + + if( !login_config.log_login ) + return; + + Sql_EscapeStringLen(sql_handle, esc_username, username, strnlen(username, NAME_LENGTH)); + Sql_EscapeStringLen(sql_handle, esc_message, message, strnlen(message, 255)); + + retcode = Sql_Query(sql_handle, + "INSERT INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', '%s', '%d', '%s')", + loginlog_db, ip, esc_username, rcode, message); + + if( retcode != SQL_SUCCESS ) + Sql_ShowDebug(sql_handle); +} + +/*============================================= * Does a mysql_ping to all connection handles *---------------------------------------------*/ int login_sql_ping(int tid, unsigned int tick, int id, int data) @@ -179,7 +202,7 @@ int sql_ping_init(void) } //----------------------------------------------------- -// Read Account database - mysql db +// Initialize database connection //----------------------------------------------------- int mmo_auth_init(void) { @@ -203,9 +226,6 @@ int mmo_auth_init(void) if( default_codepage[0] != '\0' && SQL_ERROR == Sql_SetEncoding(sql_handle, default_codepage) ) Sql_ShowDebug(sql_handle); - if( login_config.log_login && SQL_ERROR == Sql_Query(sql_handle, "INSERT DELAYED INTO `%s` (`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '0', 'lserver','100','login server started')", loginlog_db) ) - Sql_ShowDebug(sql_handle); - sql_ping_init(); return 0; @@ -217,15 +237,11 @@ int mmo_auth_init(void) //----------------------------------------------------- void mmo_db_close(void) { - int i, fd; - - //set log. - if( login_config.log_login && SQL_ERROR == Sql_Query(sql_handle, "INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '0', 'lserver','100', 'login server shutdown')", loginlog_db) ) - Sql_ShowDebug(sql_handle); + int i; for( i = 0; i < MAX_SERVERS; ++i ) { - fd = server[i].fd; + int 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) ) @@ -233,11 +249,10 @@ void mmo_db_close(void) do_close(fd); } } + Sql_Free(sql_handle); sql_handle = NULL; ShowStatus("close DB connect....\n"); - if( login_fd > 0 ) - do_close(login_fd); } @@ -495,12 +510,8 @@ 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 ) - { - 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) ) - Sql_ShowDebug(sql_handle); - } + ShowStatus("Char-server '%s': Request to re-load GM database (ip: %s).\n", server[id].name, ip); + login_log(ipl, server[id].name, 0, "GM reload request"); read_gm_account(); // send GM accounts to all char-servers send_GM_accounts(-1); @@ -1008,9 +1019,8 @@ int login_ip_ban_check(uint32 ip) // ip ban ok. ShowInfo("Packet from banned ip : %u.%u.%u.%u\n", CONVIP(ip)); + login_log(ip, "unknown", -3, "ip banned"); - if( login_config.log_login && SQL_ERROR == Sql_Query(sql_handle, "INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', 'unknown','-3', 'ip banned')", loginlog_db, ip) ) - Sql_ShowDebug(sql_handle); return 1; } @@ -1019,14 +1029,11 @@ void login_auth_ok(struct login_session_data* sd) int fd = sd->fd; uint32 ip = session[fd]->client_addr; - char esc_userid[NAME_LENGTH*2+1]; uint8 server_num, n; uint32 subnet_char_ip; struct auth_node* node; int i; - Sql_EscapeStringLen(sql_handle, esc_userid, sd->userid, strlen(sd->userid)); - if( sd->level < login_config.min_level_to_connect ) { ShowStatus("Connection refused: the minimum GM level for connection is %d (account: %s, GM level: %d).\n", login_config.min_level_to_connect, sd->userid, sd->level); @@ -1084,8 +1091,7 @@ void login_auth_ok(struct login_session_data* sd) } } - 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, ip, esc_userid) ) - Sql_ShowDebug(sql_handle); + login_log(ip, sd->userid, 100, "login ok"); if( sd->level > 0 ) ShowStatus("Connection of the GM (level:%d) account '%s' accepted.\n", sd->level, sd->userid); @@ -1176,8 +1182,7 @@ void login_auth_failed(struct login_session_data* sd, int result) default : error = "Unknown Error."; break; } - if( SQL_ERROR == Sql_Query(sql_handle, "INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', '%s', '%d','login failed : %s')", loginlog_db, ip, esc_userid, result, error) ) - Sql_ShowDebug(sql_handle); + login_log(ip, sd->userid, result, error); } if( result == 1 && login_config.dynamic_pass_failure_ban && login_config.log_login ) // failed password @@ -1345,9 +1350,11 @@ int parse_login(int fd) if (RFIFOREST(fd) < 86) return 0; { - char esc_userid[NAME_LENGTH*2+1]; char server_name[20]; +#ifndef TXT_ONLY char esc_server_name[20*2+1]; +#endif + char message[256]; uint32 server_ip; uint16 server_port; uint16 maintenance; @@ -1364,14 +1371,9 @@ int parse_login(int fd) 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, sd->userid, strnlen(sd->userid, NAME_LENGTH)); - - 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, sd->userid, sd->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) ) - Sql_ShowDebug(sql_handle); + ShowInfo("Connection request of the char-server '%s' @ %u.%u.%u.%u:%u (account: '%s', pass: '%s', ip: '%s')\n", server_name, CONVIP(server_ip), server_port, sd->userid, sd->passwd, ip); + sprintf(message, "charserver - %s@%u.%u.%u.%u:%u", server_name, CONVIP(server_ip), server_port); + login_log(ipl, sd->userid, 100, message); result = mmo_auth(sd); if( result == -1 && sd->sex == 'S' && sd->account_id < MAX_SERVERS && server[sd->account_id].fd == -1 ) @@ -1398,8 +1400,11 @@ int parse_login(int fd) // send GM account to char-server send_GM_accounts(fd); +#ifndef TXT_ONLY + Sql_EscapeStringLen(sql_handle, esc_server_name, server_name, strnlen(server_name, 20)); if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `sstatus`(`index`,`name`,`user`) VALUES ( '%d', '%s', '%d')", sd->account_id, esc_server_name, 0) ) Sql_ShowDebug(sql_handle); +#endif } else { diff --git a/src/login/login_txt.c b/src/login/login_txt.c index a014ff871..cffede93b 100644 --- a/src/login/login_txt.c +++ b/src/login/login_txt.c @@ -28,6 +28,7 @@ char GM_account_filename[1024] = "conf/GM_account.txt"; long creation_time_GM_account_file; // tracks the last-changed timestamp of the gm accounts file int gm_account_filename_check_timer = 15; // Timer to check if GM_account file has been changed and reload GM account automaticaly (in seconds; default: 15) +char login_log_filename[1024] = "log/login.log"; // data handling (TXT) char account_txt[1024] = "save/account.txt"; @@ -697,6 +698,36 @@ int check_GM_file(int tid, unsigned int tick, int id, int data) return 0; } +/*============================================= + * Records an event in the login log + *---------------------------------------------*/ +void login_log(uint32 ip, const char* username, int rcode, const char* message) +{ + FILE* log_fp; + + if( !login_config.log_login ) + return; + + log_fp = fopen(login_log_filename, "a"); + if( log_fp != NULL ) + { + char esc_username[NAME_LENGTH*4+1]; + char esc_message[255*4+1]; + time_t raw_time; + char str_time[24]; + + sv_escape_c(esc_username, username, NAME_LENGTH, NULL); + sv_escape_c(esc_message, message, 255, NULL); + + time(&raw_time); + strftime(str_time, 24, login_config.date_format, localtime(&raw_time)); + str_time[23] = '\0'; + + fprintf(log_fp, "%s\t%u\t%s\t%d\t%s\n", str_time, ip, esc_username, rcode, esc_message); + + fclose(log_fp); + } +} //------------------------------------- // Make new account @@ -962,7 +993,8 @@ 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); + ShowStatus("Char-server '%s': Request to re-load GM database (ip: %s).\n", server[id].name, ip); + login_log(ipl, server[id].name, 0, "GM reload request"); read_gm_account(); // send GM accounts to all char-servers send_GM_accounts(-1); @@ -1506,6 +1538,8 @@ void login_auth_ok(struct login_session_data* sd) } } + login_log(ip, sd->userid, 100, "login ok"); + if( sd->level > 0 ) ShowStatus("Connection of the GM (level:%d) account '%s' accepted.\n", sd->level, sd->userid); else @@ -1561,6 +1595,9 @@ void login_auth_ok(struct login_session_data* sd) void login_auth_failed(struct login_session_data* sd, int result) { int fd = sd->fd; + uint32 ip = session[fd]->client_addr; + + login_log(ip, sd->userid, result, "login failed"); WFIFOHEAD(fd,23); WFIFOW(fd,0) = 0x6a; @@ -1685,25 +1722,29 @@ int parse_login(int fd) return 0; { char server_name[20]; +#ifndef TXT_ONLY + char esc_server_name[20*2+1]; +#endif + char message[256]; uint32 server_ip; uint16 server_port; uint16 maintenance; uint16 new_; - safestrncpy(sd->userid, (char*)RFIFOP(fd,2), NAME_LENGTH); //remove_control_chars(account.userid); - safestrncpy(sd->passwd, (char*)RFIFOP(fd,26), NAME_LENGTH); //remove_control_chars(account.passwd); + safestrncpy(sd->userid, (char*)RFIFOP(fd,2), NAME_LENGTH); + safestrncpy(sd->passwd, (char*)RFIFOP(fd,26), NAME_LENGTH); sd->passwdenc = 0; sd->version = login_config.client_version_to_connect; // hack to skip version check - 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); + safestrncpy(server_name, (char*)RFIFOP(fd,60), 20); 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, sd->userid, sd->passwd, ip); + sprintf(message, "charserver - %s@%u.%u.%u.%u:%u", server_name, CONVIP(server_ip), server_port); + login_log(ipl, sd->userid, 100, message); result = mmo_auth(sd); if( result == -1 && sd->sex == 'S' && sd->account_id < MAX_SERVERS && server[sd->account_id].fd == -1 ) @@ -1729,6 +1770,12 @@ int parse_login(int fd) // send GM account to char-server send_GM_accounts(fd); + +#ifndef TXT_ONLY + Sql_EscapeStringLen(sql_handle, esc_server_name, server_name, strnlen(server_name, 20)); + if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `sstatus`(`index`,`name`,`user`) VALUES ( '%d', '%s', '%d')", sd->account_id, esc_server_name, 0) ) + Sql_ShowDebug(sql_handle); +#endif } else { |