login.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978
  1. // $Id: login.c,v 1.6 2004/09/19 21:12:07 Valaris Exp $
  2. // original : login2.c 2003/01/28 02:29:17 Rev.1.1.1.1
  3. // txt version 1.100
  4. #include <sys/types.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <time.h>
  8. #include <signal.h>
  9. #include <fcntl.h>
  10. #include <string.h>
  11. #include "timer.h"
  12. #include "login.h"
  13. #include "login_int.h"
  14. #include "char_int.h"
  15. #ifdef PASSWORDENC
  16. #include "md5calc.h"
  17. #endif
  18. #ifdef MEMWATCH
  19. #include "memwatch.h"
  20. #endif
  21. #define J_MAX_MALLOC_SIZE 65535
  22. // Login Listening Port
  23. int login_port = 6900;
  24. struct auth_fifo auth_fifo[AUTH_FIFO_SIZE];
  25. int auth_fifo_pos;
  26. // MySQL Query
  27. char tmpsql[65535], prev_query[65535];
  28. // MySQL Connection Handle
  29. MYSQL mysql_handle;
  30. MYSQL_RES* sql_res ;
  31. MYSQL_ROW sql_row ;
  32. // It's to check IP of a player between login-server and char-server (part of anti-hacking system)
  33. int check_ip_flag;
  34. // Login's FD
  35. int login_fd;
  36. // LAN IP of char-server and subnet mask(Kashy)
  37. char lan_char_ip[16];
  38. int subnetmaski[4];
  39. // Char-server data
  40. struct mmo_char_server server[MAX_SERVERS];
  41. int server_fd[MAX_SERVERS];
  42. unsigned char servers_connected = 0;
  43. // Anti-freeze Data
  44. int server_freezeflag[MAX_SERVERS];
  45. int anti_freeze_enable = 0;
  46. int ANTI_FREEZE_INTERVAL = 15;
  47. // MD5 Key Data for encrypted login
  48. char md5key[20];
  49. int md5keylen = 16;
  50. // Auth FIFO Position
  51. int auth_fifo_pos = 0;
  52. //Added for Mugendai's I'm Alive mod
  53. int imalive_on=0;
  54. int imalive_time=60;
  55. //Added by Mugendai for GUI
  56. int flush_on=1;
  57. int flush_time=100;
  58. // Date format for bans
  59. char date_format[32] = "%Y-%m-%d %H:%M:%S";
  60. // minimum level of player/GM (0: player, 1-99: gm) to connect on the server
  61. int min_level_to_connect = 0;
  62. // It's to check IP of a player between login-server and char-server (part of anti-hacking system)
  63. int check_ip_flag = 1;
  64. // Dynamic IP Ban config
  65. int ipban = 1;
  66. int dynamic_account_ban = 1;
  67. int dynamic_account_ban_class = 0;
  68. int dynamic_pass_failure_ban = 1;
  69. int dynamic_pass_failure_ban_time = 5;
  70. int dynamic_pass_failure_ban_how_many = 3;
  71. int dynamic_pass_failure_ban_how_long = 60;
  72. // MySQL Config
  73. int login_server_port = 3306;
  74. char login_server_ip[16] = "127.0.0.1";
  75. char login_server_id[16] = "ragnarok";
  76. char login_server_pw[16] = "ragnarok";
  77. char login_server_db[16] = "ragnarok";
  78. int use_md5_passwds = 0;
  79. // MySQL custom table and column names
  80. char login_db[32] = "login";
  81. char loginlog_db[32] = "loginlog";
  82. char login_db_account_id[32] = "account_id";
  83. char login_db_userid[32] = "userid";
  84. char login_db_user_pass[32] = "user_pass";
  85. char login_db_level[32] = "level";
  86. // Console interface on/off
  87. int console = 0;
  88. // Online User DB
  89. struct dbt *online_db;
  90. // GM Database
  91. struct dbt *gm_db;
  92. int lowest_gm_level = 1;
  93. //-----------------------------------------------------
  94. // Online User Database [Wizputer]
  95. //-----------------------------------------------------
  96. void add_online_user(int account_id) {
  97. int *p;
  98. p = malloc(sizeof(int));
  99. if (p == NULL) {
  100. printf("add_online_user: memory allocation failure (malloc)!\n");
  101. exit(0);
  102. }
  103. p = &account_id;
  104. numdb_insert(online_db, account_id, p);
  105. }
  106. int is_user_online(int account_id) {
  107. int *p;
  108. p = numdb_search(online_db, account_id);
  109. if (p == NULL)
  110. return 0;
  111. #ifdef DEBUG
  112. printf("Acccount [%d] Online\n",*p);
  113. #endif
  114. return 1;
  115. }
  116. void remove_online_user(int account_id) {
  117. int *p;
  118. p = numdb_erase(online_db,account_id);
  119. free(p);
  120. }
  121. //----------------------------------------------
  122. //SQL Commands ( Original by Clownisius ) [Edit: Wizputer]
  123. //----------------------------------------------
  124. void sql_query(char* query,char function[32]) {
  125. if(mysql_query(&mysql_handle, query)){
  126. printf("---------- SQL error report ----------\n");
  127. printf("MySQL Server Error: %s\n", mysql_error(&mysql_handle));
  128. printf("Query: %s\n", query);
  129. printf("In function: %s \n", function);
  130. printf("\nPrevious query: %s\n", prev_query);
  131. // if (strcmp(mysql_error(&mysql_handle),"CR_COMMANDS_OUT_OF_SYNC") !=0) printf(" - = Shutting down Char Server = - \n\n");
  132. printf("-------- End SQL Error Report --------\n");
  133. // printf("Uncontrolled param: %s",&mysql_handle);
  134. // if (strcmp(mysql_error(&mysql_handle),"CR_COMMANDS_OUT_OF_SYNC") !=0) exit(1);
  135. }
  136. strcpy(prev_query,query);
  137. }
  138. //-----------------------------------------------------
  139. // check user level [Wizputer]
  140. //-----------------------------------------------------
  141. unsigned char isGM(int account_id) {
  142. unsigned char *level;
  143. level = numdb_search(gm_db, account_id);
  144. if (level == NULL)
  145. return 0;
  146. return *level;
  147. }
  148. static int gmdb_final(void *key,void *data,va_list ap) {
  149. unsigned char *level;
  150. nullpo_retr(0, level=data);
  151. free(level);
  152. return 0;
  153. }
  154. void do_final_gmdb(void) {
  155. if(gm_db){
  156. numdb_final(gm_db,gmdb_final);
  157. gm_db=NULL;
  158. }
  159. }
  160. void read_GMs(int fd) {
  161. unsigned char *level;
  162. int i=0;
  163. if(gm_db)
  164. do_final_gmdb();
  165. gm_db = numdb_init();
  166. sprintf(tmpsql,"SELECT `%s`,`%s` FROM `%s` WHERE `%s` > '%d'", login_db_account_id, login_db_level, login_db,login_db_level,lowest_gm_level);
  167. sql_query(tmpsql,"read_GMs");
  168. WFIFOW(fd, 0) = 0x2732;
  169. if ((sql_res = mysql_store_result(&mysql_handle))) {
  170. for(i=0;(sql_row = mysql_fetch_row(sql_res));i++) {
  171. level = malloc(sizeof(unsigned char));
  172. if( (*level = atoi(sql_row[1])) > 99 )
  173. *level = 99;
  174. numdb_insert(gm_db, atoi(sql_row[0]), level);
  175. WFIFOL(fd,6+5*i) = atoi(sql_row[0]);
  176. WFIFOB(fd,10+5*i) = *level;
  177. }
  178. WFIFOW(fd,2) = i;
  179. }
  180. WFIFOSET(fd,6+5*i);
  181. mysql_free_result(sql_res);
  182. }
  183. //---------------------------------------------------
  184. // E-mail check: return 0 (not correct) or 1 (valid).
  185. //---------------------------------------------------
  186. int e_mail_check(unsigned char *email) {
  187. char ch;
  188. unsigned char* last_arobas;
  189. // athena limits
  190. if (strlen(email) < 3 || strlen(email) > 39)
  191. return 0;
  192. // part of RFC limits (official reference of e-mail description)
  193. if (strchr(email, '@') == NULL || email[strlen(email)-1] == '@')
  194. return 0;
  195. if (email[strlen(email)-1] == '.')
  196. return 0;
  197. last_arobas = strrchr(email, '@');
  198. if (strstr(last_arobas, "@.") != NULL ||
  199. strstr(last_arobas, "..") != NULL)
  200. return 0;
  201. for(ch = 1; ch < 32; ch++) {
  202. if (strchr(last_arobas, ch) != NULL) {
  203. return 0;
  204. break;
  205. }
  206. }
  207. if (strchr(last_arobas, ' ') != NULL ||
  208. strchr(last_arobas, ';') != NULL)
  209. return 0;
  210. // all correct
  211. return 1;
  212. }
  213. //-----------------------------------------------------
  214. // Connect to MySQL
  215. //-----------------------------------------------------
  216. int mmo_auth_sqldb_init(void) {
  217. printf("Login-server starting...\n");
  218. // memory initialize
  219. #ifdef DEBUG
  220. printf("memory initialize....\n");
  221. #endif
  222. mysql_init(&mysql_handle);
  223. // DB connection start
  224. printf("Connecting to Login Database Server...\n");
  225. if (!mysql_real_connect(&mysql_handle, login_server_ip, login_server_id, login_server_pw,
  226. login_server_db, login_server_port, (char *)NULL, 0)) {
  227. // pointer check
  228. printf("%s\n", mysql_error(&mysql_handle));
  229. exit(1);
  230. } else {
  231. printf("Connected to MySQL Server\n");
  232. }
  233. //delete all server status
  234. sprintf(tmpsql,"TRUNCATE TABLE `sstatus`");
  235. sql_query(tmpsql,"mmo_db_close");
  236. sprintf(tmpsql, "INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '', 'lserver', '100','login server started')", loginlog_db);
  237. sql_query(tmpsql,"mmo_auth_sqldb_init");
  238. return 0;
  239. }
  240. //-----------------------------------------------------
  241. // Close MySQL and Close all sessions
  242. //-----------------------------------------------------
  243. void mmo_db_close(void) {
  244. int i, fd;
  245. //set log.
  246. sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '', 'lserver','100', 'login server shutdown')", loginlog_db);
  247. sql_query(tmpsql,"mmo_db_close");
  248. //delete all server status
  249. sprintf(tmpsql,"TRUNCATE TABLE `sstatus`");
  250. sql_query(tmpsql,"mmo_db_close");
  251. mysql_close(&mysql_handle);
  252. printf("MySQL Connection closed\n");
  253. for (i = 0; i < MAX_SERVERS; i++) {
  254. if ((fd = server_fd[i]) >= 0)
  255. delete_session(fd);
  256. }
  257. delete_session(login_fd);
  258. }
  259. //-----------------------------------------------------
  260. // Auth account
  261. //-----------------------------------------------------
  262. int mmo_auth( struct mmo_account* account , int fd){
  263. struct timeval tv;
  264. char tmpstr[256];
  265. char t_uid[32], t_pass[32];
  266. char user_password[32];
  267. char ip[16];
  268. int encpasswdok = 0;
  269. int state;
  270. #ifdef PASSWORDENC
  271. char logbuf[1024], *p = logbuf;
  272. char md5str[64],md5bin[32];
  273. int j;
  274. #endif
  275. unsigned char *sin_addr = (unsigned char *)&session[fd]->client_addr.sin_addr;
  276. sprintf(ip, "%d.%d.%d.%d", sin_addr[0], sin_addr[1], sin_addr[2], sin_addr[3]);
  277. #ifdef DEBUG
  278. printf ("Starting auth for [%s]...\n",ip);
  279. #endif
  280. // auth start : time seed
  281. gettimeofday(&tv, NULL);
  282. strftime(tmpstr, 24, "%Y-%m-%d %H:%M:%S",localtime(&(tv.tv_sec)));
  283. sprintf(tmpstr+19, ".%03d", (int)tv.tv_usec/1000);
  284. jstrescapecpy(t_uid,account->userid);
  285. jstrescapecpy(t_pass, account->passwd);
  286. // make query
  287. sprintf(tmpsql, "SELECT `%s`,`%s`,`%s`,`lastlogin`,`logincount`,`sex`,`connect_until`,`last_ip`,`ban_until`,`state`,`%s`"
  288. " FROM `%s` WHERE `%s`='%s'", login_db_account_id, login_db_userid, login_db_user_pass, login_db_level, login_db, login_db_userid, t_uid);
  289. //login {0-account_id/1-userid/2-user_pass/3-lastlogin/4-logincount/5-sex/6-connect_untl/7-last_ip/8-ban_until/9-state}
  290. sql_query(tmpsql,"mmo_auth");
  291. if ((sql_res = mysql_store_result(&mysql_handle))) {
  292. if(!(sql_row = mysql_fetch_row(sql_res))) {
  293. #ifdef DEBUG
  294. printf ("Auth failed: No Account Time: [%s] Username: [%s] Password: [%s]\n", tmpstr, account->userid, account->passwd);
  295. #endif
  296. mysql_free_result(sql_res);
  297. return 0;
  298. }
  299. } else {
  300. #ifdef DEBUG
  301. printf("mmo_auth DB result error\n");
  302. #endif
  303. return 0;
  304. }
  305. account->ban_until_time = atol(sql_row[8]);
  306. state = atoi(sql_row[9]);
  307. if (state) {
  308. switch(state) { // packet 0x006a value + 1
  309. case 1: // 0 = Unregistered ID
  310. case 2: // 1 = Incorrect Password
  311. case 3: // 2 = This ID is expired
  312. case 4: // 3 = Rejected from Server
  313. case 5: // 4 = You have been blocked by the GM Team
  314. case 6: // 5 = Your Game's EXE file is not the latest version
  315. case 8: // 7 = Server is jammed due to over populated
  316. case 9: // 8 = No MSG (actually, all states after 9 except 99 are No MSG, use only this)
  317. case 100: // 99 = This ID has been totally erased
  318. #ifdef DEBUG
  319. printf("Auth Error #%d\n", state);
  320. #endif
  321. mysql_free_result(sql_res);
  322. return state;
  323. break;
  324. case 7: // 6 = Your are Prohibited to log in until %s
  325. strftime(tmpstr, 20, date_format, localtime(&account->ban_until_time));
  326. tmpstr[19] = '\0';
  327. if (account->ban_until_time > time(NULL)) { // always banned
  328. mysql_free_result(sql_res);
  329. return 7;
  330. } else { // ban is finished
  331. // reset the ban time
  332. sprintf(tmpsql, "UPDATE `%s` SET `ban_until`='0',`state`='0' WHERE BINARY `%s`='%s'", login_db, login_db_userid, t_uid);
  333. sql_query(tmpsql,"mmo_auth");
  334. }
  335. break;
  336. default:
  337. return 100; // 99 = ID has been totally erased
  338. break;
  339. }
  340. }
  341. if (atol(sql_row[6]) != 0 && atol(sql_row[6]) < time(NULL)) {
  342. return 2; // 2 = This ID is expired
  343. }
  344. if ( is_user_online(atol(sql_row[0])) ) {
  345. printf("User [%s] is already online - Rejected.\n",sql_row[1]);
  346. return 3; // Rejected
  347. }
  348. if (use_md5_passwds) {
  349. MD5_String(account->passwd,user_password);
  350. } else {
  351. jstrescapecpy(user_password, account->passwd);
  352. }
  353. #ifdef DEBUG
  354. printf("Account [ok] Pass Encode Value: [%d]\n",account->passwdenc);
  355. #endif
  356. #ifdef PASSWORDENC
  357. if (account->passwdenc > 0) {
  358. j = account->passwdenc;
  359. #ifdef DEBUG
  360. printf ("Starting md5calc..\n");
  361. #endif
  362. if (j > 2)
  363. j = 1;
  364. do {
  365. if (j == 1) {
  366. sprintf(md5str, "%s%s", md5key,sql_row[2]);
  367. } else if (j == 2) {
  368. sprintf(md5str, "%s%s", sql_row[2], md5key);
  369. } else
  370. md5str[0] = 0;
  371. #ifdef DEBUG
  372. printf("j: [%d] mdstr: [%s]\n", j, md5str);
  373. #endif
  374. MD5_String2binary(md5str, md5bin);
  375. encpasswdok = (memcmp(user_password, md5bin, 16) == 0);
  376. } while (j < 2 && !encpasswdok && (j++) != account->passwdenc);
  377. #ifdef DEBUG
  378. printf("key [%s] md5 [%s] ", md5key, md5str);
  379. printf("client [%s] accountpass [%s]\n", user_password, sql_row[2]);
  380. printf ("end md5calc..\n");
  381. #endif
  382. }
  383. #endif
  384. if ((strcmp(user_password, sql_row[2]) && !encpasswdok)) {
  385. if (account->passwdenc == 0) {
  386. #ifdef DEBUG
  387. printf ("auth failed pass error %s %s %s" RETCODE, tmpstr, account->userid, user_password);
  388. #endif
  389. #ifdef PASSWORDENC
  390. } else {
  391. p += sprintf(p, "auth failed pass error %s %s recv-md5[", tmpstr, account->userid);
  392. for(j = 0; j < 16; j++)
  393. p += sprintf(p, "%02x", ((unsigned char *)user_password)[j]);
  394. p += sprintf(p, "] calc-md5[");
  395. for(j = 0; j < 16; j++)
  396. p += sprintf(p, "%02x", ((unsigned char *)md5bin)[j]);
  397. p += sprintf(p, "] md5key[");
  398. for(j = 0; j < md5keylen; j++)
  399. p += sprintf(p, "%02x", ((unsigned char *)md5key)[j]);
  400. p += sprintf(p, "]" RETCODE);
  401. #ifdef DEBUG
  402. printf("%s\n", p);
  403. #endif
  404. #endif
  405. }
  406. return 2;
  407. }
  408. #ifdef DEBUG
  409. printf("Auth ok: Time: [%s] Username: [%s]\n" RETCODE, tmpstr, account->userid);
  410. #endif
  411. account->account_id = atoi(sql_row[0]);
  412. account->login_id1 = rand();
  413. account->login_id2 = rand();
  414. memcpy(tmpstr, sql_row[3], 19);
  415. memcpy(account->lastlogin, tmpstr, 24);
  416. account->sex = sql_row[5][0] == 'S' ? 2 : sql_row[5][0]=='M';
  417. sprintf(tmpsql, "UPDATE `%s` SET `lastlogin` = NOW(), `logincount`=`logincount` +1, `last_ip`='%s' WHERE BINARY `%s` = '%s'",
  418. login_db, ip, login_db_userid, sql_row[1]);
  419. sql_query(tmpsql,"mmo_auth");
  420. mysql_free_result(sql_res) ; //resource free
  421. return -1;
  422. }
  423. //-----------------------------------------
  424. // Lan ip check ( added by Kashy )
  425. //-----------------------------------------
  426. int lan_ip_check(unsigned char *p) {
  427. int y;
  428. int lancheck = 1;
  429. int lancharip[4];
  430. unsigned int k0, k1, k2, k3;
  431. sscanf(lan_char_ip, "%d.%d.%d.%d", &k0, &k1, &k2, &k3);
  432. lancharip[0] = k0; lancharip[1] = k1; lancharip[2] = k2; lancharip[3] = k3;
  433. for(y = 0; y < 4; y++) {
  434. if ((lancharip[y] & subnetmaski[y])!= (p[y]))
  435. lancheck = 0;
  436. break; }
  437. #ifdef DEBUG
  438. printf("LAN check: %s.\n", (lancheck) ? "\033[1;32mLAN\033[0m" : "\033[1;31mWAN\033[0m");
  439. #endif
  440. return lancheck;
  441. }
  442. //-----------------------------------------------------
  443. // BANNED IP CHECK.
  444. //-----------------------------------------------------
  445. int ip_ban_check(int tid, unsigned int tick, int id, int data){
  446. //query
  447. if(mysql_query(&mysql_handle, "DELETE FROM `ipbanlist` WHERE `rtime` <= NOW()")) {
  448. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  449. }
  450. return 0;
  451. }
  452. //------------------------------------
  453. // Console Command Parser [Wizputer]
  454. //------------------------------------
  455. int parse_console(char *buf) {
  456. char *type,*command;
  457. type = (char *)malloc(64);
  458. command = (char *)malloc(64);
  459. memset(type,0,64);
  460. memset(command,0,64);
  461. printf("Console: %s\n",buf);
  462. if ( sscanf(buf, "%[^:]:%[^\n]", type , command ) < 2 )
  463. sscanf(buf,"%[^\n]",type);
  464. printf("Type of command: %s || Command: %s \n",type,command);
  465. if(buf) free(buf);
  466. if(type) free(type);
  467. if(command) free(command);
  468. return 0;
  469. }
  470. //-------------------------------------------------
  471. // Return numerical value of a switch configuration
  472. // on/off, english, français, deutsch, español
  473. //-------------------------------------------------
  474. int config_switch(const char *str) {
  475. if (strcmpi(str, "on") == 0 || strcmpi(str, "yes") == 0 || strcmpi(str, "oui") == 0 || strcmpi(str, "ja") == 0 || strcmpi(str, "si") == 0)
  476. return 1;
  477. if (strcmpi(str, "off") == 0 || strcmpi(str, "no") == 0 || strcmpi(str, "non") == 0 || strcmpi(str, "nein") == 0)
  478. return 0;
  479. return atoi(str);
  480. }
  481. //-------------------------------
  482. // LAN Support Config (Kashy)
  483. //-------------------------------
  484. int login_lan_config_read(const char *lancfgName){
  485. int i;
  486. char subnetmask[128];
  487. char line[1024], w1[1024], w2[1024];
  488. FILE *fp;
  489. fp=fopen(lancfgName, "r");
  490. if (fp == NULL) {
  491. printf("file not found: %s\n", lancfgName);
  492. return 1;
  493. }
  494. printf("Start reading of Lan Support configuration file\n");
  495. while(fgets(line, sizeof(line)-1, fp)){
  496. if (line[0] == '/' && line[1] == '/')
  497. continue;
  498. i = sscanf(line,"%[^:]: %[^\r\n]",w1,w2);
  499. if(i!=2)
  500. continue;
  501. else if(strcmpi(w1,"lan_char_ip")==0){
  502. strcpy(lan_char_ip, w2);
  503. printf ("set Lan_Char_IP : %s\n",w2);
  504. }
  505. else if(strcmpi(w1,"subnetmask")==0){
  506. unsigned int k0, k1, k2, k3;
  507. strcpy(subnetmask, w2);
  508. sscanf(subnetmask, "%d.%d.%d.%d", &k0, &k1, &k2, &k3);
  509. subnetmaski[0] = k0; subnetmaski[1] = k1; subnetmaski[2] = k2; subnetmaski[3] = k3;
  510. printf ("set subnetmask : %s\n",w2);
  511. }
  512. }
  513. fclose(fp);
  514. {
  515. unsigned int a0, a1, a2, a3;
  516. unsigned char p[4];
  517. sscanf(lan_char_ip, "%d.%d.%d.%d", &a0, &a1, &a2, &a3);
  518. p[0] = a0; p[1] = a1; p[2] = a2; p[3] = a3;
  519. printf("LAN test of LAN IP of the char-server: ");
  520. if (lan_ip_check(p) == 0) {
  521. printf("\033[1;31m***ERROR: LAN IP of the char-server doesn't belong to the specified Sub-network\033[0m\n");
  522. }
  523. }
  524. printf("End reading of Lan Support configuration file\n");
  525. return 0;
  526. }
  527. //-----------------------------------------------------
  528. // Login configuration
  529. //-----------------------------------------------------
  530. int login_config_read(const char *cfgName){
  531. int i;
  532. char line[1024], w1[1024], w2[1024];
  533. FILE *fp;
  534. fp=fopen(cfgName,"r");
  535. if(fp==NULL){
  536. printf("Configuration file (%s) not found.\n", cfgName);
  537. return 1;
  538. }
  539. printf("Start reading login configuration: %s\n", cfgName);
  540. while(fgets(line, sizeof(line)-1, fp)){
  541. if(line[0] == '/' && line[1] == '/')
  542. continue;
  543. i=sscanf(line,"%[^:]: %[^\r\n]",w1,w2);
  544. if(i!=2)
  545. continue;
  546. else if(strcmpi(w1,"login_port")==0){
  547. login_port=atoi(w2);
  548. printf ("set login_port : %s\n",w2);
  549. }
  550. else if(strcmpi(w1,"ipban")==0){
  551. ipban=atoi(w2);
  552. printf ("set ipban : %d\n",ipban);
  553. }
  554. //account ban -> ip ban
  555. else if(strcmpi(w1,"dynamic_account_ban")==0){
  556. dynamic_account_ban=atoi(w2);
  557. printf ("set dynamic_account_ban : %d\n",dynamic_account_ban);
  558. }
  559. else if(strcmpi(w1,"dynamic_account_ban_class")==0){
  560. dynamic_account_ban_class=atoi(w2);
  561. printf ("set dynamic_account_ban_class : %d\n",dynamic_account_ban_class);
  562. }
  563. //dynamic password error ban
  564. else if(strcmpi(w1,"dynamic_pass_failure_ban")==0){
  565. dynamic_pass_failure_ban=atoi(w2);
  566. printf ("set dynamic_pass_failure_ban : %d\n",dynamic_pass_failure_ban);
  567. }
  568. else if(strcmpi(w1,"dynamic_pass_failure_ban_time")==0){
  569. dynamic_pass_failure_ban_time=atoi(w2);
  570. printf ("set dynamic_pass_failure_ban_time : %d\n",dynamic_pass_failure_ban_time);
  571. }
  572. else if(strcmpi(w1,"dynamic_pass_failure_ban_how_many")==0){
  573. dynamic_pass_failure_ban_how_many=atoi(w2);
  574. printf ("set dynamic_pass_failure_ban_how_many : %d\n",dynamic_pass_failure_ban_how_many);
  575. }
  576. else if(strcmpi(w1,"dynamic_pass_failure_ban_how_long")==0){
  577. dynamic_pass_failure_ban_how_long=atoi(w2);
  578. printf ("set dynamic_pass_failure_ban_how_long : %d\n",dynamic_pass_failure_ban_how_long);
  579. }
  580. else if(strcmpi(w1,"anti_freeze_enable")==0){
  581. anti_freeze_enable = config_switch(w2);
  582. }
  583. else if (strcmpi(w1, "anti_freeze_interval") == 0) {
  584. ANTI_FREEZE_INTERVAL = atoi(w2);
  585. if (ANTI_FREEZE_INTERVAL < 5)
  586. ANTI_FREEZE_INTERVAL = 5; // minimum 5 seconds
  587. }
  588. else if (strcmpi(w1, "import") == 0) {
  589. login_config_read(w2);
  590. } else if(strcmpi(w1,"imalive_on")==0) { //Added by Mugendai for I'm Alive mod
  591. imalive_on = atoi(w2); //Added by Mugendai for I'm Alive mod
  592. } else if(strcmpi(w1,"imalive_time")==0) { //Added by Mugendai for I'm Alive mod
  593. imalive_time = atoi(w2); //Added by Mugendai for I'm Alive mod
  594. } else if(strcmpi(w1,"flush_on")==0) { //Added by Mugendai for GUI
  595. flush_on = atoi(w2); //Added by Mugendai for GUI
  596. } else if(strcmpi(w1,"flush_time")==0) { //Added by Mugendai for GUI
  597. flush_time = atoi(w2); //Added by Mugendai for GUI
  598. }
  599. else if(strcmpi(w1,"use_MD5_passwords")==0){
  600. if (!strcmpi(w2,"yes")) {
  601. use_md5_passwds=1;
  602. } else if (!strcmpi(w2,"no")){
  603. use_md5_passwds=0;
  604. }
  605. printf ("Using MD5 Passwords: %s \n",w2);
  606. }
  607. else if (strcmpi(w1, "date_format") == 0) { // note: never have more than 19 char for the date!
  608. switch (atoi(w2)) {
  609. case 0:
  610. strcpy(date_format, "%d-%m-%Y %H:%M:%S"); // 31-12-2004 23:59:59
  611. break;
  612. case 1:
  613. strcpy(date_format, "%m-%d-%Y %H:%M:%S"); // 12-31-2004 23:59:59
  614. break;
  615. case 2:
  616. strcpy(date_format, "%Y-%d-%m %H:%M:%S"); // 2004-31-12 23:59:59
  617. break;
  618. case 3:
  619. strcpy(date_format, "%Y-%m-%d %H:%M:%S"); // 2004-12-31 23:59:59
  620. break;
  621. }
  622. }
  623. else if (strcmpi(w1, "min_level_to_connect") == 0) {
  624. min_level_to_connect = atoi(w2);
  625. }
  626. else if (strcmpi(w1, "check_ip_flag") == 0) {
  627. check_ip_flag = config_switch(w2);
  628. }
  629. else if (strcmpi(w1, "console") == 0) {
  630. if(strcmpi(w2,"on") == 0 || strcmpi(w2,"yes") == 0 )
  631. console = 1;
  632. }
  633. }
  634. fclose(fp);
  635. printf ("End reading login configuration...\n");
  636. return 0;
  637. }
  638. //-----------------------------------------------------
  639. // SQL configuration
  640. //-----------------------------------------------------
  641. void sql_config_read(const char *cfgName){ /* Kalaspuff, to get login_db */
  642. int i;
  643. char line[1024], w1[1024], w2[1024];
  644. FILE *fp=fopen(cfgName,"r");
  645. if(fp==NULL){
  646. printf("file not found: %s\n",cfgName);
  647. exit(1);
  648. }
  649. printf("Start reading SQL configuration: %s\n", cfgName);
  650. while(fgets(line, sizeof(line)-1, fp)){
  651. if(line[0] == '/' && line[1] == '/')
  652. continue;
  653. i=sscanf(line,"%[^:]: %[^\r\n]",w1,w2);
  654. if(i!=2)
  655. continue;
  656. if (strcmpi(w1, "login_db") == 0) {
  657. strcpy(login_db, w2);
  658. }
  659. //add for DB connection
  660. else if(strcmpi(w1,"login_server_ip")==0){
  661. strcpy(login_server_ip, w2);
  662. printf ("set login_server_ip : %s\n",w2);
  663. }
  664. else if(strcmpi(w1,"login_server_port")==0){
  665. login_server_port=atoi(w2);
  666. printf ("set login_server_port : %s\n",w2);
  667. }
  668. else if(strcmpi(w1,"login_server_id")==0){
  669. strcpy(login_server_id, w2);
  670. printf ("set login_server_id : %s\n",w2);
  671. }
  672. else if(strcmpi(w1,"login_server_pw")==0){
  673. strcpy(login_server_pw, w2);
  674. printf ("set login_server_pw : %s\n",w2);
  675. }
  676. else if(strcmpi(w1,"login_server_db")==0){
  677. strcpy(login_server_db, w2);
  678. printf ("set login_server_db : %s\n",w2);
  679. }
  680. //added for custom column names for custom login table
  681. else if(strcmpi(w1,"login_db_account_id")==0){
  682. strcpy(login_db_account_id, w2);
  683. }
  684. else if(strcmpi(w1,"login_db_userid")==0){
  685. strcpy(login_db_userid, w2);
  686. }
  687. else if(strcmpi(w1,"login_db_user_pass")==0){
  688. strcpy(login_db_user_pass, w2);
  689. }
  690. else if(strcmpi(w1,"login_db_level")==0){
  691. strcpy(login_db_level, w2);
  692. }
  693. //end of custom table config
  694. else if (strcmpi(w1, "loginlog_db") == 0) {
  695. strcpy(loginlog_db, w2);
  696. }
  697. else if(strcmpi(w1,"lowest_gm_level")==0){
  698. lowest_gm_level = atoi(w2);
  699. }
  700. //support the import command, just like any other config
  701. else if(strcmpi(w1,"import")==0){
  702. sql_config_read(w2);
  703. }
  704. }
  705. fclose(fp);
  706. printf("reading SQL configuration done.....\n");
  707. }
  708. //-----------------------------------------------------
  709. //I'm Alive Alert
  710. //Used to output 'I'm Alive' every few seconds
  711. //Intended to let frontends know if the app froze
  712. //-----------------------------------------------------
  713. int imalive_timer(int tid, unsigned int tick, int id, int data){
  714. printf("I'm Alive\n");
  715. return 0;
  716. }
  717. //-----------------------------------------------------
  718. //Flush stdout
  719. //stdout buffer needs flushed to be seen in GUI
  720. //-----------------------------------------------------
  721. int flush_timer(int tid, unsigned int tick, int id, int data){
  722. fflush(stdout);
  723. return 0;
  724. }
  725. int do_init(int argc,char **argv){
  726. int i;
  727. //read login configuration
  728. login_config_read( (argc>1)?argv[1]:LOGIN_CONF_NAME );
  729. //read SQL configuration
  730. sql_config_read(SQL_CONF_NAME);
  731. //read LAN support configuation
  732. login_lan_config_read((argc > 1) ? argv[1] : LAN_CONF_NAME);
  733. //Generate Passworded Key.
  734. #ifdef DEBUG
  735. printf ("memset value: [0] var: [md5key] \n");
  736. #endif
  737. memset(md5key, 0, sizeof(md5key));
  738. #ifdef DEBUG
  739. printf ("memset var: [md5key] complete\n");
  740. printf ("Set MD5 key length\n");
  741. #endif
  742. md5keylen=rand()%4+12;
  743. for(i=0;i<md5keylen;i++)
  744. md5key[i]=rand()%255+1;
  745. #ifdef DEBUG
  746. printf ("Set MD5 key length complete\n");
  747. printf ("Set Auth FIFO Size\n");
  748. #endif
  749. for(i=0;i<AUTH_FIFO_SIZE;i++)
  750. auth_fifo[i].delflag=1;
  751. #ifdef DEBUG
  752. printf ("Set Auth FIFO Size complete\n");
  753. printf ("Set max number servers\n");
  754. #endif
  755. for(i=0;i<MAX_SERVERS;i++)
  756. server_fd[i]=-1;
  757. #ifdef DEBUG
  758. printf ("Set max number servers complete\n");
  759. #endif
  760. //server port open & binding
  761. login_fd=make_listen_port(login_port);
  762. printf ("Initializing SQL DB\n");
  763. mmo_auth_sqldb_init();
  764. printf ("SQL DB Initialized\n");
  765. // Close connection to SQL DB at termiantion
  766. set_termfunc(mmo_db_close);
  767. //set default parser as parse_login function
  768. set_defaultparse(parse_login);
  769. //Added for Mugendais I'm Alive mod
  770. if(imalive_on)
  771. add_timer_interval(gettick()+10, imalive_timer,0,0,imalive_time*1000);
  772. //Added by Mugendai for GUI support
  773. if(flush_on)
  774. add_timer_interval(gettick()+10, flush_timer,0,0,flush_time);
  775. if(anti_freeze_enable > 0) {
  776. add_timer_func_list(char_anti_freeze_system, "char_anti_freeze_system");
  777. i = add_timer_interval(gettick()+1000, char_anti_freeze_system, 0, 0, ANTI_FREEZE_INTERVAL * 1000);
  778. }
  779. // ban deleter timer - 1 minute term
  780. #ifdef DEBUG
  781. printf("add interval tic (ip_ban_check)...\n");
  782. #endif
  783. i=add_timer_interval(gettick()+10, ip_ban_check,0,0,60*1000);
  784. if (console) {
  785. set_defaultconsoleparse(parse_console);
  786. start_console();
  787. }
  788. // Online user database init
  789. free(online_db);
  790. online_db = numdb_init();
  791. printf("The login-server is \033[1;32mready\033[0m (Server is listening on the port %d).\n\n", login_port);
  792. return 0;
  793. }