diff options
Diffstat (limited to 'src/login_sql')
-rw-r--r-- | src/login_sql/Makefile | 22 | ||||
-rw-r--r-- | src/login_sql/Makefile.in | 46 | ||||
-rw-r--r-- | src/login_sql/login.c | 1335 |
3 files changed, 706 insertions, 697 deletions
diff --git a/src/login_sql/Makefile b/src/login_sql/Makefile deleted file mode 100644 index d87a465ea..000000000 --- a/src/login_sql/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -all sql: login-server_sql - -COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o \ - ../common/obj/db.o ../common/obj/plugins.o ../common/obj/lock.o \ - ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/utils.o \ - ../common/obj/strlib.o ../common/obj/grfio.o \ - ../common/obj/mapindex.o ../common/obj/ers.o ../common/obj/md5calc.o -COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h \ - ../common/version.h ../common/db.h ../common/plugins.h ../common/lock.h \ - ../common/malloc.h ../common/showmsg.h ../common/utils.h ../common/strlib.h \ - ../common/grfio.h ../common/mapindex.h \ - ../common/md5calc.h - -login-server_sql: login.o $(COMMON_OBJ) - $(CC) -o ../../$@ $^ $(LIB_S) - -clean: - rm -f *.o ../../login-server_sql GNUmakefile - -# DO NOT DELETE - -login.o: login.c login.h $(COMMON_H) diff --git a/src/login_sql/Makefile.in b/src/login_sql/Makefile.in new file mode 100644 index 000000000..d10b49b5f --- /dev/null +++ b/src/login_sql/Makefile.in @@ -0,0 +1,46 @@ +COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o \ + ../common/obj/db.o ../common/obj/plugins.o ../common/obj/lock.o \ + ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/utils.o \ + ../common/obj/strlib.o ../common/obj/grfio.o ../common/obj/mapindex.o \ + ../common/obj/ers.o ../common/obj/md5calc.o ../common/obj_sql/sql.o +COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h \ + ../common/version.h ../common/db.h ../common/plugins.h ../common/lock.h \ + ../common/malloc.h ../common/showmsg.h ../common/utils.h ../common/strlib.h \ + ../common/grfio.h ../common/mapindex.h \ + ../common/ers.h ../common/md5calc.h ../common/sql.h + +HAVE_MYSQL=@HAVE_MYSQL@ +ifeq ($(HAVE_MYSQL),yes) + LOGIN_SERVER_SQL_DEPENDS=login.o $(COMMON_OBJ) +else + LOGIN_SERVER_SQL_DEPENDS=needs_mysql +endif + +##################################################################### +.PHONY : all login-server_sql clean help + +all: login-server_sql + +login-server_sql: $(LOGIN_SERVER_SQL_DEPENDS) + @CC@ @LDFLAGS@ -o ../../login-server_sql@EXEEXT@ login.o $(COMMON_OBJ) @LIBS@ @MYSQL_LIBS@ + +clean: + rm -f *.o ../../login-server_sql@EXEEXT@ + +help: + @echo "possible targets are 'login-server_sql' 'all' 'clean' 'help'" + @echo "'login-server_sql' - login server (SQL version)" + @echo "'all' - builds all above targets" + @echo "'clean' - cleans builds and objects" + @echo "'help' - outputs this message" + +##################################################################### + +needs_mysql: + @echo "MySQL not found or disabled by the configure script" + @exit 1 + +# DO NOT DELETE + +login.o: login.c login.h $(COMMON_H) + @CC@ @CFLAGS@ @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< diff --git a/src/login_sql/login.c b/src/login_sql/login.c index 9411c6fec..bc3c1117a 100644 --- a/src/login_sql/login.c +++ b/src/login_sql/login.c @@ -12,20 +12,13 @@ #include "../common/showmsg.h" #include "../common/version.h" #include "../common/md5calc.h" +#include "../common/sql.h" #include "login.h" #include <stdio.h> #include <stdlib.h> -#include <sys/stat.h> // for stat/lstat/fstat -#include <signal.h> -#include <fcntl.h> #include <string.h> - -//add include for DBMS(mysql) -#ifdef WIN32 -#include <winsock2.h> -#endif -#include <mysql.h> +#include <sys/stat.h> // for stat/lstat/fstat struct Login_Config { @@ -59,7 +52,7 @@ int server_fd[MAX_SERVERS]; // char server sockets struct mmo_char_server server[MAX_SERVERS]; // char server data // Advanced subnet check [LuzZza] -struct _subnet { +struct s_subnet { uint32 subnet; uint32 mask; uint32 char_ip; @@ -78,13 +71,10 @@ int time_allowed = 10; //in seconds int num_regs = 0; unsigned int new_reg_tick = 0; -MYSQL mysql_handle; -MYSQL_RES* sql_res ; -MYSQL_ROW sql_row ; -char tmpsql[65535]; +Sql* sql_handle; // database parameters -int login_server_port = 3306; +uint16 login_server_port = 3306; char login_server_ip[32] = "127.0.0.1"; char login_server_id[32] = "ragnarok"; char login_server_pw[32] = "ragnarok"; @@ -127,19 +117,19 @@ struct online_login_data { //----------------------------------------------------- -struct dbt *online_db; +struct dbt* online_db; static void* create_online_user(DBKey key, va_list args) { - struct online_login_data *p; - p = aCalloc(1, sizeof(struct online_login_data)); + struct online_login_data* p; + CREATE(p, struct online_login_data, 1); p->account_id = key.i; p->char_server = -1; p->waiting_disconnect = -1; - return p; + return p; } -int charif_sendallwos(int sfd, unsigned char *buf, unsigned int len); +int charif_sendallwos(int sfd, uint8* buf, size_t len); static int waiting_disconnect_timer(int tid, unsigned int tick, int id, int data); //----------------------------------------------------- @@ -148,12 +138,12 @@ static int waiting_disconnect_timer(int tid, unsigned int tick, int id, int data void add_online_user(int char_server, int account_id) { - struct online_login_data *p; - if (!login_config.online_check) + struct online_login_data* p; + if( !login_config.online_check ) return; p = idb_ensure(online_db, account_id, create_online_user); p->char_server = char_server; - if (p->waiting_disconnect != -1) + if( p->waiting_disconnect != -1 ) { delete_timer(p->waiting_disconnect, waiting_disconnect_timer); p->waiting_disconnect = -1; @@ -162,19 +152,20 @@ void add_online_user(int char_server, int account_id) void remove_online_user(int account_id) { - if(!login_config.online_check) + if( !login_config.online_check ) return; - if (account_id == 99) { // reset all to offline + if( account_id == 99 ) + {// reset all to offline online_db->clear(online_db, NULL); // purge db return; } - idb_remove(online_db,account_id); + idb_remove(online_db, account_id); } static int waiting_disconnect_timer(int tid, unsigned int tick, int id, int data) { - struct online_login_data *p; - if ((p= idb_get(online_db, id)) != NULL && p->waiting_disconnect == id) + struct online_login_data* p = idb_get(online_db, id); + if( p != NULL && p->waiting_disconnect == id ) { p->waiting_disconnect = -1; remove_online_user(id); @@ -184,7 +175,7 @@ static int waiting_disconnect_timer(int tid, unsigned int tick, int id, int data static int sync_ip_addresses(int tid, unsigned int tick, int id, int data) { - unsigned char buf[2]; + uint8 buf[2]; ShowInfo("IP Sync in progress...\n"); WBUFW(buf,0) = 0x2735; charif_sendallwos(-1, buf, 2); @@ -196,32 +187,30 @@ static int sync_ip_addresses(int tid, unsigned int tick, int id, int data) //----------------------------------------------------- void read_gm_account(void) { - if(!login_config.login_gm_read) - return; - sprintf(tmpsql, "SELECT `%s`,`%s` FROM `%s` WHERE `%s`> '0'",login_db_account_id,login_db_level,login_db,login_db_level); - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - return; //Failed to read GM list! - } + if( !login_config.login_gm_read ) + return;// char server's job - if (gm_account_db != NULL) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `%s`,`%s` FROM `%s` WHERE `%s` > '0'", login_db_account_id, login_db_level, login_db, login_db_level) ) { - aFree(gm_account_db); - gm_account_db = NULL; + Sql_ShowDebug(sql_handle); + return;// Failed to read GM list! } - GM_num = 0; - - sql_res = mysql_store_result(&mysql_handle); - if (sql_res) { - gm_account_db = (struct gm_account*)aCalloc((size_t)mysql_num_rows(sql_res), sizeof(struct gm_account)); - while ((sql_row = mysql_fetch_row(sql_res))) { - gm_account_db[GM_num].account_id = atoi(sql_row[0]); - gm_account_db[GM_num].level = atoi(sql_row[1]); - GM_num++; - } - mysql_free_result(sql_res); + + RECREATE(gm_account_db, struct gm_account, (size_t)Sql_NumRows(sql_handle)); + + for( GM_num = 0; SQL_SUCCESS == Sql_NextRow(sql_handle); ++GM_num ) + { + char* account; + char* level; + + Sql_GetData(sql_handle, 0, &account, NULL); + Sql_GetData(sql_handle, 1, &level, NULL); + + gm_account_db[GM_num].account_id = atoi(account); + gm_account_db[GM_num].level = atoi(level); } + + Sql_FreeResult(sql_handle); } //----------------------------------------------------- @@ -233,27 +222,32 @@ void send_GM_accounts(int fd) uint8 buf[32767]; uint16 len; - if(!login_config.login_gm_read) + if( !login_config.login_gm_read ) return; len = 4; WBUFW(buf,0) = 0x2732; - for(i = 0; i < GM_num; i++) + for( i = 0; i < GM_num; ++i ) + { // send only existing accounts. We can not create a GM account when server is online. - if (gm_account_db[i].level > 0) { + if( gm_account_db[i].level > 0 ) + { WBUFL(buf,len) = gm_account_db[i].account_id; WBUFB(buf,len+4) = (uint8)gm_account_db[i].level; len += 5; - if (len >= 32000) { + if( len >= 32000 ) + { ShowWarning("send_GM_accounts: Too many accounts! Only %d out of %d were sent.\n", i, GM_num); break; } } + } WBUFW(buf,2) = len; - if (fd == -1) // send to all charservers + if( fd == -1 )// send to all charservers charif_sendallwos(-1, buf, len); - else { // send only to target + else + {// send only to target WFIFOHEAD(fd,len); memcpy(WFIFOP(fd,0), buf, len); WFIFOSET(fd,len); @@ -268,27 +262,20 @@ void send_GM_accounts(int fd) int login_sql_ping(int tid, unsigned int tick, int id, int data) { ShowInfo("Pinging SQL server to keep connection alive...\n"); - mysql_ping(&mysql_handle); + Sql_Ping(sql_handle); return 0; } int sql_ping_init(void) { - int connection_timeout, connection_ping_interval; + uint32 connection_timeout, connection_ping_interval; // set a default value first connection_timeout = 28800; // 8 hours // ask the mysql server for the timeout value - if (!mysql_query(&mysql_handle, "SHOW VARIABLES LIKE 'wait_timeout'") - && (sql_res = mysql_store_result(&mysql_handle)) != NULL) { - sql_row = mysql_fetch_row(sql_res); - if (sql_row) - connection_timeout = atoi(sql_row[1]); - if (connection_timeout < 60) - connection_timeout = 60; - mysql_free_result(sql_res); - } + if( SQL_SUCCESS == Sql_GetTimeout(sql_handle, &connection_timeout) && connection_timeout < 60 ) + connection_timeout = 60; // establish keepalive connection_ping_interval = connection_timeout - 30; // 30-second reserve @@ -305,34 +292,26 @@ int mmo_auth_sqldb_init(void) { ShowStatus("Login server init....\n"); - mysql_init(&mysql_handle); + sql_handle = Sql_Malloc(); // DB connection start ShowStatus("Connect Login Database Server....\n"); - if (!mysql_real_connect(&mysql_handle, login_server_ip, login_server_id, login_server_pw, login_server_db, login_server_port, (char *)NULL, 0)) { - ShowFatalError("%s\n", mysql_error(&mysql_handle)); + if( SQL_ERROR == Sql_Connect(sql_handle, login_server_id, login_server_pw, login_server_ip, login_server_port, login_server_db) ) + { + Sql_ShowDebug(sql_handle); + Sql_Free(sql_handle); exit(1); - } else { - ShowStatus("Connect success!\n"); } - if( strlen(default_codepage) > 0 ) { - sprintf( tmpsql, "SET NAMES %s", default_codepage ); - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } + else + { + ShowStatus("Connect success!\n"); } - if (login_config.log_login) - { - sprintf(tmpsql, "INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '0', 'lserver','100','login server started')", loginlog_db); + if( default_codepage[0] != '\0' && SQL_ERROR == Sql_SetEncoding(sql_handle, default_codepage) ) + Sql_ShowDebug(sql_handle); - //query - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } - } + 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(); @@ -348,32 +327,23 @@ void mmo_db_close(void) int i, fd; //set log. - if (login_config.log_login) - { - sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '0', 'lserver','100', 'login server shutdown')", loginlog_db); - - //query - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } - } + 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); - for (i = 0; i < MAX_SERVERS; i++) { - if ((fd = server_fd[i]) >= 0) - { //Clean only data related to servers we are connected to. [Skotlex] - sprintf(tmpsql,"DELETE FROM `sstatus` WHERE `index` = '%d'", i); - if (mysql_query(&mysql_handle, tmpsql)) - { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } + for( i = 0; i < MAX_SERVERS; ++i ) + { + fd = server_fd[i]; + 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) ) + Sql_ShowDebug(sql_handle); do_close(fd); } } - mysql_close(&mysql_handle); + Sql_Free(sql_handle); + sql_handle = NULL; ShowStatus("close DB connect....\n"); - if (login_fd > 0) + if( login_fd > 0 ) do_close(login_fd); } @@ -383,75 +353,66 @@ void mmo_db_close(void) int mmo_auth_new(struct mmo_account* account, char sex) { unsigned int tick = gettick(); - char user_password[256]; + char md5buf[32+1]; + SqlStmt* stmt; + //Account Registration Flood Protection by [Kevin] - if(DIFF_TICK(tick, new_reg_tick) < 0 && num_regs >= allowed_regs) { + if( DIFF_TICK(tick, new_reg_tick) < 0 && num_regs >= allowed_regs ) + { ShowNotice("Account registration denied (registration limit exceeded)\n"); return 3; } - //Check for preexisting account - sprintf(tmpsql, "SELECT `%s` FROM `%s` WHERE `userid` = '%s'", login_db_userid, login_db, account->userid); - if(mysql_query(&mysql_handle, tmpsql)){ - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - return 1; //Return Incorrect user/pass? + // check if the account doesn't exist already + stmt = SqlStmt_Malloc(sql_handle); + if ( SQL_SUCCESS != SqlStmt_Prepare(stmt, "SELECT `%s` FROM `%s` WHERE `userid` = ?", login_db_userid, login_db) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, account->userid, strnlen(account->userid, NAME_LENGTH)) + || SQL_SUCCESS != SqlStmt_Execute(stmt) + || SqlStmt_NumRows(stmt) > 0 ) + { + SqlStmt_ShowDebug(stmt); + SqlStmt_Free(stmt); + return 1; // incorrect user/pass } - - sql_res = mysql_store_result(&mysql_handle); - if(mysql_num_rows(sql_res) > 0){ - mysql_free_result(sql_res); - return 1; //Already exists, return incorrect user/pass. + SqlStmt_Free(stmt); + + // insert new entry into db + //TODO: error checking + stmt = SqlStmt_Malloc(sql_handle); + SqlStmt_Prepare(stmt, "INSERT INTO `%s` (`%s`, `%s`, `sex`, `email`) VALUES (?, ?, '%c', 'a@a.com')", login_db, login_db_userid, login_db_user_pass, TOUPPER(sex)); + SqlStmt_BindParam(stmt, 0, SQLDT_STRING, account->userid, strnlen(account->userid, NAME_LENGTH)); + if( login_config.use_md5_passwds ) + { + MD5_String(account->passwd, md5buf); + SqlStmt_BindParam(stmt, 1, SQLDT_STRING, md5buf, 32); } - mysql_free_result(sql_res); //Only needed for the already-exists check... - - mysql_real_escape_string(&mysql_handle, account->userid, account->userid, strlen(account->userid)); - mysql_real_escape_string(&mysql_handle, account->passwd, account->passwd, strlen(account->passwd)); - - sex = TOUPPER(sex); - - if (login_config.use_md5_passwds) - MD5_String(account->passwd, user_password); else - jstrescapecpy(user_password, account->passwd); - - ShowInfo("New account: user: %s with passwd: %s sex: %c\n", account->userid, user_password, sex); - - sprintf(tmpsql, "INSERT INTO `%s` (`%s`, `%s`, `sex`, `email`) VALUES ('%s', '%s', '%c', '%s')", login_db, login_db_userid, login_db_user_pass, account->userid, user_password, sex, "a@a.com"); + SqlStmt_BindParam(stmt, 1, SQLDT_STRING, account->passwd, strnlen(account->passwd, NAME_LENGTH)); + SqlStmt_Execute(stmt); + SqlStmt_Free(stmt); - if(mysql_query(&mysql_handle, tmpsql)){ - //Failed to insert new acc :/ - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - return 1; - } + ShowInfo("New account: userid='%s' passwd='%s' sex='%c'\n", account->userid, account->passwd, TOUPPER(sex)); - if(mysql_field_count(&mysql_handle) == 0 && - mysql_insert_id(&mysql_handle) < START_ACCOUNT_NUM) { - //Invalid Account ID! Must update it. - int id = (int)mysql_insert_id(&mysql_handle); - sprintf(tmpsql, "UPDATE `%s` SET `%s`='%d' WHERE `%s`='%d'", login_db, login_db_account_id, START_ACCOUNT_NUM, login_db_account_id, id); - if(mysql_query(&mysql_handle, tmpsql)){ - ShowError("New account %s has an invalid account ID [%d] which could not be updated (account_id must be %d or higher).", account->userid, id, START_ACCOUNT_NUM); - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); + if( Sql_LastInsertId(sql_handle) < START_ACCOUNT_NUM ) + {// Invalid Account ID! Must update it. + uint64 id = Sql_LastInsertId(sql_handle); + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `%s`='%d' WHERE `%s`='%lld'", login_db, login_db_account_id, START_ACCOUNT_NUM, login_db_account_id, id) ) + { + Sql_ShowDebug(sql_handle); + ShowError("New account '%s' has an invalid account ID [%lld] which could not be updated (account_id must be %d or higher).", account->userid, id, START_ACCOUNT_NUM); //Just delete it and fail. - sprintf(tmpsql, "DELETE FROM `%s` WHERE `%s`='%d'", login_db, login_db_account_id, id); - if(mysql_query(&mysql_handle, tmpsql)){ - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `%s`='%lld'", login_db, login_db_account_id, id) ) + Sql_ShowDebug(sql_handle); return 1; } - ShowNotice("Updated New account %s's ID %d->%d (account_id must be %d or higher).", account->userid, id, START_ACCOUNT_NUM, START_ACCOUNT_NUM); + ShowNotice("Updated New account '%s' ID %d->%d (account_id must be %d or higher).", account->userid, id, START_ACCOUNT_NUM, START_ACCOUNT_NUM); } - if(DIFF_TICK(tick, new_reg_tick) > 0) - { //Update the registration check. - num_regs=0; - new_reg_tick=tick+time_allowed*1000; + if( DIFF_TICK(tick, new_reg_tick) > 0 ) + {// Update the registration check. + num_regs = 0; + new_reg_tick = tick + time_allowed*1000; } - num_regs++; - + ++num_regs; return 0; } @@ -459,16 +420,19 @@ int mmo_auth_new(struct mmo_account* account, char sex) //-------------------------------------------------------------------- // Packet send to all char-servers, except one (wos: without our self) //-------------------------------------------------------------------- -int charif_sendallwos(int sfd, unsigned char *buf, unsigned int len) +int charif_sendallwos(int sfd, uint8* buf, size_t len) { - int i, c, fd; + int i, c; - for(i = 0, c = 0; i < MAX_SERVERS; i++) { - if ((fd = server_fd[i]) > 0 && fd != sfd) { + 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++; + ++c; } } @@ -482,7 +446,9 @@ int charif_sendallwos(int sfd, unsigned char *buf, unsigned int len) bool check_encrypted(const char* str1, const char* str2, const char* passwd) { char md5str[64], md5bin[32]; - snprintf(md5str, sizeof(md5str), "%s%s", str1, str2); md5str[sizeof(md5str)-1] = '\0'; + + snprintf(md5str, sizeof(md5str), "%s%s", str1, str2); + md5str[sizeof(md5str)-1] = '\0'; MD5_String2binary(md5str, md5bin); return (0==memcmp(passwd, md5bin, 16)); @@ -512,134 +478,144 @@ bool check_password(struct login_session_data* ld, int passwdenc, const char* pa int mmo_auth(struct mmo_account* account, int fd) { time_t ban_until_time; - char t_uid[256]; + char esc_userid[NAME_LENGTH*2+1];// escaped username char user_password[256], password[256]; long connect_until; int state; + size_t len; + char* data; char ip[16]; - uint32 ipl = session[fd]->client_addr; - uint8* sin_addr = (uint8*)&ipl; - sprintf(ip, "%d.%d.%d.%d", sin_addr[3], sin_addr[2], sin_addr[1], sin_addr[0]); + uint8* sin_addr = (uint8*)&session[fd]->client_addr; + sprintf(ip, "%u.%u.%u.%u", sin_addr[3], sin_addr[2], sin_addr[1], sin_addr[0]); // DNS Blacklist check - if(login_config.use_dnsbl) + if( login_config.use_dnsbl ) { char r_ip[16]; char ip_dnsbl[256]; char *dnsbl_serv; bool matched = false; - sprintf(r_ip, "%d.%d.%d.%d", sin_addr[0], sin_addr[1], sin_addr[2], sin_addr[3]); + sprintf(r_ip, "%u.%u.%u.%u", sin_addr[0], sin_addr[1], sin_addr[2], sin_addr[3]); - for (dnsbl_serv = strtok(login_config.dnsbl_servs,","); dnsbl_serv != NULL; dnsbl_serv = strtok(NULL,",")) + for( dnsbl_serv = strtok(login_config.dnsbl_servs,","); !matched && dnsbl_serv != NULL; dnsbl_serv = strtok(NULL,",") ) { - if (!matched) { - sprintf(ip_dnsbl, "%s.%s", r_ip, dnsbl_serv); - if(host2ip(ip_dnsbl)) - matched = true; - } + sprintf(ip_dnsbl, "%s.%s", r_ip, dnsbl_serv); + if( host2ip(ip_dnsbl) ) + matched = true; } - if (matched) { + if( matched ) + { ShowInfo("DNSBL: (%s) Blacklisted. User Kicked.\n", r_ip); return 3; } } + //Client Version check + if( login_config.check_client_version && account->version != 0 && + account->version != login_config.client_version_to_connect ) + return 5; + + len = strnlen(account->userid, NAME_LENGTH); + // Account creation with _M/_F - if (login_config.new_account_flag) + if( login_config.new_account_flag ) { - int len = strlen(account->userid) - 2; - if (account->passwdenc == 0 && account->userid[len] == '_' && - (account->userid[len+1] == 'F' || account->userid[len+1] == 'M' || - account->userid[len+1] == 'f' || account->userid[len+1] == 'm') && - len >= 4 && strlen(account->passwd) >= 4) + if( len > 2 && strnlen(account->passwd, NAME_LENGTH) >= 4 && // valid user and password lengths + account->passwdenc == 0 &&// unencoded password + account->userid[len-2] == '_' && memchr("FfMm", (unsigned char)account->userid[len-1], 4) ) // _M/_F suffix { int result; - account->userid[len] = '\0'; //Terminating the name. - if ((result = mmo_auth_new(account, account->userid[len+1]))) - return result; //Failed to make account. [Skotlex]. + account->userid[len-2] = '\0';// terminate the name. + result = mmo_auth_new(account, account->userid[len-1]); + if( result ) + return result;// Failed to make account. [Skotlex]. } } - jstrescapecpy(t_uid,account->userid); + // escape username + Sql_EscapeStringLen(sql_handle, esc_userid, account->userid, len); // retrieve login entry for the specified username - sprintf(tmpsql, "SELECT `%s`,`%s`,`lastlogin`,`sex`,`connect_until`,`ban_until`,`state`,`%s`" - " FROM `%s` WHERE `%s`= %s '%s'", login_db_account_id, login_db_user_pass, login_db_level, login_db, login_db_userid, login_config.case_sensitive ? "BINARY" : "", t_uid); + if( SQL_ERROR == Sql_Query(sql_handle, + "SELECT `%s`,`%s`,`lastlogin`,`sex`,`connect_until`,`ban_until`,`state`,`%s` FROM `%s` WHERE `%s`= %s '%s'", + login_db_account_id, login_db_user_pass, login_db_level, + login_db, login_db_userid, (login_config.case_sensitive ? "BINARY" : ""), esc_userid) ) + Sql_ShowDebug(sql_handle); //login {0-account_id/1-user_pass/2-lastlogin/3-sex/4-connect_untl/5-ban_until/6-state/7-level} - // query - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } - sql_res = mysql_store_result(&mysql_handle) ; - if (!sql_res) { - ShowError("mmo_auth DB result error ! \n"); - return 0; - } - sql_row = mysql_fetch_row(sql_res); - if (!sql_row) { - //there's no id. - ShowNotice("auth failed: no such account %s\n", account->userid); - mysql_free_result(sql_res); + if( Sql_NumRows(sql_handle) == 0 ) // no such entry + { + ShowNotice("auth failed: no such account '%s'\n", esc_userid); + Sql_FreeResult(sql_handle); return 0; } - account->account_id = atoi(sql_row[0]); - strncpy(password, sql_row[1], sizeof(password)-1); - strncpy(account->lastlogin, sql_row[2], 24); - account->sex = sql_row[3][0] == 'S' ? 2 : sql_row[3][0]=='M' ? 1 : 0; - connect_until = atol(sql_row[4]); - ban_until_time = atol(sql_row[5]); - state = atoi(sql_row[6]); - account->level = atoi(sql_row[7]); - if (account->level > 99) account->level = 99; - - //This function has too many leaks because this is only free'd on the end. - //Better avoid that and free it as soon as possible. [Skotlex] - mysql_free_result(sql_res); + Sql_NextRow(sql_handle); //TODO: error checking? - //Client Version check - if(login_config.check_client_version && account->version != 0 && - account->version != login_config.client_version_to_connect) - return 5; + Sql_GetData(sql_handle, 0, &data, &len); + account->account_id = atoi(data); - switch (state) { - case -3: //id is banned - case -2: //dynamic ban - return state; + Sql_GetData(sql_handle, 1, &data, &len); + if( len > sizeof(password) - 1 ) + { +#if defined(DEBUG) + ShowDebug("mmo_auth: password buffer is too small (len=%u,buflen=%u)\n", len, sizeof(password)); +#endif + len = sizeof(password) - 1; } + memcpy(password, data, len); + password[len] = '\0'; + + Sql_GetData(sql_handle, 2, &data, &len); safestrncpy(account->lastlogin, data, sizeof(account->lastlogin)); + Sql_GetData(sql_handle, 3, &data, &len); account->sex = (*data == 'S' ? 2 : *data == 'M' ? 1 : 0); + Sql_GetData(sql_handle, 4, &data, &len); connect_until = atol(data); + Sql_GetData(sql_handle, 5, &data, &len); ban_until_time = atol(data); + Sql_GetData(sql_handle, 6, &data, &len); state = atoi(data); + Sql_GetData(sql_handle, 7, &data, &len); account->level = atoi(data); + if( account->level > 99 ) + account->level = 99; - if (login_config.use_md5_passwds) + Sql_FreeResult(sql_handle); + + if( login_config.use_md5_passwds ) MD5_String(account->passwd, user_password); else - memcpy(user_password, account->passwd, NAME_LENGTH); + safestrncpy(user_password, account->passwd, NAME_LENGTH); - if (!check_password(session[fd]->session_data, account->passwdenc, user_password, password)) + if( !check_password(session[fd]->session_data, account->passwdenc, user_password, password) ) { - ShowInfo("Invalid password (account: %s, pass: %s, received pass: %s, ip: %s)\n", - account->userid, password, (account->passwdenc) ? "[MD5]" : account->passwd, ip); + ShowInfo("Invalid password (account: '%s', pass: '%s', received pass: '%s', ip: %s)\n", + esc_userid, password, (account->passwdenc) ? "[MD5]" : user_password, ip); return 1; // 1 = Incorrect Password } - if (ban_until_time != 0) { // if account is banned - if (ban_until_time > time(NULL)) // always banned + if( connect_until != 0 && connect_until < time(NULL) ) + return 2; // 2 = This ID is expired + + if( ban_until_time != 0 ) + {// account is banned + if( ban_until_time > time(NULL) )// still banned return 6; // 6 = Your are Prohibited to log in until %s - sprintf(tmpsql, "UPDATE `%s` SET `ban_until`='0' %s WHERE `%s`= '%d'", - login_db, state==7?",state='0'":"", - login_db_account_id, account->account_id); - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `ban_until`='0' %s WHERE `%s`= '%d'", + login_db, (state == 7 ? ",state='0'" : ""), login_db_account_id, account->account_id) ) + Sql_ShowDebug(sql_handle); } - if (state) - switch(state) { // packet 0x006a value + 1 + switch( state ) + { + case -3: //id is banned + case -2: //dynamic ban + return state; + } + + switch( state ) + {// packet 0x006a value + 1 + case 0: + break; case 1: // 0 = Unregistered ID case 2: // 1 = Incorrect Password case 3: // 2 = This ID is expired @@ -668,19 +644,18 @@ int mmo_auth(struct mmo_account* account, int fd) return 99; // 99 = ID has been totally erased } - if (connect_until != 0 && connect_until < time(NULL)) - return 2; // 2 = This ID is expired - - if (login_config.online_check) { - struct online_login_data* data = idb_get(online_db,account->account_id); - if (data && data->char_server > -1) { + if( login_config.online_check ) + { + struct online_login_data* data = idb_get(online_db, account->account_id); + if( data && data->char_server > -1 ) + { //Request char servers to kick this account out. [Skotlex] - unsigned char buf[8]; - ShowNotice("User [%s] is already online - Rejected.\n",account->userid); + uint8 buf[8]; + ShowNotice("User '%s' is already online - Rejected.\n", account->userid); WBUFW(buf,0) = 0x2734; WBUFL(buf,2) = account->account_id; charif_sendallwos(-1, buf, 6); - if (data->waiting_disconnect == -1) + if( data->waiting_disconnect == -1 ) data->waiting_disconnect = add_timer(gettick()+30000, waiting_disconnect_timer, account->account_id, 0); return 3; // Rejected } @@ -689,30 +664,30 @@ int mmo_auth(struct mmo_account* account, int fd) account->login_id1 = rand(); account->login_id2 = rand(); - if (account->sex != 2 && account->account_id < START_ACCOUNT_NUM) + if( account->sex != 2 && account->account_id < START_ACCOUNT_NUM ) ShowWarning("Account %s has account id %d! Account IDs must be over %d to work properly!\n", account->userid, account->account_id, START_ACCOUNT_NUM); - sprintf(tmpsql, "UPDATE `%s` SET `lastlogin` = NOW(), `logincount`=`logincount` +1, `last_ip`='%s' WHERE `%s` = '%d'", - login_db, ip, login_db_account_id, account->account_id); - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } - return -1; + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `lastlogin` = NOW(), `logincount`=`logincount`+1, `last_ip`='%s' WHERE `%s` = '%d'", + login_db, ip, login_db_account_id, account->account_id) ) + Sql_ShowDebug(sql_handle); + + return -1; // account OK } static int online_db_setoffline(DBKey key, void* data, va_list ap) { - struct online_login_data *p = (struct online_login_data *)data; + struct online_login_data* p = (struct online_login_data*)data; int server = va_arg(ap, int); - if (server == -1) { + if( server == -1 ) + { p->char_server = -1; - if (p->waiting_disconnect != -1) + if( p->waiting_disconnect != -1 ) { delete_timer(p->waiting_disconnect, waiting_disconnect_timer); p->waiting_disconnect = -1; } - } else if (p->char_server == server) + } + else if( p->char_server == server ) p->char_server = -2; //Char server disconnected. return 0; } @@ -728,44 +703,40 @@ int parse_fromchar(int fd) char ip[16]; ip2str(ipl, ip); - for(id = 0; id < MAX_SERVERS; id++) - if (server_fd[id] == fd) + for( id = 0; id < MAX_SERVERS; ++id ) + if( server_fd[id] == fd ) break; - if (id == MAX_SERVERS) { // not a char server + if( id == MAX_SERVERS ) + {// not a char server set_eof(fd); do_close(fd); return 0; } - if(session[fd]->eof) { + if( session[fd]->eof ) + { ShowStatus("Char-server '%s' has disconnected.\n", server[id].name); server_fd[id] = -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. - sprintf(tmpsql, "DELETE FROM `sstatus` WHERE `index`='%d'", id); - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } + 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) ) + Sql_ShowDebug(sql_handle); do_close(fd); return 0; } - while (RFIFOREST(fd) >= 2) + while( RFIFOREST(fd) >= 2 ) { uint16 command = RFIFOW(fd,0); - switch (command) + switch( command ) { case 0x2709: // request from map-server via char-server to reload GM accounts - if (login_config.log_login) + if( login_config.log_login ) { - sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`log`) VALUES (NOW(), '%u', '%s', 'GM reload request')", loginlog_db, ipl, server[id].name); - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } + 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); } read_gm_account(); // send GM accounts to all char-servers @@ -774,12 +745,13 @@ int parse_fromchar(int fd) break; case 0x2712: // request from char-server to authenticate an account - if (RFIFOREST(fd) < 19) + if( RFIFOREST(fd) < 19 ) return 0; { int account_id; account_id = RFIFOL(fd,2); // speed up - for(i = 0; i < AUTH_FIFO_SIZE; i++) { + for( i = 0; i < AUTH_FIFO_SIZE; ++i ) + { if( auth_fifo[i].account_id == account_id && auth_fifo[i].login_id1 == RFIFOL(fd,6) && auth_fifo[i].login_id2 == RFIFOL(fd,10) && @@ -792,30 +764,45 @@ int parse_fromchar(int fd) } } - if (i != AUTH_FIFO_SIZE && account_id > 0) { // send ack - time_t connect_until_time = 0; - char email[40] = ""; - account_id=RFIFOL(fd,2); - sprintf(tmpsql, "SELECT `email`,`connect_until` FROM `%s` WHERE `%s`='%d'", login_db, login_db_account_id, account_id); - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } - sql_res = mysql_store_result(&mysql_handle) ; - if (sql_res) { - sql_row = mysql_fetch_row(sql_res); - connect_until_time = atol(sql_row[1]); - strncpy(email, sql_row[0], 40); email[39] = 0; - mysql_free_result(sql_res); + if( i != AUTH_FIFO_SIZE && account_id > 0 ) + {// send ack + uint32 connect_until_time = 0; + char email[40]; + + memset(email, 0, sizeof(email)); + account_id = RFIFOL(fd,2); + 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) ) + { + char* data = NULL; + size_t len = 0; + + Sql_GetData(sql_handle, 0, &data, &len); + if( len > sizeof(email) ) + { +#if defined(DEBUG) + ShowDebug("parse_fromchar:0x2712: email is too long (len=%u,maxlen=%u)\n", len, sizeof(email)); +#endif + len = sizeof(email); + } + memcpy(email, data, len); + + Sql_GetData(sql_handle, 1, &data, NULL); + connect_until_time = (uint32)strtoul(data, NULL, 10); + + Sql_FreeResult(sql_handle); } WFIFOHEAD(fd,51); WFIFOW(fd,0) = 0x2713; WFIFOL(fd,2) = account_id; WFIFOB(fd,6) = 0; memcpy(WFIFOP(fd, 7), email, 40); - WFIFOL(fd,47) = (unsigned long) connect_until_time; + WFIFOL(fd,47) = connect_until_time; WFIFOSET(fd,51); - } else { + } + else + { WFIFOHEAD(fd,51); WFIFOW(fd,0) = 0x2713; WFIFOL(fd,2) = account_id; @@ -832,17 +819,13 @@ int parse_fromchar(int fd) return 0; // how many users on world? (update) - if (server[id].users != RFIFOL(fd,2)) + if( server[id].users != RFIFOL(fd,2) ) { ShowStatus("set users %s : %d\n", server[id].name, RFIFOL(fd,2)); server[id].users = RFIFOL(fd,2); - sprintf(tmpsql,"UPDATE `sstatus` SET `user` = '%d' WHERE `index` = '%d'", server[id].users, id); - // query - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `sstatus` SET `user` = '%d' WHERE `index` = '%d'", server[id].users, id) ) + Sql_ShowDebug(sql_handle); } // send some answer WFIFOHEAD(fd,6); @@ -853,31 +836,44 @@ int parse_fromchar(int fd) 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) + if( RFIFOREST(fd) < 6 ) return 0; { int account_id; - time_t connect_until_time = 0; - char email[40] = ""; + uint32 connect_until_time = 0; + char email[40]; + + memset(email, 0, sizeof(email)); account_id = RFIFOL(fd,2); - sprintf(tmpsql,"SELECT `email`,`connect_until` FROM `%s` WHERE `%s`='%d'",login_db, login_db_account_id, account_id); - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } - sql_res = mysql_store_result(&mysql_handle) ; - if (sql_res) { - sql_row = mysql_fetch_row(sql_res); - connect_until_time = atol(sql_row[1]); - strcpy(email, sql_row[0]); + + 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); + else if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) + { + char* data; + 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); + + Sql_GetData(sql_handle, 1, &data, NULL); + connect_until_time = (uint32)strtoul(data, NULL, 10); + + Sql_FreeResult(sql_handle); } - mysql_free_result(sql_res); //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,46) = (unsigned long) connect_until_time; + WFIFOL(fd,46) = connect_until_time; WFIFOSET(fd,50); RFIFOSKIP(fd,6); @@ -905,43 +901,58 @@ int parse_fromchar(int fd) if (RFIFOREST(fd) < 86) return 0; { - int acc; + int account_id; char actual_email[40], new_email[40]; - acc = RFIFOL(fd,2); + + 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) + 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, acc, ip); - else if (e_mail_check(new_email) == 0) + 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, acc, ip); - else if (strcmpi(new_email, "a@a.com") == 0) + 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, acc, ip); - else { - sprintf(tmpsql, "SELECT `%s`,`email` FROM `%s` WHERE `%s` = '%d'", login_db_userid, login_db, login_db_account_id, acc); - if (mysql_query(&mysql_handle, tmpsql)) + 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) ) + { + char* data; + size_t len; + + Sql_GetData(sql_handle, 1, &data, &len); + if( len > sizeof(actual_email) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); +#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); } - sql_res = mysql_store_result(&mysql_handle); - if (sql_res) { - sql_row = mysql_fetch_row(sql_res); //row fetching - - if (strcmpi(sql_row[1], actual_email) == 0) { - sprintf(tmpsql, "UPDATE `%s` SET `email` = '%s' WHERE `%s` = '%d'", login_db, new_email, login_db_account_id, acc); - // query - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } - 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, acc, sql_row[0], actual_email, ip); + 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); + } + Sql_FreeResult(sql_handle); } RFIFOSKIP(fd, 86); @@ -952,33 +963,31 @@ int parse_fromchar(int fd) if (RFIFOREST(fd) < 10) return 0; { - int acc, statut; - acc = RFIFOL(fd,2); - statut = RFIFOL(fd,6); - sprintf(tmpsql, "SELECT `state` FROM `%s` WHERE `%s` = '%d'", login_db, login_db_account_id, acc); - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } - sql_res = mysql_store_result(&mysql_handle); - if (sql_res) { - sql_row = mysql_fetch_row(sql_res); // row fetching - } - if (atoi(sql_row[0]) != statut && statut != 0) { - unsigned char buf[16]; - WBUFW(buf,0) = 0x2731; - WBUFL(buf,2) = acc; - WBUFB(buf,6) = 0; // 0: change of statut, 1: ban - WBUFL(buf,7) = statut; // status or final date of a banishment - charif_sendallwos(-1, buf, 11); - } - sprintf(tmpsql,"UPDATE `%s` SET `state` = '%d' WHERE `%s` = '%d'", login_db, statut,login_db_account_id,acc); - //query - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); + int account_id, state; + account_id = RFIFOL(fd,2); + 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) ) + { + char* data; + + Sql_GetData(sql_handle, 0, &data, NULL); + if( atoi(data) != state && state != 0 ) + { + uint8 buf[11]; + WBUFW(buf,0) = 0x2731; + WBUFL(buf,2) = account_id; + WBUFB(buf,6) = 0; // 0: change of state, 1: ban + WBUFL(buf,7) = state; // status or final date of a banishment + charif_sendallwos(-1, buf, 11); + } + Sql_FreeResult(sql_handle); } + 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; @@ -987,51 +996,49 @@ int parse_fromchar(int fd) if (RFIFOREST(fd) < 18) return 0; { - int acc; + int account_id; struct tm *tmtime; - time_t timestamp, tmptime; - acc = RFIFOL(fd,2); - sprintf(tmpsql, "SELECT `ban_until` FROM `%s` WHERE `%s` = '%d'",login_db,login_db_account_id,acc); - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } - sql_res = mysql_store_result(&mysql_handle); - if (sql_res) { - sql_row = mysql_fetch_row(sql_res); // row fetching + time_t tmptime = 0; + time_t timestamp = time(NULL); + + 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_SUCCESS == Sql_NextRow(sql_handle) ) + { + char* data; + + Sql_GetData(sql_handle, 0, &data, NULL); + tmptime = (time_t)strtoul(data, NULL, 10); + if( tmptime > time(NULL) ) + timestamp = tmptime; } - tmptime = atol(sql_row[0]); - if (tmptime == 0 || tmptime < time(NULL)) - timestamp = time(NULL); - else - timestamp = tmptime; 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 + (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); timestamp = mktime(tmtime); - if (timestamp != -1) { - if (timestamp <= time(NULL)) + if( timestamp != (time_t)-1 ) + { + if( timestamp <= time(NULL) ) timestamp = 0; - if (tmptime != timestamp) { - if (timestamp != 0) { - unsigned char buf[16]; + if( tmptime != timestamp ) + { + if( timestamp != 0 ) + { + uint8 buf[11]; WBUFW(buf,0) = 0x2731; - WBUFL(buf,2) = acc; + WBUFL(buf,2) = 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 + WBUFL(buf,7) = (uint32)timestamp; // status or final date of a banishment charif_sendallwos(-1, buf, 11); } - ShowNotice("Account: %d Banned until: %ld\n", acc, timestamp); - sprintf(tmpsql, "UPDATE `%s` SET `ban_until` = '%ld' WHERE `%s` = '%d'", login_db, (unsigned long)timestamp, login_db_account_id, acc); - // query - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } + ShowNotice("Account: %d Banned until: %lu\n", account_id, (unsigned long)timestamp); + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `ban_until` = '%lu' WHERE `%s` = '%d'", login_db, (unsigned long)timestamp, login_db_account_id, account_id) ) + Sql_ShowDebug(sql_handle); } } @@ -1043,110 +1050,106 @@ int parse_fromchar(int fd) if (RFIFOREST(fd) < 6) return 0; { - int acc,sex; - unsigned char buf[16]; - acc = RFIFOL(fd,2); - sprintf(tmpsql,"SELECT `sex` FROM `%s` WHERE `%s` = '%d'",login_db,login_db_account_id,acc); - - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - return 0; - } + int account_id; + int sex; + uint8 buf[16]; + + 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) ) + { + char* data; - sql_res = mysql_store_result(&mysql_handle) ; + Sql_GetData(sql_handle, 0, &data, NULL); + if( *data == 'M' || *data == 'm' ) + sex = 0; //Change to female + else + sex = 1; //Change to male - if (sql_res) { - if (mysql_num_rows(sql_res) == 0) { - mysql_free_result(sql_res); - return 0; - } - sql_row = mysql_fetch_row(sql_res); //row fetching - } + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `sex` = '%c' WHERE `%s` = '%d'", login_db, (sex ? 'M' : 'F'), login_db_account_id, account_id) ) + Sql_ShowDebug(sql_handle); - if (strcmpi(sql_row[0], "M") == 0) - sex = 0; //Change to female - else - sex = 1; //Change to make - sprintf(tmpsql,"UPDATE `%s` SET `sex` = '%c' WHERE `%s` = '%d'", login_db, (sex?'M':'F'), login_db_account_id, acc); - //query - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); + WBUFW(buf,0) = 0x2723; + WBUFL(buf,2) = account_id; + WBUFB(buf,6) = sex; + charif_sendallwos(-1, buf, 7); } - WBUFW(buf,0) = 0x2723; - WBUFL(buf,2) = acc; - WBUFB(buf,6) = sex; - charif_sendallwos(-1, buf, 7); RFIFOSKIP(fd,6); } break; case 0x2728: // save account_reg2 - if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) + if( RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2) ) return 0; - if (RFIFOL(fd,4) > 0) { - int acc,p,j,len; - char str[32]; - char temp_str[64]; //Needs twice as much space as the original string. - char temp_str2[512]; - char value[256]; - unsigned char *buf; - acc = RFIFOL(fd,4); - buf = (unsigned char*)aCalloc(RFIFOW(fd,2)+1, sizeof(unsigned char)); + if( RFIFOL(fd,4) > 0 ) + { + SqlStmt* stmt; + int account_id; + size_t off; + + account_id = RFIFOL(fd,4); + //Delete all global account variables.... - sprintf(tmpsql,"DELETE FROM `%s` WHERE `type`='1' AND `account_id`='%d';",reg_db,acc); - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `type`='1' AND `account_id`='%d';", reg_db, account_id) ) + Sql_ShowDebug(sql_handle); + //Proceed to insert them.... - for(j=0,p=13;j<ACCOUNT_REG2_NUM && p<RFIFOW(fd,2);j++){ - sscanf(RFIFOP(fd,p), "%31c%n",str,&len); - str[len]='\0'; - p +=len+1; //+1 to skip the '\0' between strings. - sscanf(RFIFOP(fd,p), "%255c%n",value,&len); - value[len]='\0'; - p +=len+1; - - sprintf(tmpsql,"INSERT INTO `%s` (`type`, `account_id`, `str`, `value`) VALUES ( 1 , '%d' , '%s' , '%s');", reg_db, acc, jstrescapecpy(temp_str,str), jstrescapecpy(temp_str2,value)); - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } + stmt = SqlStmt_Malloc(sql_handle); + if( SQL_ERROR == SqlStmt_Prepare(stmt, "INSERT INTO `%s` (`type`, `account_id`, `str`, `value`) VALUES ( 1 , '%d' , ? , ?);", reg_db, account_id) ) + SqlStmt_ShowDebug(stmt); + for( i = 0, off = 13; i < ACCOUNT_REG2_NUM && off < RFIFOW(fd,2); ++i ) + { + uint8* p; + size_t len; + + // str + p = (uint8*)RFIFOP(fd,off); + len = strlen(p); + SqlStmt_BindParam(stmt, 0, SQLDT_STRING, p, len); + off += len + 1; + + // value + p = (uint8*)RFIFOP(fd,off); + len = strlen(p); + SqlStmt_BindParam(stmt, 1, SQLDT_STRING, p, len); + off += len + 1; + + if( SQL_ERROR == SqlStmt_Execute(stmt) ) + SqlStmt_ShowDebug(stmt); + } + 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)); } - - // Send to char - memcpy(WBUFP(buf,0),RFIFOP(fd,0),RFIFOW(fd,2)); - WBUFW(buf,0)=0x2729; - charif_sendallwos(fd,buf,WBUFW(buf,2)); - if (buf) aFree(buf); } RFIFOSKIP(fd,RFIFOW(fd,2)); break; case 0x272a: // Receiving of map-server via char-server an unban request - if (RFIFOREST(fd) < 6) + if( RFIFOREST(fd) < 6 ) return 0; { - int acc; - acc = RFIFOL(fd,2); - sprintf(tmpsql,"SELECT `ban_until` FROM `%s` WHERE `%s` = '%d'",login_db,login_db_account_id,acc); - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } - sql_res = mysql_store_result(&mysql_handle) ; - if (sql_res && mysql_num_rows(sql_res) > 0) { //Found a match - sprintf(tmpsql,"UPDATE `%s` SET `ban_until` = '0' WHERE `%s` = '%d'", login_db,login_db_account_id,acc); - //query - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } + int account_id; + + 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 ) + {// Found a match + 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); } - if (sql_res) mysql_free_result(sql_res); RFIFOSKIP(fd,6); return 0; @@ -1194,33 +1197,36 @@ int parse_fromchar(int fd) { int account_id = RFIFOL(fd, 2); int char_id = RFIFOL(fd, 6); - int p; - sprintf(tmpsql, "SELECT `str`,`value` FROM `%s` WHERE `type`='1' AND `account_id`='%d'",reg_db, account_id); - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - break; - } - sql_res = mysql_store_result(&mysql_handle) ; - if (!sql_res) { - break; - } + 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); + 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 - p = 13; - while ((sql_row = mysql_fetch_row(sql_res)) && p < 9000) { - if (sql_row[0][0]) { - p+= sprintf(WFIFOP(fd,p), "%s", sql_row[0])+1; //We add 1 to consider the '\0' in place. - p+= sprintf(WFIFOP(fd,p), "%s", sql_row[1])+1; + off = 13; + while( SQL_SUCCESS == Sql_NextRow(sql_handle) && off < 9000 ) + { + char* data; + + // str + Sql_GetData(sql_handle, 0, &data, NULL); + if( *data != '\0' ) + { + off += sprintf(WFIFOP(fd,off), "%s", data)+1; //We add 1 to consider the '\0' in place. + + // value + Sql_GetData(sql_handle, 1, &data, NULL); + off += sprintf(WFIFOP(fd,off), "%s", data)+1; } } - mysql_free_result(sql_res); - if (p >= 9000) + 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) = p; + WFIFOW(fd,2) = (uint16)off; WFIFOSET(fd,WFIFOW(fd,2)); RFIFOSKIP(fd,10); @@ -1258,53 +1264,39 @@ int parse_fromchar(int fd) int lan_subnetcheck(uint32 ip) { int i; - - for(i = 0; i < subnet_count; i++) { - if(subnet[i].subnet == (ip & subnet[i].mask)) { - return subnet[i].char_ip; - } - } - - return 0; + ARR_FIND( 0, subnet_count, i, subnet[i].subnet == (ip & subnet[i].mask) ); + return ( i < subnet_count ) ? subnet[i].char_ip : 0; } int login_ip_ban_check(uint32 ip) { uint8* p = (uint8*)&ip; - sprintf(tmpsql, "SELECT count(*) FROM `ipbanlist` WHERE `list` = '%d.*.*.*' OR `list` = '%d.%d.*.*' OR `list` = '%d.%d.%d.*' OR `list` = '%d.%d.%d.%d'", - p[3], p[3], p[2], p[3], p[2], p[1], p[3], p[2], p[1], p[0]); - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); + char* data = NULL; + int matches; + + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT count(*) FROM `ipbanlist` WHERE `list` = '%u.*.*.*' OR `list` = '%u.%u.*.*' OR `list` = '%u.%u.%u.*' OR `list` = '%u.%u.%u.%u'", + p[3], p[3], p[2], p[3], p[2], p[1], p[3], p[2], p[1], p[0]) ) + { + Sql_ShowDebug(sql_handle); // close connection because we can't verify their connectivity. return 1; } - sql_res = mysql_store_result(&mysql_handle) ; - sql_row = sql_res?mysql_fetch_row(sql_res):NULL; - if(!sql_row) { //Shouldn't happen, but just in case... - mysql_free_result(sql_res); - return 1; - } + if( SQL_ERROR == Sql_NextRow(sql_handle) ) + return 1;// Shouldn't happen, but just in case... + + Sql_GetData(sql_handle, 0, &data, NULL); + matches = atoi(data); + Sql_FreeResult(sql_handle); + + if( matches == 0 ) + return 0;// No ban - if (atoi(sql_row[0]) == 0) { //No ban - mysql_free_result(sql_res); - return 0; - } - // ip ban ok. - ShowInfo("Packet from banned ip : %d.%d.%d.%d\n", CONVIP(ip)); + ShowInfo("Packet from banned ip : %u.%u.%u.%u\n", CONVIP(ip)); - if (login_config.log_login) - { - sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', 'unknown','-3', 'ip banned')", loginlog_db, ip); - // query - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } - } - mysql_free_result(sql_res); + 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; } @@ -1313,7 +1305,7 @@ int login_ip_ban_check(uint32 ip) //---------------------------------------------------------------------------------------- int parse_login(int fd) { - char t_uid[100]; + char esc_userid[NAME_LENGTH*2+1];// escaped username struct mmo_account account; int result, i; uint32 ipl = session[fd]->client_addr; @@ -1321,16 +1313,17 @@ int parse_login(int fd) ip2str(ipl, ip); - if (session[fd]->eof) { + if( session[fd]->eof ) + { do_close(fd); return 0; } - while (RFIFOREST(fd) >= 2) + while( RFIFOREST(fd) >= 2 ) { uint16 command = RFIFOW(fd,0); - switch(command) + switch( command ) { case 0x0200: // New alive packet: structure: 0x200 <account.userid>.24B. used to verify if client is always alive. if (RFIFOREST(fd) < 26) @@ -1349,10 +1342,10 @@ 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) { - int packet_len = RFIFOREST(fd); + size_t packet_len = RFIFOREST(fd); - //Perform ip-ban check - if (login_config.ipban && login_ip_ban_check(ipl)) + // Perform ip-ban check + if( login_config.ipban && login_ip_ban_check(ipl) ) { WFIFOHEAD(fd,23); WFIFOW(fd,0) = 0x6a; @@ -1376,37 +1369,38 @@ 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'; - memcpy(account.passwd,RFIFOP(fd,30),NAME_LENGTH); account.passwd[23] = '\0'; + if( !account.version ) + account.version = 1; //Force some version... + safestrncpy(account.userid, RFIFOP(fd,6), NAME_LENGTH);//## does it have to be nul-terminated? + safestrncpy(account.passwd, RFIFOP(fd,30), NAME_LENGTH);//## does it have to be nul-terminated? account.passwdenc = (command != 0x01dd) ? 0 : PASSWORDENC; - jstrescapecpy(t_uid, account.userid); + Sql_EscapeStringLen(sql_handle, esc_userid, account.userid, strlen(account.userid)); result = mmo_auth(&account, fd); - if (result == -1) { // auth success - if (login_config.min_level_to_connect > account.level) { + if( result == -1 ) + { // auth success + if( login_config.min_level_to_connect > account.level ) + { WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x81; WFIFOB(fd,2) = 1; // 01 = Server closed WFIFOSET(fd,3); - } else { - if (login_config.log_login) { - sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', '%s','100', 'login ok')", loginlog_db, ipl, t_uid); - //query - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } - } - if (account.level) + } + else + { + 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); server_num = 0; - WFIFOHEAD(fd,47+32*MAX_SERVERS); - for(i = 0; i < MAX_SERVERS; i++) { - if (server_fd[i] >= 0) { + WFIFOHEAD(fd, 47+32*MAX_SERVERS); + 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); @@ -1443,7 +1437,9 @@ int parse_login(int fd) WFIFOSET(fd,3); } } - } else { // auth failed + } + else + { // auth failed if (login_config.log_login) { const char* error; @@ -1475,70 +1471,66 @@ int parse_login(int fd) default : error = "Unknown Error."; break; } - sprintf(tmpsql, "INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', '%s', '%d','login failed : %s')", loginlog_db, ipl, t_uid, result, error); - - //query - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } + 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, ipl, esc_userid, result, error) ) + Sql_ShowDebug(sql_handle); } - if ((result == 1) && login_config.dynamic_pass_failure_ban && login_config.log_login) { // failed password - sprintf(tmpsql,"SELECT count(*) FROM `%s` WHERE `ip` = '%u' AND `rcode` = '1' AND `time` > NOW() - INTERVAL %d MINUTE", - loginlog_db, ipl, login_config.dynamic_pass_failure_ban_interval); //how many times filed account? in one ip. - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } - //check query result - sql_res = mysql_store_result(&mysql_handle) ; - sql_row = sql_res?mysql_fetch_row(sql_res):NULL; //row fetching + if( result == 1 && login_config.dynamic_pass_failure_ban && login_config.log_login ) // failed password + { + unsigned long failures = 0; + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT count(*) FROM `%s` WHERE `ip` = '%u' AND `rcode` = '1' AND `time` > NOW() - INTERVAL %d MINUTE", + loginlog_db, ipl, login_config.dynamic_pass_failure_ban_interval) )// how many times failed account? in one ip. + Sql_ShowDebug(sql_handle); - if (sql_row && (unsigned int)atoi(sql_row[0]) >= login_config.dynamic_pass_failure_ban_limit ) { + //check query result + if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) + { + char* data; + Sql_GetData(sql_handle, 0, &data, NULL); + failures = strtoul(data, NULL, 10); + Sql_FreeResult(sql_handle); + } + if( failures >= login_config.dynamic_pass_failure_ban_limit ) + { uint8* p = (uint8*)&ipl; - sprintf(tmpsql,"INSERT INTO `ipbanlist`(`list`,`btime`,`rtime`,`reason`) VALUES ('%d.%d.%d.*', NOW() , NOW() + INTERVAL %d MINUTE ,'Password error ban: %s')", (uint8)p[3], (uint8)p[2], (uint8)p[1], login_config.dynamic_pass_failure_ban_duration, t_uid); - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `ipbanlist`(`list`,`btime`,`rtime`,`reason`) VALUES ('%u.%u.%u.*', NOW() , NOW() + INTERVAL %d MINUTE ,'Password error ban: %s')", p[3], p[2], p[1], login_config.dynamic_pass_failure_ban_duration, esc_userid) ) + Sql_ShowDebug(sql_handle); } - if(sql_res) mysql_free_result(sql_res); } - else if (result == -2){ //dynamic banned - add ip to ban list. + else if( result == -2 ) + {// dynamic banned - add ip to ban list. uint8* p = (uint8*)&ipl; - sprintf(tmpsql,"INSERT INTO `ipbanlist`(`list`,`btime`,`rtime`,`reason`) VALUES ('%d.%d.%d.*', NOW() , NOW() + INTERVAL 1 MONTH ,'Dynamic banned user id : %s')", (uint8)p[3], (uint8)p[2], (uint8)p[1], t_uid); - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `ipbanlist`(`list`,`btime`,`rtime`,`reason`) VALUES ('%d.%d.%d.*', NOW() , NOW() + INTERVAL 1 MONTH ,'Dynamic banned user id : %s')", p[3], p[2], p[1], esc_userid) ) + Sql_ShowDebug(sql_handle); result = -3; - }else if(result == 6){ //not lastet version .. - //result = 5; } - - sprintf(tmpsql,"SELECT `ban_until` FROM `%s` WHERE `%s` = %s '%s'",login_db, login_db_userid, login_config.case_sensitive ? "BINARY" : "", t_uid); - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); + else if( result == 6 ) + {// not lastet version .. + //result = 5; } - sql_res = mysql_store_result(&mysql_handle) ; - sql_row = sql_res?mysql_fetch_row(sql_res):NULL; //cannot connect login failed WFIFOHEAD(fd,23); memset(WFIFOP(fd,0), '\0', 23); WFIFOW(fd,0) = 0x6a; WFIFOB(fd,2) = (uint8)result; - if (result == 6) { // 6 = Your are Prohibited to log in until %s - char tmpstr[20]; - time_t ban_until_time = (sql_row) ? atol(sql_row[0]) : 0; - strftime(tmpstr, 20, login_config.date_format, localtime(&ban_until_time)); tmpstr[19] = '\0'; - strncpy(WFIFOP(fd,3), tmpstr, 20); // ban timestamp goes here + if( result == 6 ) + {// 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); + else if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) + { + char* data; + time_t ban_until_time; + + Sql_GetData(sql_handle, 0, &data, NULL); + ban_until_time = (time_t)strtoul(data, NULL, 10); + Sql_FreeResult(sql_handle); + + strftime(WFIFOP(fd,3), 20, login_config.date_format, localtime(&ban_until_time)); + } } WFIFOSET(fd,23); - - if (sql_res) mysql_free_result(sql_res); } RFIFOSKIP(fd,packet_len); @@ -1548,19 +1540,20 @@ int parse_login(int fd) case 0x01db: // Sending request of the coding key { struct login_session_data* ld; - if (session[fd]->session_data) { + if( session[fd]->session_data ) + { ShowWarning("login: abnormal request of MD5 key (already opened session).\n"); set_eof(fd); return 0; } - ld = (struct login_session_data*)aCalloc(1, sizeof(struct login_session_data)); + CREATE(ld, struct login_session_data, 1); session[fd]->session_data = ld; // Creation of the coding key memset(ld->md5key, '\0', sizeof(ld->md5key)); ld->md5keylen = (uint16)(12 + rand() % 4); - for(i = 0; i < ld->md5keylen; i++) + for( i = 0; i < ld->md5keylen; ++i ) ld->md5key[i] = (char)(1 + rand() % 255); WFIFOHEAD(fd,4 + ld->md5keylen); @@ -1577,37 +1570,32 @@ int parse_login(int fd) if (RFIFOREST(fd) < 86) return 0; { + char esc_server_name[20*2+1]; char* server_name; uint32 server_ip; uint16 server_port; memset(&account, 0, sizeof(account)); - memcpy(account.userid,RFIFOP(fd,2),NAME_LENGTH); account.userid[23] = '\0'; - memcpy(account.passwd,RFIFOP(fd,26),NAME_LENGTH); account.passwd[23] = '\0'; + safestrncpy(account.userid, RFIFOP(fd,2), NAME_LENGTH); + safestrncpy(account.passwd, RFIFOP(fd,26), NAME_LENGTH); account.passwdenc = 0; - server_name = (char*)RFIFOP(fd,60); server_name[20] = '\0'; server_ip = ntohl(RFIFOL(fd,54)); server_port = ntohs(RFIFOW(fd,58)); - ShowInfo("Connection request of the char-server '%s' @ %d.%d.%d.%d:%d (ip: %s)\n", - server_name, CONVIP(server_ip), server_port, ip); - jstrescapecpy(t_uid, server_name); - if (login_config.log_login) - { - char t_login[50]; - jstrescapecpy(t_login,account.userid); - sprintf(tmpsql,"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, t_login, t_uid, t_uid, CONVIP(server_ip), server_port); - - //query - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } - } + server_name = (char*)RFIFOP(fd,60); + + 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); + + 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); result = mmo_auth(&account, fd); - if (result == -1 && account.sex == 2 && account.account_id < MAX_SERVERS && server_fd[account.account_id] == -1) { - ShowStatus("Connection of the char-server '%s' accepted.\n", server_name); + if( result == -1 && account.sex == 2 && account.account_id < MAX_SERVERS && server_fd[account.account_id] == -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)); @@ -1616,29 +1604,23 @@ int parse_login(int fd) server[account.account_id].maintenance = RFIFOW(fd,82); server[account.account_id].new_ = RFIFOW(fd,84); server_fd[account.account_id] = fd; - sprintf(tmpsql,"DELETE FROM `sstatus` WHERE `index`='%d'", account.account_id); - //query - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } - - sprintf(tmpsql,"INSERT INTO `sstatus`(`index`,`name`,`user`) VALUES ( '%d', '%s', '%d')", - account.account_id, t_uid,0); - //query - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } + WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x2711; WFIFOB(fd,2) = 0; WFIFOSET(fd,3); + session[fd]->func_parse = parse_fromchar; realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); - + send_GM_accounts(fd); // send GM account to char-server - } else { + + 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); WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x2711; WFIFOB(fd,2) = 3; @@ -1668,12 +1650,12 @@ int parse_login(int fd) break; case 0x7532: // Request to end connection - ShowStatus ("End of connection (ip: %s)\n", ip); + ShowStatus("End of connection (ip: %s)\n", ip); set_eof(fd); break; default: - ShowStatus ("Abnormal end of connection (ip: %s): Unknown packet 0x%x\n", ip, RFIFOW(fd,0)); + ShowStatus("Abnormal end of connection (ip: %s): Unknown packet 0x%x\n", ip, RFIFOW(fd,0)); set_eof(fd); return 0; } @@ -1683,6 +1665,9 @@ int parse_login(int fd) return 0; } +//----------------------- +// Console Command Parser [Wizputer] +//----------------------- int parse_console(char* buf) { char command[256]; @@ -1691,20 +1676,22 @@ int parse_console(char* buf) sscanf(buf, "%[^\n]", command); - //login_log("Console command :%s\n", command); + ShowInfo("Console command :%s", command); if( strcmpi("shutdown", command) == 0 || strcmpi("exit", command) == 0 || strcmpi("quit", command) == 0 || strcmpi("end", command) == 0 ) runflag = 0; - else if( strcmpi("alive", command) == 0 || - strcmpi("status", command) == 0 ) + else + if( strcmpi("alive", command) == 0 || + strcmpi("status", command) == 0 ) ShowInfo(CL_CYAN"Console: "CL_BOLD"I'm Alive."CL_RESET"\n"); - else if( strcmpi("help", command) == 0 ){ + else + if( strcmpi("help", command) == 0 ) { printf(CL_BOLD"Help of commands:"CL_RESET"\n"); printf(" To shutdown the server:\n"); - printf(" 'shutdown|exit|qui|end'\n"); + printf(" 'shutdown|exit|quit|end'\n"); printf(" To know if server is alive:\n"); printf(" 'alive|status'\n"); } @@ -1788,10 +1775,8 @@ int login_lan_config_read(const char *lancfgName) //----------------------------------------------------- int ip_ban_flush(int tid, unsigned int tick, int id, int data) { - if(mysql_query(&mysql_handle, "DELETE FROM `ipbanlist` WHERE `rtime` <= NOW()")) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - DELETE FROM `ipbanlist` WHERE `rtime` <= NOW()\n", __FILE__,__LINE__); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `ipbanlist` WHERE `rtime` <= NOW()") ) + Sql_ShowDebug(sql_handle); return 0; } @@ -1909,7 +1894,7 @@ void sql_config_read(const char* cfgName) else if (!strcmpi(w1, "login_server_ip")) strcpy(login_server_ip, w2); else if (!strcmpi(w1, "login_server_port")) - login_server_port = atoi(w2); + login_server_port = (uint16)atoi(w2); else if (!strcmpi(w1, "login_server_id")) strcpy(login_server_id, w2); else if (!strcmpi(w1, "login_server_pw")) |