login.c 153 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012
  1. // $Id: login.c,v 1.1.1.1 2004/09/10 17:26:53 MagicalTux Exp $
  2. // new version of the login-server by [Yor]
  3. #include <sys/types.h>
  4. #ifdef __WIN32
  5. #define WIN32_LEAN_AND_MEAN
  6. #include <winsock2.h>
  7. #include <time.h>
  8. void Gettimeofday(struct timeval *timenow)
  9. {
  10. time_t t;
  11. t = clock();
  12. timenow->tv_usec = t;
  13. timenow->tv_sec = t / CLK_TCK;
  14. return;
  15. }
  16. #define gettimeofday(timenow, dummy) Gettimeofday(timenow)
  17. #define in_addr_t unsigned long
  18. #else
  19. #include <sys/socket.h>
  20. #include <netinet/in.h>
  21. #include <sys/time.h>
  22. #include <sys/ioctl.h>
  23. #include <unistd.h>
  24. #include <arpa/inet.h>
  25. #include <netdb.h>
  26. #endif
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <time.h>
  30. #include <sys/stat.h> // for stat/lstat/fstat
  31. #include <signal.h>
  32. #include <fcntl.h>
  33. #include <string.h>
  34. #include <stdarg.h>
  35. #include "../common/core.h"
  36. #include "../common/socket.h"
  37. #include "../common/timer.h"
  38. #include "login.h"
  39. #include "../common/mmo.h"
  40. #include "../common/version.h"
  41. #include "../common/db.h"
  42. #include "../common/lock.h"
  43. #include "../common/malloc.h"
  44. #include "../common/buffer.h"
  45. #include "../common/strlib.h"
  46. #ifdef PASSWORDENC
  47. #include "md5calc.h"
  48. #endif
  49. #ifdef MEMWATCH
  50. #include "memwatch.h"
  51. #endif
  52. int account_id_count = START_ACCOUNT_NUM;
  53. int server_num;
  54. int new_account_flag = 0;
  55. char bind_ip_str[16];
  56. in_addr_t bind_ip;
  57. int login_port = 6900;
  58. char lan_char_ip[16];
  59. int subneti[4];
  60. int subnetmaski[4];
  61. char account_filename[1024] = "save/account.txt";
  62. char GM_account_filename[1024] = "conf/GM_account.txt";
  63. char login_log_filename[1024] = "log/login.log";
  64. FILE *log_fp = NULL;
  65. char login_log_unknown_packets_filename[1024] = "log/login_unknown_packets.log";
  66. char date_format[32] = "%Y-%m-%d %H:%M:%S";
  67. int save_unknown_packets = 0;
  68. long creation_time_GM_account_file;
  69. int gm_account_filename_check_timer = 15; // Timer to check if GM_account file has been changed and reload GM account automaticaly (in seconds; default: 15)
  70. int log_login = 1;
  71. int display_parse_login = 0; // 0: no, 1: yes
  72. int display_parse_admin = 0; // 0: no, 1: yes
  73. int display_parse_fromchar = 0; // 0: no, 1: yes (without packet 0x2714), 2: all packets
  74. struct mmo_char_server server[MAX_SERVERS];
  75. int server_fd[MAX_SERVERS];
  76. int server_freezeflag[MAX_SERVERS]; // Char-server anti-freeze system. Counter. 5 ok, 4...0 freezed
  77. int anti_freeze_enable = 0;
  78. int ANTI_FREEZE_INTERVAL = 15;
  79. int login_fd;
  80. //Added for Mugendai's I'm Alive mod
  81. int imalive_on=0;
  82. int imalive_time=60;
  83. //Added by Mugendai for GUI
  84. int flush_on=1;
  85. int flush_time=100;
  86. enum {
  87. ACO_DENY_ALLOW = 0,
  88. ACO_ALLOW_DENY,
  89. ACO_MUTUAL_FAILTURE,
  90. ACO_STRSIZE = 128,
  91. };
  92. int access_order = ACO_DENY_ALLOW;
  93. int access_allownum = 0;
  94. int access_denynum = 0;
  95. char *access_allow = NULL;
  96. char *access_deny = NULL;
  97. int access_ladmin_allownum = 0;
  98. char *access_ladmin_allow = NULL;
  99. int min_level_to_connect = 0; // minimum level of player/GM (0: player, 1-99: gm) to connect on the server
  100. int add_to_unlimited_account = 0; // Give possibility or not to adjust (ladmin command: timeadd) the time of an unlimited account.
  101. int start_limited_time = -1; // Starting additional sec from now for the limited time at creation of accounts (-1: unlimited time, 0 or more: additional sec from now)
  102. int check_ip_flag = 1; // It's to check IP of a player between login-server and char-server (part of anti-hacking system)
  103. int check_client_version = 0; //Client version check ON/OFF .. (sirius)
  104. int client_version_to_connect = 20; //Client version needed to connect ..(sirius)
  105. struct login_session_data {
  106. int md5keylen;
  107. char md5key[20];
  108. };
  109. #define AUTH_FIFO_SIZE 256
  110. struct {
  111. int account_id, login_id1, login_id2;
  112. int ip, sex, delflag;
  113. } auth_fifo[AUTH_FIFO_SIZE];
  114. int auth_fifo_pos = 0;
  115. struct auth_dat {
  116. int account_id, sex;
  117. char userid[24], pass[33], lastlogin[24]; // 33 for 32 + NULL terminated
  118. int logincount;
  119. int state; // packet 0x006a value + 1 (0: compte OK)
  120. char email[40]; // e-mail (by default: a@a.com)
  121. char error_message[20]; // Message of error code #6 = Your are Prohibited to log in until %s (packet 0x006a)
  122. time_t ban_until_time; // # of seconds 1/1/1970 (timestamp): ban time limit of the account (0 = no ban)
  123. time_t connect_until_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
  124. char last_ip[16]; // save of last IP of connection
  125. char memo[255]; // a memo field
  126. int account_reg2_num;
  127. struct global_reg account_reg2[ACCOUNT_REG2_NUM];
  128. } *auth_dat = NULL;
  129. int auth_num = 0, auth_max = 0;
  130. // define the number of times that some players must authentify them before to save account file.
  131. // it's just about normal authentification. If an account is created or modified, save is immediatly done.
  132. // An authentification just change last connected IP and date. It already save in log file.
  133. // set minimum auth change before save:
  134. #define AUTH_BEFORE_SAVE_FILE 10
  135. // set divider of auth_num to found number of change before save
  136. #define AUTH_SAVE_FILE_DIVIDER 50
  137. int auth_before_save_file = 0; // Counter. First save when 1st char-server do connection.
  138. int admin_state = 0;
  139. char admin_pass[24] = "";
  140. int GM_num;
  141. int GM_max=256;
  142. char gm_pass[64] = "";
  143. int level_new_gm = 60;
  144. struct gm_account *gm_account_db;
  145. int dynamic_pass_failure_ban = 1;
  146. int dynamic_pass_failure_ban_time = 5;
  147. int dynamic_pass_failure_ban_how_many = 3;
  148. int dynamic_pass_failure_ban_how_long = 1;
  149. int use_md5_passwds = 0;
  150. int console = 0;
  151. //------------------------------
  152. // Writing function of logs file
  153. //------------------------------
  154. int login_log(char *fmt, ...) {
  155. if (log_login) {
  156. va_list ap;
  157. struct timeval tv;
  158. char tmpstr[2048];
  159. if(!log_fp)
  160. log_fp = fopen(login_log_filename, "a");
  161. if (log_fp) {
  162. if (fmt[0] == '\0') // jump a line if no message
  163. fprintf(log_fp, RETCODE);
  164. else {
  165. va_start(ap, fmt);
  166. gettimeofday(&tv, NULL);
  167. strftime(tmpstr, 24, date_format, localtime((const time_t*)&(tv.tv_sec)));
  168. sprintf(tmpstr + strlen(tmpstr), ".%03d: %s", (int)tv.tv_usec / 1000, fmt);
  169. vfprintf(log_fp, tmpstr, ap);
  170. va_end(ap);
  171. }
  172. fflush(log_fp); // under cygwin or windows, if software is stopped, data are not written in the file -> fflush at every line
  173. }
  174. }
  175. return 0;
  176. }
  177. //----------------------------------------------------------------------
  178. // Determine if an account (id) is a GM account
  179. // and returns its level (or 0 if it isn't a GM account or if not found)
  180. //----------------------------------------------------------------------
  181. int isGM(int account_id) {
  182. int i;
  183. for(i=0; i < GM_num; i++)
  184. if(gm_account_db[i].account_id == account_id)
  185. return gm_account_db[i].level;
  186. return 0;
  187. }
  188. //----------------------------------------------------------------------
  189. // Adds a new GM using acc id and level
  190. //----------------------------------------------------------------------
  191. void addGM(int account_id, int level) {
  192. int i;
  193. int do_add = 0;
  194. for(i = 0; i < auth_num; i++) {
  195. if (auth_dat[i].account_id==account_id) {
  196. do_add = 1;
  197. break;
  198. }
  199. }
  200. for(i = 0; i < GM_num; i++)
  201. if (gm_account_db[i].account_id == account_id) {
  202. if (gm_account_db[i].level == level)
  203. printf("addGM: GM account %d defined twice (same level: %d).\n", account_id, level);
  204. else {
  205. printf("addGM: GM account %d defined twice (levels: %d and %d).\n", account_id, gm_account_db[i].level, level);
  206. gm_account_db[i].level = level;
  207. }
  208. return;
  209. }
  210. // if new account
  211. if (i == GM_num && do_add) {
  212. if (GM_num >= GM_max) {
  213. GM_max += 256;
  214. gm_account_db = (struct gm_account*)aRealloc(gm_account_db, sizeof(struct gm_account) * GM_max);
  215. memset(gm_account_db + (GM_max - 256), 0, sizeof(struct gm_account) * 256);
  216. }
  217. gm_account_db[GM_num].account_id = account_id;
  218. gm_account_db[GM_num].level = level;
  219. GM_num++;
  220. if (GM_num >= 4000) {
  221. printf("***WARNING: 4000 GM accounts found. Next GM accounts are not read.\n");
  222. login_log("***WARNING: 4000 GM accounts found. Next GM accounts are not read." RETCODE);
  223. }
  224. }
  225. }
  226. //-------------------------------------------------------
  227. // Reading function of GM accounts file (and their level)
  228. //-------------------------------------------------------
  229. int read_gm_account() {
  230. char line[512];
  231. FILE *fp;
  232. int account_id, level;
  233. int line_counter;
  234. struct stat file_stat;
  235. int start_range = 0, end_range = 0, is_range = 0, current_id = 0;
  236. if(gm_account_db) aFree(gm_account_db);
  237. GM_num = 0;
  238. if(GM_max < 0) GM_max = 256;
  239. gm_account_db = (struct gm_account*)aCalloc(GM_max, sizeof(struct gm_account));
  240. // get last modify time/date
  241. if (stat(GM_account_filename, &file_stat))
  242. creation_time_GM_account_file = 0; // error
  243. else
  244. creation_time_GM_account_file = file_stat.st_mtime;
  245. if ((fp = fopen(GM_account_filename, "r")) == NULL) {
  246. printf("read_gm_account: GM accounts file [%s] not found.\n", GM_account_filename);
  247. printf(" Actually, there is no GM accounts on the server.\n");
  248. login_log("read_gm_account: GM accounts file [%s] not found." RETCODE, GM_account_filename);
  249. login_log(" Actually, there is no GM accounts on the server." RETCODE);
  250. return 1;
  251. }
  252. line_counter = 0;
  253. // limited to 4000, because we send information to char-servers (more than 4000 GM accounts???)
  254. // int (id) + int (level) = 8 bytes * 4000 = 32k (limit of packets in windows)
  255. while(fgets(line, sizeof(line)-1, fp) && GM_num < 4000) {
  256. line_counter++;
  257. if ((line[0] == '/' && line[1] == '/') || line[0] == '\0' || line[0] == '\n' || line[0] == '\r')
  258. continue;
  259. is_range = (sscanf(line, "%d%*[-~]%d %d",&start_range,&end_range,&level)==3); // ID Range [MC Cameri]
  260. if (!is_range && sscanf(line, "%d %d", &account_id, &level) != 2 && sscanf(line, "%d: %d", &account_id, &level) != 2)
  261. printf("read_gm_account: file [%s], invalid 'acount_id|range level' format (line #%d).\n", GM_account_filename, line_counter);
  262. else if (level <= 0)
  263. printf("read_gm_account: file [%s] %dth account (line #%d) (invalid level [0 or negative]: %d).\n", GM_account_filename, GM_num+1, line_counter, level);
  264. else {
  265. if (level > 99) {
  266. printf("read_gm_account: file [%s] %dth account (invalid level, but corrected: %d->99).\n", GM_account_filename, GM_num+1, level);
  267. level = 99;
  268. }
  269. if (is_range) {
  270. if (start_range==end_range)
  271. printf("read_gm_account: file [%s] invalid range, beginning of range is equal to end of range (line #%d).\n", GM_account_filename, line_counter);
  272. else if (start_range>end_range)
  273. printf("read_gm_account: file [%s] invalid range, beginning of range must be lower than end of range (line #%d).\n", GM_account_filename, line_counter);
  274. else
  275. for (current_id = start_range;current_id<=end_range;current_id++)
  276. addGM(current_id,level);
  277. } else {
  278. addGM(account_id,level);
  279. }
  280. }
  281. }
  282. fclose(fp);
  283. printf("read_gm_account: file '%s' read (%d GM accounts found).\n", GM_account_filename, GM_num);
  284. login_log("read_gm_account: file '%s' read (%d GM accounts found)." RETCODE, GM_account_filename, GM_num);
  285. return 0;
  286. }
  287. //--------------------------------------------------------------
  288. // Test of the IP mask
  289. // (ip: IP to be tested, str: mask x.x.x.x/# or x.x.x.x/y.y.y.y)
  290. //--------------------------------------------------------------
  291. int check_ipmask(unsigned int ip, const unsigned char *str) {
  292. unsigned int mask = 0, i = 0, m, ip2, a0, a1, a2, a3;
  293. unsigned char *p = (unsigned char *)&ip2, *p2 = (unsigned char *)&mask;
  294. if (sscanf((const char*)str, "%d.%d.%d.%d/%n", &a0, &a1, &a2, &a3, &i) != 4 || i == 0)
  295. return 0;
  296. p[0] = a0; p[1] = a1; p[2] = a2; p[3] = a3;
  297. if (sscanf((const char*)str+i, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) == 4) {
  298. p2[0] = a0; p2[1] = a1; p2[2] = a2; p2[3] = a3;
  299. mask = ntohl(mask);
  300. } else if (sscanf((const char*)(str+i), "%d", &m) == 1 && m >= 0 && m <= 32) {
  301. for(i = 0; i < m && i < 32; i++)
  302. mask = (mask >> 1) | 0x80000000;
  303. } else {
  304. printf("check_ipmask: invalid mask [%s].\n", str);
  305. return 0;
  306. }
  307. // printf("Tested IP: %08x, network: %08x, network mask: %08x\n",
  308. // (unsigned int)ntohl(ip), (unsigned int)ntohl(ip2), (unsigned int)mask);
  309. return ((ntohl(ip) & mask) == (ntohl(ip2) & mask));
  310. }
  311. //---------------------
  312. // Access control by IP
  313. //---------------------
  314. int check_ip(unsigned int ip) {
  315. int i;
  316. unsigned char *p = (unsigned char *)&ip;
  317. char buf[16];
  318. char * access_ip;
  319. enum { ACF_DEF, ACF_ALLOW, ACF_DENY } flag = ACF_DEF;
  320. if (access_allownum == 0 && access_denynum == 0)
  321. return 1; // When there is no restriction, all IP are authorised.
  322. // + 012.345.: front match form, or
  323. // all: all IP are matched, or
  324. // 012.345.678.901/24: network form (mask with # of bits), or
  325. // 012.345.678.901/255.255.255.0: network form (mask with ip mask)
  326. // + Note about the DNS resolution (like www.ne.jp, etc.):
  327. // There is no guarantee to have an answer.
  328. // If we have an answer, there is no guarantee to have a 100% correct value.
  329. // And, the waiting time (to check) can be long (over 1 minute to a timeout). That can block the software.
  330. // So, DNS notation isn't authorised for ip checking.
  331. sprintf(buf, "%d.%d.%d.%d.", p[0], p[1], p[2], p[3]);
  332. for(i = 0; i < access_allownum; i++) {
  333. access_ip = access_allow + i * ACO_STRSIZE;
  334. if (memcmp(access_ip, buf, strlen(access_ip)) == 0 || check_ipmask(ip, (unsigned char*)access_ip)) {
  335. if(access_order == ACO_ALLOW_DENY)
  336. return 1; // With 'allow, deny' (deny if not allow), allow has priority
  337. flag = ACF_ALLOW;
  338. break;
  339. }
  340. }
  341. for(i = 0; i < access_denynum; i++) {
  342. access_ip = access_deny + i * ACO_STRSIZE;
  343. if (memcmp(access_ip, buf, strlen(access_ip)) == 0 || check_ipmask(ip, (unsigned char*)access_ip)) {
  344. //flag = ACF_DENY; // not necessary to define flag
  345. return 0; // At this point, if it's 'deny', we refuse connection.
  346. }
  347. }
  348. return (flag == ACF_ALLOW || access_order == ACO_DENY_ALLOW) ? 1:0;
  349. // With 'mutual-failture', only 'allow' and non 'deny' IP are authorised.
  350. // A non 'allow' (even non 'deny') IP is not authorised. It's like: if allowed and not denied, it's authorised.
  351. // So, it's disapproval if you have no description at the time of 'mutual-failture'.
  352. // With 'deny,allow' (allow if not deny), because here it's not deny, we authorise.
  353. }
  354. //--------------------------------
  355. // Access control by IP for ladmin
  356. //--------------------------------
  357. int check_ladminip(unsigned int ip) {
  358. int i;
  359. unsigned char *p = (unsigned char *)&ip;
  360. char buf[16];
  361. char * access_ip;
  362. if (access_ladmin_allownum == 0)
  363. return 1; // When there is no restriction, all IP are authorised.
  364. // + 012.345.: front match form, or
  365. // all: all IP are matched, or
  366. // 012.345.678.901/24: network form (mask with # of bits), or
  367. // 012.345.678.901/255.255.255.0: network form (mask with ip mask)
  368. // + Note about the DNS resolution (like www.ne.jp, etc.):
  369. // There is no guarantee to have an answer.
  370. // If we have an answer, there is no guarantee to have a 100% correct value.
  371. // And, the waiting time (to check) can be long (over 1 minute to a timeout). That can block the software.
  372. // So, DNS notation isn't authorised for ip checking.
  373. sprintf(buf, "%d.%d.%d.%d.", p[0], p[1], p[2], p[3]);
  374. for(i = 0; i < access_ladmin_allownum; i++) {
  375. access_ip = access_ladmin_allow + i * ACO_STRSIZE;
  376. if (memcmp(access_ip, buf, strlen(access_ip)) == 0 || check_ipmask(ip, (unsigned char*)access_ip)) {
  377. return 1;
  378. }
  379. }
  380. return 0;
  381. }
  382. //---------------------------------------------------
  383. // E-mail check: return 0 (not correct) or 1 (valid).
  384. //---------------------------------------------------
  385. int e_mail_check(char *email) {
  386. char ch;
  387. char* last_arobas;
  388. // athena limits
  389. if (strlen(email) < 3 || strlen(email) > 39)
  390. return 0;
  391. // part of RFC limits (official reference of e-mail description)
  392. if (strchr(email, '@') == NULL || email[strlen(email)-1] == '@')
  393. return 0;
  394. if (email[strlen(email)-1] == '.')
  395. return 0;
  396. last_arobas = strrchr(email, '@');
  397. if (strstr(last_arobas, "@.") != NULL ||
  398. strstr(last_arobas, "..") != NULL)
  399. return 0;
  400. for(ch = 1; ch < 32; ch++)
  401. if (strchr(last_arobas, ch) != NULL)
  402. return 0;
  403. if (strchr(last_arobas, ' ') != NULL ||
  404. strchr(last_arobas, ';') != NULL)
  405. return 0;
  406. // all correct
  407. return 1;
  408. }
  409. //-----------------------------------------------
  410. // Search an account id
  411. // (return account index or -1 (if not found))
  412. // If exact account name is not found,
  413. // the function checks without case sensitive
  414. // and returns index if only 1 account is found
  415. // and similar to the searched name.
  416. //-----------------------------------------------
  417. int search_account_index(char* account_name) {
  418. int i, quantity, index;
  419. quantity = 0;
  420. index = -1;
  421. for(i = 0; i < auth_num; i++) {
  422. // Without case sensitive check (increase the number of similar account names found)
  423. if (stricmp(auth_dat[i].userid, account_name) == 0) {
  424. // Strict comparison (if found, we finish the function immediatly with correct value)
  425. if (strcmp(auth_dat[i].userid, account_name) == 0)
  426. return i;
  427. quantity++;
  428. index = i;
  429. }
  430. }
  431. // Here, the exact account name is not found
  432. // We return the found index of a similar account ONLY if there is 1 similar account
  433. if (quantity == 1)
  434. return index;
  435. // Exact account name is not found and 0 or more than 1 similar accounts have been found ==> we say not found
  436. return -1;
  437. }
  438. //--------------------------------------------------------
  439. // Create a string to save the account in the account file
  440. //--------------------------------------------------------
  441. int mmo_auth_tostr(char *str, struct auth_dat *p) {
  442. int i;
  443. char *str_p = str;
  444. str_p += sprintf(str_p, "%d\t%s\t%s\t%s\t%c\t%d\t%d\t"
  445. "%s\t%s\t%ld\t%s\t%s\t%ld\t",
  446. p->account_id, p->userid, p->pass, p->lastlogin,
  447. (p->sex == 2) ? 'S' : (p->sex ? 'M' : 'F'),
  448. p->logincount, p->state,
  449. p->email, p->error_message,
  450. p->connect_until_time, p->last_ip, p->memo, p->ban_until_time);
  451. for(i = 0; i < p->account_reg2_num; i++)
  452. if (p->account_reg2[i].str[0])
  453. str_p += sprintf(str_p, "%s,%d ", p->account_reg2[i].str, p->account_reg2[i].value);
  454. return 0;
  455. }
  456. //---------------------------------
  457. // Reading of the accounts database
  458. //---------------------------------
  459. int mmo_auth_init(void) {
  460. FILE *fp;
  461. int account_id, logincount, state, n, i, j, v;
  462. char line[2048], *p, userid[2048], pass[2048], lastlogin[2048], sex, email[2048], error_message[2048], last_ip[2048], memo[2048];
  463. time_t ban_until_time;
  464. time_t connect_until_time;
  465. char str[2048];
  466. int GM_count = 0;
  467. int server_count = 0;
  468. auth_max = 256;
  469. auth_dat = (struct auth_dat*)aCalloc(auth_max, sizeof(struct auth_dat));
  470. if ((fp = fopen(account_filename, "r")) == NULL) {
  471. // no account file -> no account -> no login, including char-server (ERROR)
  472. printf("\033[1;31mmmo_auth_init: Accounts file [%s] not found.\033[0m\n", account_filename);
  473. return 0;
  474. }
  475. while(fgets(line, sizeof(line)-1, fp) != NULL) {
  476. if (line[0] == '/' && line[1] == '/')
  477. continue;
  478. line[sizeof(line)-1] = '\0';
  479. // remove carriage return if exist
  480. while(line[0] != '\0' && (line[strlen(line)-1] == '\n' || line[strlen(line)-1] == '\r'))
  481. line[strlen(line)-1] = '\0';
  482. p = line;
  483. memset(userid, 0, sizeof(userid));
  484. memset(pass, 0, sizeof(pass));
  485. memset(lastlogin, 0, sizeof(lastlogin));
  486. memset(email, 0, sizeof(email));
  487. memset(error_message, 0, sizeof(error_message));
  488. memset(last_ip, 0, sizeof(last_ip));
  489. memset(memo, 0, sizeof(memo));
  490. // database version reading (v2)
  491. if (((i = sscanf(line, "%d\t%[^\t]\t%[^\t]\t%[^\t]\t%c\t%d\t%d\t"
  492. "%[^\t]\t%[^\t]\t%ld\t%[^\t]\t%[^\t]\t%ld%n",
  493. &account_id, userid, pass, lastlogin, &sex, &logincount, &state,
  494. email, error_message, &connect_until_time, last_ip, memo, &ban_until_time, &n)) == 13 && line[n] == '\t') ||
  495. ((i = sscanf(line, "%d\t%[^\t]\t%[^\t]\t%[^\t]\t%c\t%d\t%d\t"
  496. "%[^\t]\t%[^\t]\t%ld\t%[^\t]\t%[^\t]%n",
  497. &account_id, userid, pass, lastlogin, &sex, &logincount, &state,
  498. email, error_message, &connect_until_time, last_ip, memo, &n)) == 12 && line[n] == '\t')) {
  499. n = n + 1;
  500. // Some checks
  501. if (account_id > END_ACCOUNT_NUM) {
  502. printf("\033[1;31mmmo_auth_init: ******Error: an account has an id higher than %d\n", END_ACCOUNT_NUM);
  503. printf(" account id #%d -> account not read (saved in log file).\033[0m\n", account_id);
  504. login_log("mmmo_auth_init: ******Error: an account has an id higher than %d." RETCODE, END_ACCOUNT_NUM);
  505. login_log(" account id #%d -> account not read (saved in next line):" RETCODE, account_id);
  506. login_log("%s", line);
  507. continue;
  508. }
  509. userid[23] = '\0';
  510. remove_control_chars((unsigned char *)userid);
  511. for(j = 0; j < auth_num; j++) {
  512. if (auth_dat[j].account_id == account_id) {
  513. printf("\033[1;31mmmo_auth_init: ******Error: an account has an identical id to another.\n");
  514. printf(" account id #%d -> new account not read (saved in log file).\033[0m\n", account_id);
  515. login_log("mmmo_auth_init: ******Error: an account has an identical id to another." RETCODE);
  516. login_log(" account id #%d -> new account not read (saved in next line):" RETCODE, account_id);
  517. login_log("%s", line);
  518. break;
  519. } else if (strcmp(auth_dat[j].userid, userid) == 0) {
  520. printf("\033[1;31mmmo_auth_init: ******Error: account name already exists.\n");
  521. printf(" account name '%s' -> new account not read.\n", userid); // 2 lines, account name can be long.
  522. printf(" Account saved in log file.\033[0m\n");
  523. login_log("mmmo_auth_init: ******Error: an account has an identical name to another." RETCODE);
  524. login_log(" account name '%s' -> new account not read (saved in next line):" RETCODE, userid);
  525. login_log("%s", line);
  526. break;
  527. }
  528. }
  529. if (j != auth_num)
  530. continue;
  531. if (auth_num >= auth_max) {
  532. auth_max += 256;
  533. auth_dat = (struct auth_dat*)aRealloc(auth_dat, sizeof(struct auth_dat) * auth_max);
  534. }
  535. memset(&auth_dat[auth_num], '\0', sizeof(struct auth_dat));
  536. auth_dat[auth_num].account_id = account_id;
  537. strncpy(auth_dat[auth_num].userid, userid, 24);
  538. pass[23] = '\0';
  539. remove_control_chars((unsigned char *)pass);
  540. strncpy(auth_dat[auth_num].pass, pass, 24);
  541. lastlogin[23] = '\0';
  542. remove_control_chars((unsigned char *)lastlogin);
  543. strncpy(auth_dat[auth_num].lastlogin, lastlogin, 24);
  544. auth_dat[auth_num].sex = (sex == 'S' || sex == 's') ? 2 : (sex == 'M' || sex == 'm');
  545. if (logincount >= 0)
  546. auth_dat[auth_num].logincount = logincount;
  547. else
  548. auth_dat[auth_num].logincount = 0;
  549. if (state > 255)
  550. auth_dat[auth_num].state = 100;
  551. else if (state < 0)
  552. auth_dat[auth_num].state = 0;
  553. else
  554. auth_dat[auth_num].state = state;
  555. if (e_mail_check(email) == 0) {
  556. printf("Account %s (%d): invalid e-mail (replaced par a@a.com).\n", auth_dat[auth_num].userid, auth_dat[auth_num].account_id);
  557. strncpy(auth_dat[auth_num].email, "a@a.com", 40);
  558. } else {
  559. remove_control_chars((unsigned char *)email);
  560. strncpy(auth_dat[auth_num].email, email, 40);
  561. }
  562. error_message[19] = '\0';
  563. remove_control_chars((unsigned char *)error_message);
  564. if (error_message[0] == '\0' || state != 7) { // 7, because state is packet 0x006a value + 1
  565. strncpy(auth_dat[auth_num].error_message, "-", 20);
  566. } else {
  567. strncpy(auth_dat[auth_num].error_message, error_message, 20);
  568. }
  569. if (i == 13)
  570. auth_dat[auth_num].ban_until_time = ban_until_time;
  571. else
  572. auth_dat[auth_num].ban_until_time = 0;
  573. auth_dat[auth_num].connect_until_time = connect_until_time;
  574. last_ip[15] = '\0';
  575. remove_control_chars((unsigned char *)last_ip);
  576. strncpy(auth_dat[auth_num].last_ip, last_ip, 16);
  577. memo[254] = '\0';
  578. remove_control_chars((unsigned char *)memo);
  579. strncpy(auth_dat[auth_num].memo, memo, 255);
  580. for(j = 0; j < ACCOUNT_REG2_NUM; j++) {
  581. p += n;
  582. if (sscanf(p, "%[^\t,],%d %n", str, &v, &n) != 2) {
  583. // We must check if a str is void. If it's, we can continue to read other REG2.
  584. // Account line will have something like: str2,9 ,9 str3,1 (here, ,9 is not good)
  585. if (p[0] == ',' && sscanf(p, ",%d %n", &v, &n) == 1) {
  586. j--;
  587. continue;
  588. } else
  589. break;
  590. }
  591. str[31] = '\0';
  592. remove_control_chars((unsigned char *)str);
  593. strncpy(auth_dat[auth_num].account_reg2[j].str, str, 32);
  594. auth_dat[auth_num].account_reg2[j].value = v;
  595. }
  596. auth_dat[auth_num].account_reg2_num = j;
  597. if (isGM(account_id) > 0)
  598. GM_count++;
  599. if (auth_dat[auth_num].sex == 2)
  600. server_count++;
  601. auth_num++;
  602. if (account_id >= account_id_count)
  603. account_id_count = account_id + 1;
  604. // Old athena database version reading (v1)
  605. } else if ((i = sscanf(line, "%d\t%[^\t]\t%[^\t]\t%[^\t]\t%c\t%d\t%d\t%n",
  606. &account_id, userid, pass, lastlogin, &sex, &logincount, &state, &n)) >= 5) {
  607. if (account_id > END_ACCOUNT_NUM) {
  608. printf("\033[1;31mmmo_auth_init: ******Error: an account has an id higher than %d\n", END_ACCOUNT_NUM);
  609. printf(" account id #%d -> account not read (saved in log file).\033[0m\n", account_id);
  610. login_log("mmmo_auth_init: ******Error: an account has an id higher than %d." RETCODE, END_ACCOUNT_NUM);
  611. login_log(" account id #%d -> account not read (saved in next line):" RETCODE, account_id);
  612. login_log("%s", line);
  613. continue;
  614. }
  615. userid[23] = '\0';
  616. remove_control_chars((unsigned char *)userid);
  617. for(j = 0; j < auth_num; j++) {
  618. if (auth_dat[j].account_id == account_id) {
  619. printf("\033[1;31mmmo_auth_init: ******Error: an account has an identical id to another.\n");
  620. printf(" account id #%d -> new account not read (saved in log file).\033[0m\n", account_id);
  621. login_log("mmmo_auth_init: ******Error: an account has an identical id to another." RETCODE);
  622. login_log(" account id #%d -> new account not read (saved in next line):" RETCODE, account_id);
  623. login_log("%s", line);
  624. break;
  625. } else if (strcmp(auth_dat[j].userid, userid) == 0) {
  626. printf("\033[1;31mmmo_auth_init: ******Error: account name already exists.\n");
  627. printf(" account name '%s' -> new account not read.\n", userid); // 2 lines, account name can be long.
  628. printf(" Account saved in log file.\033[0m\n");
  629. login_log("mmmo_auth_init: ******Error: an account has an identical id to another." RETCODE);
  630. login_log(" account id #%d -> new account not read (saved in next line):" RETCODE, account_id);
  631. login_log("%s", line);
  632. break;
  633. }
  634. }
  635. if (j != auth_num)
  636. continue;
  637. if (auth_num >= auth_max) {
  638. auth_max += 256;
  639. auth_dat = (struct auth_dat*)aRealloc(auth_dat, sizeof(struct auth_dat) * auth_max);
  640. }
  641. memset(&auth_dat[auth_num], '\0', sizeof(struct auth_dat));
  642. auth_dat[auth_num].account_id = account_id;
  643. strncpy(auth_dat[auth_num].userid, userid, 24);
  644. pass[23] = '\0';
  645. remove_control_chars((unsigned char *)pass);
  646. strncpy(auth_dat[auth_num].pass, pass, 24);
  647. lastlogin[23] = '\0';
  648. remove_control_chars((unsigned char *)lastlogin);
  649. strncpy(auth_dat[auth_num].lastlogin, lastlogin, 24);
  650. auth_dat[auth_num].sex = (sex == 'S' || sex == 's') ? 2 : (sex == 'M' || sex == 'm');
  651. if (i >= 6) {
  652. if (logincount >= 0)
  653. auth_dat[auth_num].logincount = logincount;
  654. else
  655. auth_dat[auth_num].logincount = 0;
  656. } else
  657. auth_dat[auth_num].logincount = 0;
  658. if (i >= 7) {
  659. if (state > 255)
  660. auth_dat[auth_num].state = 100;
  661. else if (state < 0)
  662. auth_dat[auth_num].state = 0;
  663. else
  664. auth_dat[auth_num].state = state;
  665. } else
  666. auth_dat[auth_num].state = 0;
  667. // Initialization of new data
  668. strncpy(auth_dat[auth_num].email, "a@a.com", 40);
  669. strncpy(auth_dat[auth_num].error_message, "-", 20);
  670. auth_dat[auth_num].ban_until_time = 0;
  671. auth_dat[auth_num].connect_until_time = 0;
  672. strncpy(auth_dat[auth_num].last_ip, "-", 16);
  673. strncpy(auth_dat[auth_num].memo, "-", 255);
  674. for(j = 0; j < ACCOUNT_REG2_NUM; j++) {
  675. p += n;
  676. if (sscanf(p, "%[^\t,],%d %n", str, &v, &n) != 2) {
  677. // We must check if a str is void. If it's, we can continue to read other REG2.
  678. // Account line will have something like: str2,9 ,9 str3,1 (here, ,9 is not good)
  679. if (p[0] == ',' && sscanf(p, ",%d %n", &v, &n) == 1) {
  680. j--;
  681. continue;
  682. } else
  683. break;
  684. }
  685. str[31] = '\0';
  686. remove_control_chars((unsigned char *)str);
  687. strncpy(auth_dat[auth_num].account_reg2[j].str, str, 32);
  688. auth_dat[auth_num].account_reg2[j].value = v;
  689. }
  690. auth_dat[auth_num].account_reg2_num = j;
  691. if (isGM(account_id) > 0)
  692. GM_count++;
  693. if (auth_dat[auth_num].sex == 2)
  694. server_count++;
  695. auth_num++;
  696. if (account_id >= account_id_count)
  697. account_id_count = account_id + 1;
  698. } else {
  699. i = 0;
  700. if (sscanf(line, "%d\t%%newid%%\n%n", &account_id, &i) == 1 &&
  701. i > 0 && account_id > account_id_count)
  702. account_id_count = account_id;
  703. }
  704. }
  705. fclose(fp);
  706. if (auth_num == 0) {
  707. printf("mmo_auth_init: No account found in %s.\n", account_filename);
  708. sprintf(line, "No account found in %s.", account_filename);
  709. } else {
  710. if (auth_num == 1) {
  711. printf("mmo_auth_init: 1 account read in %s,\n", account_filename);
  712. sprintf(line, "1 account read in %s,", account_filename);
  713. } else {
  714. printf("mmo_auth_init: %d accounts read in %s,\n", auth_num, account_filename);
  715. sprintf(line, "%d accounts read in %s,", auth_num, account_filename);
  716. }
  717. if (GM_count == 0) {
  718. printf(" of which is no GM account, and ");
  719. sprintf(str, "%s of which is no GM account and", line);
  720. } else if (GM_count == 1) {
  721. printf(" of which is 1 GM account, and ");
  722. sprintf(str, "%s of which is 1 GM account and", line);
  723. } else {
  724. printf(" of which is %d GM accounts, and ", GM_count);
  725. sprintf(str, "%s of which is %d GM accounts and", line, GM_count);
  726. }
  727. if (server_count == 0) {
  728. printf("no server account ('S').\n");
  729. sprintf(line, "%s no server account ('S').", str);
  730. } else if (server_count == 1) {
  731. printf("1 server account ('S').\n");
  732. sprintf(line, "%s 1 server account ('S').", str);
  733. } else {
  734. printf("%d server accounts ('S').\n", server_count);
  735. sprintf(line, "%s %d server accounts ('S').", str, server_count);
  736. }
  737. }
  738. login_log("%s" RETCODE, line);
  739. return 0;
  740. }
  741. //------------------------------------------
  742. // Writing of the accounts database file
  743. // (accounts are sorted by id before save)
  744. //------------------------------------------
  745. void mmo_auth_sync(void) {
  746. FILE *fp;
  747. int i, j, k, lock;
  748. int account_id;
  749. //int id[auth_num];
  750. //int *id = (int *)aCalloc(auth_num, sizeof(int));
  751. CREATE_BUFFER(id, int, auth_num);
  752. char line[65536];
  753. // Sorting before save
  754. for(i = 0; i < auth_num; i++) {
  755. id[i] = i;
  756. account_id = auth_dat[i].account_id;
  757. for(j = 0; j < i; j++) {
  758. if (account_id < auth_dat[id[j]].account_id) {
  759. for(k = i; k > j; k--)
  760. id[k] = id[k-1];
  761. id[j] = i; // id[i]
  762. break;
  763. }
  764. }
  765. }
  766. // Data save
  767. if ((fp = lock_fopen(account_filename, &lock)) == NULL) {
  768. //if (id) aFree(id); // aFree, right?
  769. DELETE_BUFFER(id);
  770. return;
  771. }
  772. fprintf(fp, "// Accounts file: here are saved all information about the accounts.\n");
  773. fprintf(fp, "// Structure: ID, account name, password, last login time, sex, # of logins, state, email, error message for state 7, validity time, last (accepted) login ip, memo field, ban timestamp, repeated(register text, register value)\n");
  774. fprintf(fp, "// Some explanations:\n");
  775. fprintf(fp, "// account name : between 4 to 23 char for a normal account (standard client can't send less than 4 char).\n");
  776. fprintf(fp, "// account password: between 4 to 23 char\n");
  777. fprintf(fp, "// sex : M or F for normal accounts, S for server accounts\n");
  778. fprintf(fp, "// state : 0: account is ok, 1 to 256: error code of packet 0x006a + 1\n");
  779. fprintf(fp, "// email : between 3 to 39 char (a@a.com is like no email)\n");
  780. fprintf(fp, "// error message : text for the state 7: 'Your are Prohibited to login until <text>'. Max 19 char\n");
  781. fprintf(fp, "// valitidy time : 0: unlimited account, <other value>: date calculated by addition of 1/1/1970 + value (number of seconds since the 1/1/1970)\n");
  782. fprintf(fp, "// memo field : max 254 char\n");
  783. fprintf(fp, "// ban time : 0: no ban, <other value>: banned until the date: date calculated by addition of 1/1/1970 + value (number of seconds since the 1/1/1970)\n");
  784. for(i = 0; i < auth_num; i++) {
  785. k = id[i]; // use of sorted index
  786. if (auth_dat[k].account_id < 0)
  787. continue;
  788. mmo_auth_tostr(line, &auth_dat[k]);
  789. fprintf(fp, "%s" RETCODE, line);
  790. }
  791. fprintf(fp, "%d\t%%newid%%\n", account_id_count);
  792. lock_fclose(fp, account_filename, &lock);
  793. // set new counter to minimum number of auth before save
  794. auth_before_save_file = auth_num / AUTH_SAVE_FILE_DIVIDER; // Re-initialise counter. We have save.
  795. if (auth_before_save_file < AUTH_BEFORE_SAVE_FILE)
  796. auth_before_save_file = AUTH_BEFORE_SAVE_FILE;
  797. //if (id) aFree(id);
  798. DELETE_BUFFER(id);
  799. return;
  800. }
  801. //-----------------------------------------------------
  802. // Check if we must save accounts file or not
  803. // every minute, we check if we must save because we
  804. // have do some authentifications without arrive to
  805. // the minimum of authentifications for the save.
  806. // Note: all other modification of accounts (deletion,
  807. // change of some informations excepted lastip/
  808. // lastlogintime, creation) are always save
  809. // immediatly and set the minimum of
  810. // authentifications to its initialization value.
  811. //-----------------------------------------------------
  812. int check_auth_sync(int tid, unsigned int tick, int id, int data) {
  813. // we only save if necessary:
  814. // we have do some authentifications without do saving
  815. if (auth_before_save_file < AUTH_BEFORE_SAVE_FILE ||
  816. auth_before_save_file < (int)(auth_num / AUTH_SAVE_FILE_DIVIDER))
  817. mmo_auth_sync();
  818. return 0;
  819. }
  820. //--------------------------------------------------------------------
  821. // Packet send to all char-servers, except one (wos: without our self)
  822. //--------------------------------------------------------------------
  823. int charif_sendallwos(int sfd, unsigned char *buf, unsigned int len) {
  824. int i, c, fd;
  825. for(i = 0, c = 0; i < MAX_SERVERS; i++) {
  826. if ((fd = server_fd[i]) >= 0 && fd != sfd) {
  827. memcpy(WFIFOP(fd,0), buf, len);
  828. WFIFOSET(fd, len);
  829. c++;
  830. }
  831. }
  832. return c;
  833. }
  834. //-----------------------------------------------------
  835. // Send GM accounts to all char-server
  836. //-----------------------------------------------------
  837. void send_GM_accounts() {
  838. int i;
  839. unsigned char buf[32767];
  840. int len;
  841. len = 4;
  842. WBUFW(buf,0) = 0x2732;
  843. for(i = 0; i < GM_num; i++)
  844. // send only existing accounts. We can not create a GM account when server is online.
  845. if (gm_account_db[i].level > 0) {
  846. WBUFL(buf,len) = gm_account_db[i].account_id;
  847. WBUFB(buf,len+4) = (unsigned char)gm_account_db[i].level;
  848. len += 5;
  849. }
  850. WBUFW(buf,2) = len;
  851. charif_sendallwos(-1, buf, len);
  852. return;
  853. }
  854. //-----------------------------------------------------
  855. // Check if GM file account have been changed
  856. //-----------------------------------------------------
  857. int check_GM_file(int tid, unsigned int tick, int id, int data) {
  858. struct stat file_stat;
  859. long new_time;
  860. // if we would not check
  861. if (gm_account_filename_check_timer < 1)
  862. return 0;
  863. // get last modify time/date
  864. if (stat(GM_account_filename, &file_stat))
  865. new_time = 0; // error
  866. else
  867. new_time = file_stat.st_mtime;
  868. if (new_time != creation_time_GM_account_file) {
  869. read_gm_account();
  870. send_GM_accounts();
  871. }
  872. return 0;
  873. }
  874. //-------------------------------------
  875. // Account creation (with e-mail check)
  876. //-------------------------------------
  877. int mmo_auth_new(struct mmo_account* account, char sex, char* email) {
  878. time_t timestamp, timestamp_temp;
  879. struct tm *tmtime;
  880. int i = auth_num;
  881. if (auth_num >= auth_max) {
  882. auth_max += 256;
  883. auth_dat = (struct auth_dat*)aRealloc(auth_dat, sizeof(struct auth_dat) * auth_max);
  884. }
  885. memset(&auth_dat[i], '\0', sizeof(struct auth_dat));
  886. while (isGM(account_id_count) > 0)
  887. account_id_count++;
  888. auth_dat[i].account_id = account_id_count++;
  889. strncpy(auth_dat[i].userid, account->userid, 24);
  890. auth_dat[i].userid[23] = '\0';
  891. strncpy(auth_dat[i].pass, account->passwd, 32);
  892. auth_dat[i].pass[23] = '\0';
  893. memcpy(auth_dat[i].lastlogin, "-", 2);
  894. auth_dat[i].sex = (sex == 'M');
  895. auth_dat[i].logincount = 0;
  896. auth_dat[i].state = 0;
  897. if (e_mail_check(email) == 0)
  898. strncpy(auth_dat[i].email, "a@a.com", 40);
  899. else
  900. strncpy(auth_dat[i].email, email, 40);
  901. strncpy(auth_dat[i].error_message, "-", 20);
  902. auth_dat[i].ban_until_time = 0;
  903. if (start_limited_time < 0)
  904. auth_dat[i].connect_until_time = 0; // unlimited
  905. else { // limited time
  906. timestamp = time(NULL) + start_limited_time;
  907. // double conversion to be sure that it is possible
  908. tmtime = localtime(&timestamp);
  909. timestamp_temp = mktime(tmtime);
  910. if (timestamp_temp != -1 && (timestamp_temp + 3600) >= timestamp) // check possible value and overflow (and avoid summer/winter hour)
  911. auth_dat[i].connect_until_time = timestamp_temp;
  912. else
  913. auth_dat[i].connect_until_time = 0; // unlimited
  914. }
  915. strncpy(auth_dat[i].last_ip, "-", 16);
  916. strncpy(auth_dat[i].memo, "-", 255);
  917. auth_dat[i].account_reg2_num = 0;
  918. auth_num++;
  919. return (account_id_count - 1);
  920. }
  921. //---------------------------------------
  922. // Check/authentification of a connection
  923. //---------------------------------------
  924. int mmo_auth(struct mmo_account* account, int fd) {
  925. int i;
  926. struct timeval tv;
  927. char tmpstr[256];
  928. int len, newaccount = 0;
  929. #ifdef PASSWORDENC
  930. struct login_session_data *ld;
  931. #endif
  932. int encpasswdok;
  933. char md5str[64], md5bin[32];
  934. char ip[16];
  935. unsigned char *sin_addr = (unsigned char *)&session[fd]->client_addr.sin_addr;
  936. char user_password[256];
  937. sprintf(ip, "%d.%d.%d.%d", sin_addr[0], sin_addr[1], sin_addr[2], sin_addr[3]);
  938. len = strlen(account->userid) - 2;
  939. // Account creation with _M/_F
  940. if (account->passwdenc == 0 && account->userid[len] == '_' &&
  941. (account->userid[len+1] == 'F' || account->userid[len+1] == 'M') && new_account_flag == 1 &&
  942. account_id_count <= END_ACCOUNT_NUM && len >= 4 && strlen(account->passwd) >= 4) {
  943. if (new_account_flag == 1)
  944. newaccount = 1;
  945. account->userid[len] = '\0';
  946. }
  947. //EXE Version check [Sirius]
  948. if(check_client_version == 1 && account->version != 0){
  949. if(account->version != client_version_to_connect){
  950. return 5;
  951. }
  952. }
  953. // Strict account search
  954. for(i = 0; i < auth_num; i++) {
  955. if (strcmp(account->userid, auth_dat[i].userid) == 0)
  956. break;
  957. }
  958. // if there is no creation request and strict account search fails, we do a no sensitive case research for index
  959. if (newaccount == 0 && i == auth_num) {
  960. i = search_account_index(account->userid);
  961. if (i == -1)
  962. i = auth_num;
  963. else
  964. memcpy(account->userid, auth_dat[i].userid, 24); // for the possible tests/checks afterwards (copy correcte sensitive case).
  965. }
  966. if (i != auth_num) {
  967. if (newaccount) {
  968. login_log("Attempt of creation of an already existant account (account: %s_%c, pass: %s, received pass: %s, ip: %s)" RETCODE,
  969. account->userid, account->userid[len+1], auth_dat[i].pass, account->passwd, ip);
  970. return 1; // 1 = Incorrect Password
  971. }
  972. if(use_md5_passwds)
  973. MD5_String(account->passwd, user_password);
  974. else
  975. memcpy(user_password, account->passwd, 25);
  976. encpasswdok = 0;
  977. #ifdef PASSWORDENC
  978. ld = (struct login_session_data*)session[fd]->session_data;
  979. if (account->passwdenc > 0) {
  980. int j = account->passwdenc;
  981. if (!ld) {
  982. login_log("Md5 key not created (account: %s, ip: %s)" RETCODE, account->userid, ip);
  983. return 1; // 1 = Incorrect Password
  984. }
  985. if (j > 2)
  986. j = 1;
  987. do {
  988. if (j == 1) {
  989. sprintf(md5str, "%s%s", ld->md5key, auth_dat[i].pass); // 20 + 24
  990. } else if (j == 2) {
  991. sprintf(md5str, "%s%s", auth_dat[i].pass, ld->md5key); // 24 + 20
  992. } else
  993. md5str[0] = '\0';
  994. md5str[sizeof(md5str)-1] = '\0'; // 64
  995. MD5_String2binary(md5str, md5bin);
  996. encpasswdok = (memcmp(account->passwd, md5bin, 16) == 0);
  997. } while (j < 2 && !encpasswdok && (j++) != account->passwdenc);
  998. // printf("key[%s] md5 [%s] ", md5key, md5);
  999. // printf("client [%s] accountpass [%s]\n", account->passwd, auth_dat[i].pass);
  1000. }
  1001. #endif
  1002. if ((strcmp(account->passwd, auth_dat[i].pass) && !encpasswdok)) {
  1003. if (account->passwdenc == 0)
  1004. login_log("Invalid password (account: %s, pass: %s, received pass: %s, ip: %s)" RETCODE, account->userid, auth_dat[i].pass, account->passwd, ip);
  1005. #ifdef PASSWORDENC
  1006. else {
  1007. char logbuf[512], *p = logbuf;
  1008. int j;
  1009. p += sprintf(p, "Invalid password (account: %s, received md5[", account->userid);
  1010. for(j = 0; j < 16; j++)
  1011. p += sprintf(p, "%02x", ((unsigned char *)account->passwd)[j]);
  1012. p += sprintf(p,"] calculated md5[");
  1013. for(j = 0; j < 16; j++)
  1014. p += sprintf(p, "%02x", ((unsigned char *)md5bin)[j]);
  1015. p += sprintf(p, "] md5 key[");
  1016. for(j = 0; j < ld->md5keylen; j++)
  1017. p += sprintf(p, "%02x", ((unsigned char *)ld->md5key)[j]);
  1018. p += sprintf(p, "], ip: %s)" RETCODE, ip);
  1019. login_log(logbuf);
  1020. }
  1021. #endif
  1022. return 1; // 1 = Incorrect Password
  1023. }
  1024. if (auth_dat[i].state) {
  1025. login_log("Connection refused (account: %s, pass: %s, state: %d, ip: %s)" RETCODE,
  1026. account->userid, account->passwd, auth_dat[i].state, ip);
  1027. switch(auth_dat[i].state) { // packet 0x006a value + 1
  1028. case 1: // 0 = Unregistered ID
  1029. case 2: // 1 = Incorrect Password
  1030. case 3: // 2 = This ID is expired
  1031. case 4: // 3 = Rejected from Server
  1032. case 5: // 4 = You have been blocked by the GM Team
  1033. case 6: // 5 = Your Game's EXE file is not the latest version
  1034. case 7: // 6 = Your are Prohibited to log in until %s
  1035. case 8: // 7 = Server is jammed due to over populated
  1036. case 9: // 8 = No MSG (actually, all states after 9 except 99 are No MSG, use only this)
  1037. case 100: // 99 = This ID has been totally erased
  1038. return auth_dat[i].state - 1;
  1039. default:
  1040. return 99; // 99 = ID has been totally erased
  1041. }
  1042. }
  1043. if (auth_dat[i].ban_until_time != 0) { // if account is banned
  1044. strftime(tmpstr, 20, date_format, localtime(&auth_dat[i].ban_until_time));
  1045. tmpstr[19] = '\0';
  1046. if (auth_dat[i].ban_until_time > time(NULL)) { // always banned
  1047. login_log("Connection refused (account: %s, pass: %s, banned until %s, ip: %s)" RETCODE,
  1048. account->userid, account->passwd, tmpstr, ip);
  1049. return 6; // 6 = Your are Prohibited to log in until %s
  1050. } else { // ban is finished
  1051. login_log("End of ban (account: %s, pass: %s, previously banned until %s -> not more banned, ip: %s)" RETCODE,
  1052. account->userid, account->passwd, tmpstr, ip);
  1053. auth_dat[i].ban_until_time = 0; // reset the ban time
  1054. }
  1055. }
  1056. if (auth_dat[i].connect_until_time != 0 && auth_dat[i].connect_until_time < time(NULL)) {
  1057. login_log("Connection refused (account: %s, pass: %s, expired ID, ip: %s)" RETCODE,
  1058. account->userid, account->passwd, ip);
  1059. return 2; // 2 = This ID is expired
  1060. }
  1061. login_log("Authentification accepted (account: %s (id: %d), ip: %s)" RETCODE, account->userid, auth_dat[i].account_id, ip);
  1062. } else {
  1063. if (newaccount == 0) {
  1064. login_log("Unknown account (account: %s, received pass: %s, ip: %s)" RETCODE,
  1065. account->userid, account->passwd, ip);
  1066. return 0; // 0 = Unregistered ID
  1067. } else {
  1068. int new_id = mmo_auth_new(account, account->userid[len+1], "a@a.com");
  1069. login_log("Account creation and authentification accepted (account %s (id: %d), pass: %s, sex: %c, connection with _F/_M, ip: %s)" RETCODE,
  1070. account->userid, new_id, account->passwd, account->userid[len+1], ip);
  1071. auth_before_save_file = 0; // Creation of an account -> save accounts file immediatly
  1072. }
  1073. }
  1074. gettimeofday(&tv, NULL);
  1075. strftime(tmpstr, 24, date_format, localtime((const time_t*)&(tv.tv_sec)));
  1076. sprintf(tmpstr + strlen(tmpstr), ".%03d", (int)tv.tv_usec / 1000);
  1077. account->account_id = auth_dat[i].account_id;
  1078. account->login_id1 = rand();
  1079. account->login_id2 = rand();
  1080. memcpy(account->lastlogin, auth_dat[i].lastlogin, 24);
  1081. memcpy(auth_dat[i].lastlogin, tmpstr, 24);
  1082. account->sex = auth_dat[i].sex;
  1083. strncpy(auth_dat[i].last_ip, ip, 16);
  1084. auth_dat[i].logincount++;
  1085. // Save until for change ip/time of auth is not very useful => limited save for that
  1086. // Save there informations isnot necessary, because they are saved in log file.
  1087. if (--auth_before_save_file <= 0) // Reduce counter. 0 or less, we save
  1088. mmo_auth_sync();
  1089. return -1; // account OK
  1090. }
  1091. //-------------------------------
  1092. // Char-server anti-freeze system
  1093. //-------------------------------
  1094. int char_anti_freeze_system(int tid, unsigned int tick, int id, int data) {
  1095. int i;
  1096. //printf("Entering in char_anti_freeze_system function to check freeze of servers.\n");
  1097. for(i = 0; i < MAX_SERVERS; i++) {
  1098. if (server_fd[i] >= 0) {// if char-server is online
  1099. //printf("char_anti_freeze_system: server #%d '%s', flag: %d.\n", i, server[i].name, server_freezeflag[i]);
  1100. if (server_freezeflag[i]-- < 1) { // Char-server anti-freeze system. Counter. 5 ok, 4...0 freezed
  1101. printf("Char-server anti-freeze system: char-server #%d '%s' is freezed -> disconnection.\n", i, server[i].name);
  1102. login_log("Char-server anti-freeze system: char-server #%d '%s' is freezed -> disconnection." RETCODE,
  1103. i, server[i].name);
  1104. session[server_fd[i]]->eof = 1;
  1105. } else {
  1106. // send alive packet to check connection
  1107. WFIFOW(server_fd[i],0) = 0x2718;
  1108. WFIFOSET(server_fd[i],2);
  1109. }
  1110. }
  1111. }
  1112. return 0;
  1113. }
  1114. //--------------------------------
  1115. // Packet parsing for char-servers
  1116. //--------------------------------
  1117. int parse_fromchar(int fd) {
  1118. int i, j, id;
  1119. unsigned char *p = (unsigned char *) &session[fd]->client_addr.sin_addr;
  1120. char ip[16];
  1121. int acc;
  1122. sprintf(ip, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
  1123. for(id = 0; id < MAX_SERVERS; id++)
  1124. if (server_fd[id] == fd)
  1125. break;
  1126. if (id == MAX_SERVERS)
  1127. session[fd]->eof = 1;
  1128. if(session[fd]->eof) {
  1129. if (id < MAX_SERVERS) {
  1130. printf("Char-server '%s' has disconnected.\n", server[id].name);
  1131. login_log("Char-server '%s' has disconnected (ip: %s)." RETCODE,
  1132. server[id].name, ip);
  1133. server_fd[id] = -1;
  1134. memset(&server[id], 0, sizeof(struct mmo_char_server));
  1135. }
  1136. close(fd);
  1137. delete_session(fd);
  1138. return 0;
  1139. }
  1140. while (RFIFOREST(fd) >= 2) {
  1141. if (display_parse_fromchar == 2 || (display_parse_fromchar == 1 && RFIFOW(fd,0) != 0x2714)) // 0x2714 is done very often (number of players)
  1142. printf("parse_fromchar: connection #%d, packet: 0x%x (with being read: %d bytes).\n", fd, RFIFOW(fd,0), RFIFOREST(fd));
  1143. switch (RFIFOW(fd,0)) {
  1144. // request from map-server via char-server to reload GM accounts (by Yor).
  1145. case 0x2709:
  1146. login_log("Char-server '%s': Request to re-load GM configuration file (ip: %s)." RETCODE, server[id].name, ip);
  1147. read_gm_account();
  1148. // send GM accounts to all char-servers
  1149. send_GM_accounts();
  1150. RFIFOSKIP(fd,2);
  1151. break;
  1152. case 0x2712: // request from char-server to authentify an account
  1153. if (RFIFOREST(fd) < 19)
  1154. return 0;
  1155. {
  1156. int acc;
  1157. acc = RFIFOL(fd,2); // speed up
  1158. for(i = 0; i < AUTH_FIFO_SIZE; i++) {
  1159. if (auth_fifo[i].account_id == acc &&
  1160. auth_fifo[i].login_id1 == RFIFOL(fd,6) &&
  1161. #if CMP_AUTHFIFO_LOGIN2 != 0
  1162. auth_fifo[i].login_id2 == RFIFOL(fd,10) && // relate to the versions higher than 18
  1163. #endif
  1164. auth_fifo[i].sex == RFIFOB(fd,14) &&
  1165. (!check_ip_flag || auth_fifo[i].ip == RFIFOL(fd,15)) &&
  1166. !auth_fifo[i].delflag) {
  1167. int p, k;
  1168. auth_fifo[i].delflag = 1;
  1169. login_log("Char-server '%s': authentification of the account %d accepted (ip: %s)." RETCODE,
  1170. server[id].name, acc, ip);
  1171. // printf("%d\n", i);
  1172. for(k = 0; k < auth_num; k++) {
  1173. if (auth_dat[k].account_id == acc) {
  1174. WFIFOW(fd,0) = 0x2729; // Sending of the account_reg2
  1175. WFIFOL(fd,4) = acc;
  1176. for(p = 8, j = 0; j < auth_dat[k].account_reg2_num; p += 36, j++) {
  1177. memcpy(WFIFOP(fd,p), auth_dat[k].account_reg2[j].str, 32);
  1178. WFIFOL(fd,p+32) = auth_dat[k].account_reg2[j].value;
  1179. }
  1180. WFIFOW(fd,2) = p;
  1181. WFIFOSET(fd,p);
  1182. // printf("parse_fromchar: Sending of account_reg2: login->char (auth fifo)\n");
  1183. WFIFOW(fd,0) = 0x2713;
  1184. WFIFOL(fd,2) = acc;
  1185. WFIFOB(fd,6) = 0;
  1186. memcpy(WFIFOP(fd, 7), auth_dat[k].email, 40);
  1187. WFIFOL(fd,47) = (unsigned long)auth_dat[k].connect_until_time;
  1188. WFIFOSET(fd,51);
  1189. break;
  1190. }
  1191. }
  1192. break;
  1193. }
  1194. }
  1195. // authentification not found
  1196. if (i == AUTH_FIFO_SIZE) {
  1197. login_log("Char-server '%s': authentification of the account %d REFUSED (ip: %s)." RETCODE,
  1198. server[id].name, acc, ip);
  1199. WFIFOW(fd,0) = 0x2713;
  1200. WFIFOL(fd,2) = acc;
  1201. WFIFOB(fd,6) = 1;
  1202. // It is unnecessary to send email
  1203. // It is unnecessary to send validity date of the account
  1204. WFIFOSET(fd,51);
  1205. }
  1206. }
  1207. RFIFOSKIP(fd,19);
  1208. break;
  1209. case 0x2714:
  1210. if (RFIFOREST(fd) < 6)
  1211. return 0;
  1212. //printf("parse_fromchar: Receiving of the users number of the server '%s': %d\n", server[id].name, RFIFOL(fd,2));
  1213. server[id].users = RFIFOL(fd,2);
  1214. if(anti_freeze_enable)
  1215. server_freezeflag[id] = 5; // Char anti-freeze system. Counter. 5 ok, 4...0 freezed
  1216. RFIFOSKIP(fd,6);
  1217. break;
  1218. // we receive a e-mail creation of an account with a default e-mail (no answer)
  1219. case 0x2715:
  1220. if (RFIFOREST(fd) < 46)
  1221. return 0;
  1222. {
  1223. char email[40];
  1224. acc = RFIFOL(fd,2); // speed up
  1225. memcpy(email, RFIFOP(fd,6), 40);
  1226. email[39] = '\0';
  1227. remove_control_chars((unsigned char *)email);
  1228. //printf("parse_fromchar: an e-mail creation of an account with a default e-mail: server '%s', account: %d, e-mail: '%s'.\n", server[id].name, acc, RFIFOP(fd,6));
  1229. if (e_mail_check(email) == 0)
  1230. login_log("Char-server '%s': Attempt to create an e-mail on an account with a default e-mail REFUSED - e-mail is invalid (account: %d, ip: %s)" RETCODE,
  1231. server[id].name, acc, ip);
  1232. else {
  1233. for(i = 0; i < auth_num; i++) {
  1234. if (auth_dat[i].account_id == acc && (strcmp(auth_dat[i].email, "a@a.com") == 0 || auth_dat[i].email[0] == '\0')) {
  1235. memcpy(auth_dat[i].email, email, 40);
  1236. login_log("Char-server '%s': Create an e-mail on an account with a default e-mail (account: %d, new e-mail: %s, ip: %s)." RETCODE,
  1237. server[id].name, acc, email, ip);
  1238. // Save
  1239. mmo_auth_sync();
  1240. break;
  1241. }
  1242. }
  1243. if (i == auth_num)
  1244. login_log("Char-server '%s': Attempt to create an e-mail on an account with a default e-mail REFUSED - account doesn't exist or e-mail of account isn't default e-mail (account: %d, ip: %s)." RETCODE,
  1245. server[id].name, acc, ip);
  1246. }
  1247. }
  1248. RFIFOSKIP(fd,46);
  1249. break;
  1250. // We receive an e-mail/limited time request, because a player comes back from a map-server to the char-server
  1251. case 0x2716:
  1252. if (RFIFOREST(fd) < 6)
  1253. return 0;
  1254. //printf("parse_fromchar: E-mail/limited time request from '%s' server (concerned account: %d)\n", server[id].name, RFIFOL(fd,2));
  1255. for(i = 0; i < auth_num; i++) {
  1256. if (auth_dat[i].account_id == RFIFOL(fd,2)) {
  1257. login_log("Char-server '%s': e-mail of the account %d found (ip: %s)." RETCODE,
  1258. server[id].name, RFIFOL(fd,2), ip);
  1259. WFIFOW(fd,0) = 0x2717;
  1260. WFIFOL(fd,2) = RFIFOL(fd,2);
  1261. memcpy(WFIFOP(fd, 6), auth_dat[i].email, 40);
  1262. WFIFOL(fd,46) = (unsigned long)auth_dat[i].connect_until_time;
  1263. WFIFOSET(fd,50);
  1264. break;
  1265. }
  1266. }
  1267. if (i == auth_num)
  1268. login_log("Char-server '%s': e-mail of the account %d NOT found (ip: %s)." RETCODE,
  1269. server[id].name, RFIFOL(fd,2), ip);
  1270. RFIFOSKIP(fd,6);
  1271. break;
  1272. case 0x2720: // To become GM request
  1273. if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
  1274. return 0;
  1275. {
  1276. unsigned char buf[10];
  1277. FILE *fp;
  1278. acc = RFIFOL(fd,4);
  1279. //printf("parse_fromchar: Request to become a GM acount from %d account.\n", acc);
  1280. WBUFW(buf,0) = 0x2721;
  1281. WBUFL(buf,2) = acc;
  1282. WBUFL(buf,6) = 0;
  1283. if (strcmp((char*)RFIFOP(fd,8), gm_pass) == 0) {
  1284. // only non-GM can become GM
  1285. if (isGM(acc) == 0) {
  1286. // if we autorise creation
  1287. if (level_new_gm > 0) {
  1288. // if we can open the file to add the new GM
  1289. if ((fp = fopen(GM_account_filename, "a")) != NULL) {
  1290. char tmpstr[24];
  1291. struct timeval tv;
  1292. gettimeofday(&tv, NULL);
  1293. strftime(tmpstr, 23, date_format, localtime((const time_t*)&(tv.tv_sec)));
  1294. fprintf(fp, RETCODE "// %s: @GM command on account %d" RETCODE "%d %d" RETCODE, tmpstr, acc, acc, level_new_gm);
  1295. fclose(fp);
  1296. WBUFL(buf,6) = level_new_gm;
  1297. read_gm_account();
  1298. send_GM_accounts();
  1299. printf("GM Change of the account %d: level 0 -> %d.\n", acc, level_new_gm);
  1300. login_log("Char-server '%s': GM Change of the account %d: level 0 -> %d (ip: %s)." RETCODE,
  1301. server[id].name, acc, level_new_gm, ip);
  1302. } else {
  1303. printf("Error of GM change (suggested account: %d, correct password, unable to add a GM account in GM accounts file)\n", acc);
  1304. login_log("Char-server '%s': Error of GM change (suggested account: %d, correct password, unable to add a GM account in GM accounts file, ip: %s)." RETCODE,
  1305. server[id].name, acc, ip);
  1306. }
  1307. } else {
  1308. printf("Error of GM change (suggested account: %d, correct password, but GM creation is disable (level_new_gm = 0))\n", acc);
  1309. login_log("Char-server '%s': Error of GM change (suggested account: %d, correct password, but GM creation is disable (level_new_gm = 0), ip: %s)." RETCODE,
  1310. server[id].name, acc, ip);
  1311. }
  1312. } else {
  1313. printf("Error of GM change (suggested account: %d (already GM), correct password).\n", acc);
  1314. login_log("Char-server '%s': Error of GM change (suggested account: %d (already GM), correct password, ip: %s)." RETCODE,
  1315. server[id].name, acc, ip);
  1316. }
  1317. } else {
  1318. printf("Error of GM change (suggested account: %d, invalid password).\n", acc);
  1319. login_log("Char-server '%s': Error of GM change (suggested account: %d, invalid password, ip: %s)." RETCODE,
  1320. server[id].name, acc, ip);
  1321. }
  1322. charif_sendallwos(-1, buf, 10);
  1323. }
  1324. RFIFOSKIP(fd, RFIFOW(fd,2));
  1325. return 0;
  1326. // Map server send information to change an email of an account via char-server
  1327. case 0x2722: // 0x2722 <account_id>.L <actual_e-mail>.40B <new_e-mail>.40B
  1328. if (RFIFOREST(fd) < 86)
  1329. return 0;
  1330. {
  1331. char actual_email[40], new_email[40];
  1332. acc = RFIFOL(fd,2);
  1333. memcpy(actual_email, RFIFOP(fd,6), 40);
  1334. actual_email[39] = '\0';
  1335. remove_control_chars((unsigned char *)actual_email);
  1336. memcpy(new_email, RFIFOP(fd,46), 40);
  1337. new_email[39] = '\0';
  1338. remove_control_chars((unsigned char *)new_email);
  1339. if (e_mail_check(actual_email) == 0)
  1340. login_log("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual email is invalid (account: %d, ip: %s)" RETCODE,
  1341. server[id].name, acc, ip);
  1342. else if (e_mail_check(new_email) == 0)
  1343. login_log("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)" RETCODE,
  1344. server[id].name, acc, ip);
  1345. else if (strcmpi(new_email, "a@a.com") == 0)
  1346. login_log("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a default e-mail (account: %d, ip: %s)" RETCODE,
  1347. server[id].name, acc, ip);
  1348. else {
  1349. for(i = 0; i < auth_num; i++) {
  1350. if (auth_dat[i].account_id == acc) {
  1351. if (strcmpi(auth_dat[i].email, actual_email) == 0) {
  1352. memcpy(auth_dat[i].email, new_email, 40);
  1353. login_log("Char-server '%s': Modify an e-mail on an account (@email GM command) (account: %d (%s), new e-mail: %s, ip: %s)." RETCODE,
  1354. server[id].name, acc, auth_dat[i].userid, new_email, ip);
  1355. // Save
  1356. mmo_auth_sync();
  1357. } else
  1358. login_log("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual e-mail is incorrect (account: %d (%s), actual e-mail: %s, proposed e-mail: %s, ip: %s)." RETCODE,
  1359. server[id].name, acc, auth_dat[i].userid, auth_dat[i].email, actual_email, ip);
  1360. break;
  1361. }
  1362. }
  1363. if (i == auth_num)
  1364. login_log("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but account doesn't exist (account: %d, ip: %s)." RETCODE,
  1365. server[id].name, acc, ip);
  1366. }
  1367. }
  1368. RFIFOSKIP(fd, 86);
  1369. break;
  1370. // Receiving of map-server via char-server a status change resquest (by Yor)
  1371. case 0x2724:
  1372. if (RFIFOREST(fd) < 10)
  1373. return 0;
  1374. {
  1375. int acc, statut;
  1376. acc = RFIFOL(fd,2);
  1377. statut = RFIFOL(fd,6);
  1378. for(i = 0; i < auth_num; i++) {
  1379. if (auth_dat[i].account_id == acc) {
  1380. if (auth_dat[i].state != statut) {
  1381. login_log("Char-server '%s': Status change (account: %d, new status %d, ip: %s)." RETCODE,
  1382. server[id].name, acc, statut, ip);
  1383. if (statut != 0) {
  1384. unsigned char buf[16];
  1385. WBUFW(buf,0) = 0x2731;
  1386. WBUFL(buf,2) = acc;
  1387. WBUFB(buf,6) = 0; // 0: change of statut, 1: ban
  1388. WBUFL(buf,7) = statut; // status or final date of a banishment
  1389. charif_sendallwos(-1, buf, 11);
  1390. for(j = 0; j < AUTH_FIFO_SIZE; j++)
  1391. if (auth_fifo[j].account_id == acc)
  1392. auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentification)
  1393. }
  1394. auth_dat[i].state = statut;
  1395. // Save
  1396. mmo_auth_sync();
  1397. } else
  1398. login_log("Char-server '%s': Error of Status change - actual status is already the good status (account: %d, status %d, ip: %s)." RETCODE,
  1399. server[id].name, acc, statut, ip);
  1400. break;
  1401. }
  1402. }
  1403. if (i == auth_num) {
  1404. login_log("Char-server '%s': Error of Status change (account: %d not found, suggested status %d, ip: %s)." RETCODE,
  1405. server[id].name, acc, statut, ip);
  1406. }
  1407. RFIFOSKIP(fd,10);
  1408. }
  1409. return 0;
  1410. case 0x2725: // Receiving of map-server via char-server a ban resquest (by Yor)
  1411. if (RFIFOREST(fd) < 18)
  1412. return 0;
  1413. {
  1414. acc = RFIFOL(fd,2);
  1415. for(i = 0; i < auth_num; i++) {
  1416. if (auth_dat[i].account_id == acc) {
  1417. time_t timestamp;
  1418. struct tm *tmtime;
  1419. if (auth_dat[i].ban_until_time == 0 || auth_dat[i].ban_until_time < time(NULL))
  1420. timestamp = time(NULL);
  1421. else
  1422. timestamp = auth_dat[i].ban_until_time;
  1423. tmtime = localtime(&timestamp);
  1424. tmtime->tm_year = tmtime->tm_year + (short)RFIFOW(fd,6);
  1425. tmtime->tm_mon = tmtime->tm_mon + (short)RFIFOW(fd,8);
  1426. tmtime->tm_mday = tmtime->tm_mday + (short)RFIFOW(fd,10);
  1427. tmtime->tm_hour = tmtime->tm_hour + (short)RFIFOW(fd,12);
  1428. tmtime->tm_min = tmtime->tm_min + (short)RFIFOW(fd,14);
  1429. tmtime->tm_sec = tmtime->tm_sec + (short)RFIFOW(fd,16);
  1430. timestamp = mktime(tmtime);
  1431. if (timestamp != -1) {
  1432. if (timestamp <= time(NULL))
  1433. timestamp = 0;
  1434. if (auth_dat[i].ban_until_time != timestamp) {
  1435. if (timestamp != 0) {
  1436. unsigned char buf[16];
  1437. char tmpstr[2048];
  1438. strftime(tmpstr, 24, date_format, localtime(&timestamp));
  1439. login_log("Char-server '%s': Ban request (account: %d, new final date of banishment: %d (%s), ip: %s)." RETCODE,
  1440. server[id].name, acc, timestamp, (timestamp == 0 ? "no banishment" : tmpstr), ip);
  1441. WBUFW(buf,0) = 0x2731;
  1442. WBUFL(buf,2) = auth_dat[i].account_id;
  1443. WBUFB(buf,6) = 1; // 0: change of statut, 1: ban
  1444. WBUFL(buf,7) = timestamp; // status or final date of a banishment
  1445. charif_sendallwos(-1, buf, 11);
  1446. for(j = 0; j < AUTH_FIFO_SIZE; j++)
  1447. if (auth_fifo[j].account_id == acc)
  1448. auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentification)
  1449. } else {
  1450. login_log("Char-server '%s': Error of ban request (account: %d, new date unbans the account, ip: %s)." RETCODE,
  1451. server[id].name, acc, ip);
  1452. }
  1453. auth_dat[i].ban_until_time = timestamp;
  1454. // Save
  1455. mmo_auth_sync();
  1456. } else {
  1457. login_log("Char-server '%s': Error of ban request (account: %d, no change for ban date, ip: %s)." RETCODE,
  1458. server[id].name, acc, ip);
  1459. }
  1460. } else {
  1461. login_log("Char-server '%s': Error of ban request (account: %d, invalid date, ip: %s)." RETCODE,
  1462. server[id].name, acc, ip);
  1463. }
  1464. break;
  1465. }
  1466. }
  1467. if (i == auth_num)
  1468. login_log("Char-server '%s': Error of ban request (account: %d not found, ip: %s)." RETCODE,
  1469. server[id].name, acc, ip);
  1470. RFIFOSKIP(fd,18);
  1471. }
  1472. return 0;
  1473. case 0x2727: // Change of sex (sex is reversed)
  1474. if (RFIFOREST(fd) < 6)
  1475. return 0;
  1476. {
  1477. int sex;
  1478. acc = RFIFOL(fd,2);
  1479. for(i = 0; i < auth_num; i++) {
  1480. // printf("%d,", auth_dat[i].account_id);
  1481. if (auth_dat[i].account_id == acc) {
  1482. if (auth_dat[i].sex == 2)
  1483. login_log("Char-server '%s': Error of sex change - Server account (suggested account: %d, actual sex %d (Server), ip: %s)." RETCODE,
  1484. server[id].name, acc, auth_dat[i].sex, ip);
  1485. else {
  1486. unsigned char buf[16];
  1487. if (auth_dat[i].sex == 0)
  1488. sex = 1;
  1489. else
  1490. sex = 0;
  1491. login_log("Char-server '%s': Sex change (account: %d, new sex %c, ip: %s)." RETCODE,
  1492. server[id].name, acc, (sex == 2) ? 'S' : (sex ? 'M' : 'F'), ip);
  1493. for(j = 0; j < AUTH_FIFO_SIZE; j++)
  1494. if (auth_fifo[j].account_id == acc)
  1495. auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentification)
  1496. auth_dat[i].sex = sex;
  1497. WBUFW(buf,0) = 0x2723;
  1498. WBUFL(buf,2) = acc;
  1499. WBUFB(buf,6) = sex;
  1500. charif_sendallwos(-1, buf, 7);
  1501. // Save
  1502. mmo_auth_sync();
  1503. }
  1504. break;
  1505. }
  1506. }
  1507. if (i == auth_num)
  1508. login_log("Char-server '%s': Error of sex change (account: %d not found, sex would be reversed, ip: %s)." RETCODE,
  1509. server[id].name, acc, ip);
  1510. RFIFOSKIP(fd,6);
  1511. }
  1512. return 0;
  1513. case 0x2728: // We receive account_reg2 from a char-server, and we send them to other char-servers.
  1514. if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
  1515. return 0;
  1516. {
  1517. int p;
  1518. acc = RFIFOL(fd,4);
  1519. for(i = 0; i < auth_num; i++) {
  1520. if (auth_dat[i].account_id == acc) {
  1521. //unsigned char buf[RFIFOW(fd,2)+1];
  1522. unsigned char *buf;
  1523. buf = (unsigned char*)aCalloc(RFIFOW(fd,2)+1, sizeof(unsigned char));
  1524. login_log("Char-server '%s': receiving (from the char-server) of account_reg2 (account: %d, ip: %s)." RETCODE,
  1525. server[id].name, acc, ip);
  1526. for(p = 8, j = 0; p < RFIFOW(fd,2) && j < ACCOUNT_REG2_NUM; p += 36, j++) {
  1527. memcpy(auth_dat[i].account_reg2[j].str, RFIFOP(fd,p), 32);
  1528. auth_dat[i].account_reg2[j].str[31] = '\0';
  1529. remove_control_chars((unsigned char *)auth_dat[i].account_reg2[j].str);
  1530. auth_dat[i].account_reg2[j].value = RFIFOL(fd,p+32);
  1531. }
  1532. auth_dat[i].account_reg2_num = j;
  1533. // Sending information towards the other char-servers.
  1534. memcpy(WBUFP(buf,0), RFIFOP(fd,0), RFIFOW(fd,2));
  1535. WBUFW(buf,0) = 0x2729;
  1536. charif_sendallwos(fd, buf, WBUFW(buf,2));
  1537. // Save
  1538. mmo_auth_sync();
  1539. // printf("parse_fromchar: receiving (from the char-server) of account_reg2 (account id: %d).\n", acc);
  1540. if (buf) free(buf);
  1541. break;
  1542. }
  1543. }
  1544. if (i == auth_num) {
  1545. // printf("parse_fromchar: receiving (from the char-server) of account_reg2 (unknwon account id: %d).\n", acc);
  1546. login_log("Char-server '%s': receiving (from the char-server) of account_reg2 (account: %d not found, ip: %s)." RETCODE,
  1547. server[id].name, acc, ip);
  1548. }
  1549. }
  1550. RFIFOSKIP(fd,RFIFOW(fd,2));
  1551. break;
  1552. case 0x272a: // Receiving of map-server via char-server a unban resquest (by Yor)
  1553. if (RFIFOREST(fd) < 6)
  1554. return 0;
  1555. {
  1556. acc = RFIFOL(fd,2);
  1557. for(i = 0; i < auth_num; i++) {
  1558. if (auth_dat[i].account_id == acc) {
  1559. if (auth_dat[i].ban_until_time != 0) {
  1560. auth_dat[i].ban_until_time = 0;
  1561. login_log("Char-server '%s': UnBan request (account: %d, ip: %s)." RETCODE,
  1562. server[id].name, acc, ip);
  1563. } else {
  1564. login_log("Char-server '%s': Error of UnBan request (account: %d, no change for unban date, ip: %s)." RETCODE,
  1565. server[id].name, acc, ip);
  1566. }
  1567. break;
  1568. }
  1569. }
  1570. if (i == auth_num)
  1571. login_log("Char-server '%s': Error of UnBan request (account: %d not found, ip: %s)." RETCODE,
  1572. server[id].name, acc, ip);
  1573. RFIFOSKIP(fd,6);
  1574. }
  1575. return 0;
  1576. case 0x3000: //change sex for chrif_changesex()
  1577. if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
  1578. return 0;
  1579. {
  1580. int sex, i = 0;
  1581. acc = RFIFOL(fd,4);
  1582. sex = RFIFOB(fd,8);
  1583. if (sex != 0 && sex != 1)
  1584. sex = 0;
  1585. for(i = 0; i < auth_num; i++) {
  1586. if (auth_dat[i].account_id == acc) {
  1587. unsigned char buf[16];
  1588. login_log("Char-server '%s': Sex change (account: %d, new sex %c, ip: %s)." RETCODE,
  1589. server[id].name, acc, (sex == 2) ? 'S' : (sex ? 'M' : 'F'), ip);
  1590. auth_fifo[i].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentification)
  1591. auth_dat[i].sex = sex;
  1592. WBUFW(buf,0) = 0x2723;
  1593. WBUFL(buf,2) = acc;
  1594. WBUFB(buf,6) = sex;
  1595. charif_sendallwos(-1, buf, 7);
  1596. break;
  1597. }
  1598. }
  1599. if (i == auth_num) {
  1600. login_log("Char-server '%s': Error of Sex change (account: %d not found, suggested sex %c, ip: %s)." RETCODE,
  1601. server[id].name, acc, (sex == 2) ? 'S' : (sex ? 'M' : 'F'), ip);
  1602. }
  1603. RFIFOSKIP(fd,RFIFOW(fd,2));
  1604. }
  1605. return 0;
  1606. default:
  1607. {
  1608. FILE *logfp;
  1609. char tmpstr[24];
  1610. struct timeval tv;
  1611. logfp = fopen(login_log_unknown_packets_filename, "a");
  1612. if (logfp) {
  1613. gettimeofday(&tv, NULL);
  1614. strftime(tmpstr, 23, date_format, localtime((const time_t*)&(tv.tv_sec)));
  1615. fprintf(logfp, "%s.%03d: receiving of an unknown packet -> disconnection" RETCODE, tmpstr, (int)tv.tv_usec / 1000);
  1616. fprintf(logfp, "parse_fromchar: connection #%d (ip: %s), packet: 0x%x (with being read: %d)." RETCODE, fd, ip, RFIFOW(fd,0), RFIFOREST(fd));
  1617. fprintf(logfp, "Detail (in hex):" RETCODE);
  1618. fprintf(logfp, "---- 00-01-02-03-04-05-06-07 08-09-0A-0B-0C-0D-0E-0F" RETCODE);
  1619. memset(tmpstr, '\0', sizeof(tmpstr));
  1620. for(i = 0; i < RFIFOREST(fd); i++) {
  1621. if ((i & 15) == 0)
  1622. fprintf(logfp, "%04X ",i);
  1623. fprintf(logfp, "%02x ", RFIFOB(fd,i));
  1624. if (RFIFOB(fd,i) > 0x1f)
  1625. tmpstr[i % 16] = RFIFOB(fd,i);
  1626. else
  1627. tmpstr[i % 16] = '.';
  1628. if ((i - 7) % 16 == 0) // -8 + 1
  1629. fprintf(logfp, " ");
  1630. else if ((i + 1) % 16 == 0) {
  1631. fprintf(logfp, " %s" RETCODE, tmpstr);
  1632. memset(tmpstr, '\0', sizeof(tmpstr));
  1633. }
  1634. }
  1635. if (i % 16 != 0) {
  1636. for(j = i; j % 16 != 0; j++) {
  1637. fprintf(logfp, " ");
  1638. if ((j - 7) % 16 == 0) // -8 + 1
  1639. fprintf(logfp, " ");
  1640. }
  1641. fprintf(logfp, " %s" RETCODE, tmpstr);
  1642. }
  1643. fprintf(logfp, RETCODE);
  1644. fclose(logfp);
  1645. }
  1646. }
  1647. printf("parse_fromchar: Unknown packet 0x%x (from a char-server)! -> disconnection.\n", RFIFOW(fd,0));
  1648. session[fd]->eof = 1;
  1649. printf("Char-server has been disconnected (unknown packet).\n");
  1650. return 0;
  1651. }
  1652. }
  1653. return 0;
  1654. }
  1655. //---------------------------------------
  1656. // Packet parsing for administation login
  1657. //---------------------------------------
  1658. int parse_admin(int fd) {
  1659. int i, j;
  1660. unsigned char *p = (unsigned char *) &session[fd]->client_addr.sin_addr;
  1661. char* account_name;
  1662. char ip[16];
  1663. sprintf(ip, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
  1664. if (session[fd]->eof) {
  1665. close(fd);
  1666. delete_session(fd);
  1667. printf("Remote administration has disconnected (session #%d).\n", fd);
  1668. return 0;
  1669. }
  1670. while(RFIFOREST(fd) >= 2) {
  1671. if (display_parse_admin == 1)
  1672. printf("parse_admin: connection #%d, packet: 0x%x (with being read: %d).\n", fd, RFIFOW(fd,0), RFIFOREST(fd));
  1673. switch(RFIFOW(fd,0)) {
  1674. case 0x7530: // Request of the server version
  1675. login_log("'ladmin': Sending of the server version (ip: %s)" RETCODE, ip);
  1676. WFIFOW(fd,0) = 0x7531;
  1677. WFIFOB(fd,2) = ATHENA_MAJOR_VERSION;
  1678. WFIFOB(fd,3) = ATHENA_MINOR_VERSION;
  1679. WFIFOB(fd,4) = ATHENA_REVISION;
  1680. WFIFOB(fd,5) = ATHENA_RELEASE_FLAG;
  1681. WFIFOB(fd,6) = ATHENA_OFFICIAL_FLAG;
  1682. WFIFOB(fd,7) = ATHENA_SERVER_LOGIN;
  1683. WFIFOW(fd,8) = ATHENA_MOD_VERSION;
  1684. WFIFOSET(fd,10);
  1685. RFIFOSKIP(fd,2);
  1686. break;
  1687. case 0x7532: // Request of end of connection
  1688. login_log("'ladmin': End of connection (ip: %s)" RETCODE, ip);
  1689. RFIFOSKIP(fd,2);
  1690. session[fd]->eof = 1;
  1691. break;
  1692. case 0x7920: // Request of an accounts list
  1693. if (RFIFOREST(fd) < 10)
  1694. return 0;
  1695. {
  1696. int st, ed, len;
  1697. //int id[auth_num];
  1698. //int *id=(int *)aCalloc(auth_num, sizeof(int));
  1699. CREATE_BUFFER(id, int, auth_num);
  1700. st = RFIFOL(fd,2);
  1701. ed = RFIFOL(fd,6);
  1702. RFIFOSKIP(fd,10);
  1703. WFIFOW(fd,0) = 0x7921;
  1704. if (st < 0)
  1705. st = 0;
  1706. if (ed > END_ACCOUNT_NUM || ed < st || ed <= 0)
  1707. ed = END_ACCOUNT_NUM;
  1708. login_log("'ladmin': Sending an accounts list (ask: from %d to %d, ip: %s)" RETCODE, st, ed, ip);
  1709. // Sort before send
  1710. for(i = 0; i < auth_num; i++) {
  1711. int k;
  1712. id[i] = i;
  1713. for(j = 0; j < i; j++) {
  1714. if (auth_dat[id[i]].account_id < auth_dat[id[j]].account_id) {
  1715. for(k = i; k > j; k--) {
  1716. id[k] = id[k-1];
  1717. }
  1718. id[j] = i; // id[i]
  1719. break;
  1720. }
  1721. }
  1722. }
  1723. // Sending accounts information
  1724. len = 4;
  1725. for(i = 0; i < auth_num && len < 30000; i++) {
  1726. int account_id = auth_dat[id[i]].account_id; // use sorted index
  1727. if (account_id >= st && account_id <= ed) {
  1728. j = id[i];
  1729. WFIFOL(fd,len) = account_id;
  1730. WFIFOB(fd,len+4) = (unsigned char)isGM(account_id);
  1731. memcpy(WFIFOP(fd,len+5), auth_dat[j].userid, 24);
  1732. WFIFOB(fd,len+29) = auth_dat[j].sex;
  1733. WFIFOL(fd,len+30) = auth_dat[j].logincount;
  1734. if (auth_dat[j].state == 0 && auth_dat[j].ban_until_time != 0) // if no state and banished
  1735. WFIFOL(fd,len+34) = 7; // 6 = Your are Prohibited to log in until %s
  1736. else
  1737. WFIFOL(fd,len+34) = auth_dat[j].state;
  1738. len += 38;
  1739. }
  1740. }
  1741. WFIFOW(fd,2) = len;
  1742. WFIFOSET(fd,len);
  1743. //if (id) free(id);
  1744. DELETE_BUFFER(id);
  1745. }
  1746. break;
  1747. case 0x7930: // Request for an account creation
  1748. if (RFIFOREST(fd) < 91)
  1749. return 0;
  1750. {
  1751. struct mmo_account ma;
  1752. ma.userid = (char*)RFIFOP(fd, 2);
  1753. memcpy(ma.passwd, RFIFOP(fd, 26), 24);
  1754. ma.passwd[24] = '\0';
  1755. memcpy(ma.lastlogin, "-", 2);
  1756. ma.sex = RFIFOB(fd,50);
  1757. WFIFOW(fd,0) = 0x7931;
  1758. WFIFOL(fd,2) = -1; // WTF? usigned being set to a -1???
  1759. memcpy(WFIFOP(fd,6), RFIFOP(fd,2), 24);
  1760. if (strlen(ma.userid) > 23 || strlen(ma.passwd) > 23) {
  1761. login_log("'ladmin': Attempt to create an invalid account (account or pass is too long, ip: %s)" RETCODE,
  1762. ip);
  1763. } else if (strlen(ma.userid) < 4 || strlen(ma.passwd) < 4) {
  1764. login_log("'ladmin': Attempt to create an invalid account (account or pass is too short, ip: %s)" RETCODE,
  1765. ip);
  1766. } else if (ma.sex != 'F' && ma.sex != 'M') {
  1767. login_log("'ladmin': Attempt to create an invalid account (account: %s, received pass: %s, invalid sex, ip: %s)" RETCODE,
  1768. ma.userid, ma.passwd, ip);
  1769. } else if (account_id_count > END_ACCOUNT_NUM) {
  1770. login_log("'ladmin': Attempt to create an account, but there is no more available id number (account: %s, pass: %s, sex: %c, ip: %s)" RETCODE,
  1771. ma.userid, ma.passwd, ma.sex, ip);
  1772. } else {
  1773. remove_control_chars((unsigned char *)ma.userid);
  1774. remove_control_chars((unsigned char *)ma.passwd);
  1775. for(i = 0; i < auth_num; i++) {
  1776. if (strncmp(auth_dat[i].userid, ma.userid, 24) == 0) {
  1777. login_log("'ladmin': Attempt to create an already existing account (account: %s, pass: %s, received pass: %s, ip: %s)" RETCODE,
  1778. auth_dat[i].userid, auth_dat[i].pass, ma.passwd, ip);
  1779. break;
  1780. }
  1781. }
  1782. if (i == auth_num) {
  1783. int new_id;
  1784. char email[40];
  1785. memcpy(email, RFIFOP(fd,51), 40);
  1786. email[39] = '\0';
  1787. remove_control_chars((unsigned char *)email);
  1788. new_id = mmo_auth_new(&ma, ma.sex, email);
  1789. login_log("'ladmin': Account creation (account: %s (id: %d), pass: %s, sex: %c, email: %s, ip: %s)" RETCODE,
  1790. ma.userid, new_id, ma.passwd, ma.sex, auth_dat[i].email, ip);
  1791. WFIFOL(fd,2) = new_id;
  1792. mmo_auth_sync();
  1793. }
  1794. }
  1795. WFIFOSET(fd,30);
  1796. RFIFOSKIP(fd,91);
  1797. }
  1798. break;
  1799. case 0x7932: // Request for an account deletion
  1800. if (RFIFOREST(fd) < 26)
  1801. return 0;
  1802. WFIFOW(fd,0) = 0x7933;
  1803. WFIFOL(fd,2) = -1; // WTF? an unsigned being set to -1
  1804. account_name = (char*)RFIFOP(fd,2);
  1805. account_name[23] = '\0';
  1806. remove_control_chars((unsigned char *)account_name);
  1807. i = search_account_index(account_name);
  1808. if (i != -1) {
  1809. // Char-server is notified of deletion (for characters deletion).
  1810. unsigned char buf[65535];
  1811. WBUFW(buf,0) = 0x2730;
  1812. WBUFL(buf,2) = auth_dat[i].account_id;
  1813. charif_sendallwos(-1, buf, 6);
  1814. // send answer
  1815. memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
  1816. WFIFOL(fd,2) = auth_dat[i].account_id;
  1817. // save deleted account in log file
  1818. login_log("'ladmin': Account deletion (account: %s, id: %d, ip: %s) - saved in next line:" RETCODE,
  1819. auth_dat[i].userid, auth_dat[i].account_id, ip);
  1820. mmo_auth_tostr((char*)buf, &auth_dat[i]);
  1821. login_log("%s" RETCODE, buf);
  1822. // delete account
  1823. memset(auth_dat[i].userid, '\0', sizeof(auth_dat[i].userid));
  1824. auth_dat[i].account_id = -1;
  1825. mmo_auth_sync();
  1826. } else {
  1827. memcpy(WFIFOP(fd,6), account_name, 24);
  1828. login_log("'ladmin': Attempt to delete an unknown account (account: %s, ip: %s)" RETCODE,
  1829. account_name, ip);
  1830. }
  1831. WFIFOSET(fd,30);
  1832. RFIFOSKIP(fd,26);
  1833. break;
  1834. case 0x7934: // Request to change a password
  1835. if (RFIFOREST(fd) < 50)
  1836. return 0;
  1837. WFIFOW(fd,0) = 0x7935;
  1838. WFIFOL(fd,2) = -1; /// WTF??? an unsigned being set to a -1
  1839. account_name = (char*)RFIFOP(fd,2);
  1840. account_name[23] = '\0';
  1841. remove_control_chars((unsigned char *)account_name);
  1842. i = search_account_index(account_name);
  1843. if (i != -1) {
  1844. memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
  1845. memcpy(auth_dat[i].pass, RFIFOP(fd,26), 24);
  1846. auth_dat[i].pass[23] = '\0';
  1847. remove_control_chars((unsigned char *)auth_dat[i].pass);
  1848. WFIFOL(fd,2) = auth_dat[i].account_id;
  1849. login_log("'ladmin': Modification of a password (account: %s, new password: %s, ip: %s)" RETCODE,
  1850. auth_dat[i].userid, auth_dat[i].pass, ip);
  1851. mmo_auth_sync();
  1852. } else {
  1853. memcpy(WFIFOP(fd,6), account_name, 24);
  1854. login_log("'ladmin': Attempt to modify the password of an unknown account (account: %s, ip: %s)" RETCODE,
  1855. account_name, ip);
  1856. }
  1857. WFIFOSET(fd,30);
  1858. RFIFOSKIP(fd,50);
  1859. break;
  1860. case 0x7936: // Request to modify a state
  1861. if (RFIFOREST(fd) < 50)
  1862. return 0;
  1863. {
  1864. char error_message[20];
  1865. int statut;
  1866. WFIFOW(fd,0) = 0x7937;
  1867. WFIFOL(fd,2) = -1; // WTF???
  1868. account_name = (char*)RFIFOP(fd,2);
  1869. account_name[23] = '\0';
  1870. remove_control_chars((unsigned char *)account_name);
  1871. statut = RFIFOL(fd,26);
  1872. memcpy(error_message, RFIFOP(fd,30), 20);
  1873. error_message[19] = '\0';
  1874. remove_control_chars((unsigned char *)error_message);
  1875. if (statut != 7 || error_message[0] == '\0') { // 7: // 6 = Your are Prohibited to log in until %s
  1876. strcpy(error_message, "-");
  1877. }
  1878. i = search_account_index(account_name);
  1879. if (i != -1) {
  1880. memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
  1881. WFIFOL(fd,2) = auth_dat[i].account_id;
  1882. if (auth_dat[i].state == statut && strcmp(auth_dat[i].error_message, error_message) == 0)
  1883. login_log("'ladmin': Modification of a state, but the state of the account is already the good state (account: %s, received state: %d, ip: %s)" RETCODE,
  1884. account_name, statut, ip);
  1885. else {
  1886. if (statut == 7)
  1887. login_log("'ladmin': Modification of a state (account: %s, new state: %d - prohibited to login until '%s', ip: %s)" RETCODE,
  1888. auth_dat[i].userid, statut, error_message, ip);
  1889. else
  1890. login_log("'ladmin': Modification of a state (account: %s, new state: %d, ip: %s)" RETCODE,
  1891. auth_dat[i].userid, statut, ip);
  1892. if (auth_dat[i].state == 0) {
  1893. unsigned char buf[16];
  1894. WBUFW(buf,0) = 0x2731;
  1895. WBUFL(buf,2) = auth_dat[i].account_id;
  1896. WBUFB(buf,6) = 0; // 0: change of statut, 1: ban
  1897. WBUFL(buf,7) = statut; // status or final date of a banishment
  1898. charif_sendallwos(-1, buf, 11);
  1899. for(j = 0; j < AUTH_FIFO_SIZE; j++)
  1900. if (auth_fifo[j].account_id == auth_dat[i].account_id)
  1901. auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentification)
  1902. }
  1903. auth_dat[i].state = statut;
  1904. memcpy(auth_dat[i].error_message, error_message, 20);
  1905. mmo_auth_sync();
  1906. }
  1907. } else {
  1908. memcpy(WFIFOP(fd,6), account_name, 24);
  1909. login_log("'ladmin': Attempt to modify the state of an unknown account (account: %s, received state: %d, ip: %s)" RETCODE,
  1910. account_name, statut, ip);
  1911. }
  1912. WFIFOL(fd,30) = statut;
  1913. }
  1914. WFIFOSET(fd,34);
  1915. RFIFOSKIP(fd,50);
  1916. break;
  1917. case 0x7938: // Request for servers list and # of online players
  1918. login_log("'ladmin': Sending of servers list (ip: %s)" RETCODE, ip);
  1919. server_num = 0;
  1920. for(i = 0; i < MAX_SERVERS; i++) {
  1921. if (server_fd[i] >= 0) {
  1922. WFIFOL(fd,4+server_num*32) = server[i].ip;
  1923. WFIFOW(fd,4+server_num*32+4) = server[i].port;
  1924. memcpy(WFIFOP(fd,4+server_num*32+6), server[i].name, 20);
  1925. WFIFOW(fd,4+server_num*32+26) = server[i].users;
  1926. WFIFOW(fd,4+server_num*32+28) = server[i].maintenance;
  1927. WFIFOW(fd,4+server_num*32+30) = server[i].new_;
  1928. server_num++;
  1929. }
  1930. }
  1931. WFIFOW(fd,0) = 0x7939;
  1932. WFIFOW(fd,2) = 4 + 32 * server_num;
  1933. WFIFOSET(fd,4+32*server_num);
  1934. RFIFOSKIP(fd,2);
  1935. break;
  1936. case 0x793a: // Request to password check
  1937. if (RFIFOREST(fd) < 50)
  1938. return 0;
  1939. WFIFOW(fd,0) = 0x793b;
  1940. WFIFOL(fd,2) = -1; // WTF???
  1941. account_name = (char*)RFIFOP(fd,2);
  1942. account_name[23] = '\0';
  1943. remove_control_chars((unsigned char *)account_name);
  1944. i = search_account_index(account_name);
  1945. if (i != -1) {
  1946. char pass[25];
  1947. memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
  1948. memcpy(pass, RFIFOP(fd,26), 24);
  1949. pass[24] = '\0';
  1950. remove_control_chars((unsigned char *)pass);
  1951. if (strcmp(auth_dat[i].pass, pass) == 0) {
  1952. WFIFOL(fd,2) = auth_dat[i].account_id;
  1953. login_log("'ladmin': Check of password OK (account: %s, password: %s, ip: %s)" RETCODE,
  1954. auth_dat[i].userid, auth_dat[i].pass, ip);
  1955. } else {
  1956. login_log("'ladmin': Failure of password check (account: %s, proposed pass: %s, ip: %s)" RETCODE,
  1957. auth_dat[i].userid, pass, ip);
  1958. }
  1959. } else {
  1960. memcpy(WFIFOP(fd,6), account_name, 24);
  1961. login_log("'ladmin': Attempt to check the password of an unknown account (account: %s, ip: %s)" RETCODE,
  1962. account_name, ip);
  1963. }
  1964. WFIFOSET(fd,30);
  1965. RFIFOSKIP(fd,50);
  1966. break;
  1967. case 0x793c: // Request to modify sex
  1968. if (RFIFOREST(fd) < 27)
  1969. return 0;
  1970. WFIFOW(fd,0) = 0x793d;
  1971. WFIFOL(fd,2) = -1; // WTF???
  1972. account_name = (char*)RFIFOP(fd,2);
  1973. account_name[23] = '\0';
  1974. remove_control_chars((unsigned char *)account_name);
  1975. memcpy(WFIFOP(fd,6), account_name, 24);
  1976. {
  1977. char sex;
  1978. sex = RFIFOB(fd,26);
  1979. if (sex != 'F' && sex != 'M') {
  1980. if (sex > 31)
  1981. login_log("'ladmin': Attempt to give an invalid sex (account: %s, received sex: %c, ip: %s)" RETCODE,
  1982. account_name, sex, ip);
  1983. else
  1984. login_log("'ladmin': Attempt to give an invalid sex (account: %s, received sex: 'control char', ip: %s)" RETCODE,
  1985. account_name, ip);
  1986. } else {
  1987. i = search_account_index(account_name);
  1988. if (i != -1) {
  1989. memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
  1990. if (auth_dat[i].sex != ((sex == 'S' || sex == 's') ? 2 : (sex == 'M' || sex == 'm'))) {
  1991. unsigned char buf[16];
  1992. WFIFOL(fd,2) = auth_dat[i].account_id;
  1993. for(j = 0; j < AUTH_FIFO_SIZE; j++)
  1994. if (auth_fifo[j].account_id == auth_dat[i].account_id)
  1995. auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentification)
  1996. auth_dat[i].sex = (sex == 'S' || sex == 's') ? 2 : (sex == 'M' || sex == 'm');
  1997. login_log("'ladmin': Modification of a sex (account: %s, new sex: %c, ip: %s)" RETCODE,
  1998. auth_dat[i].userid, sex, ip);
  1999. mmo_auth_sync();
  2000. // send to all char-server the change
  2001. WBUFW(buf,0) = 0x2723;
  2002. WBUFL(buf,2) = auth_dat[i].account_id;
  2003. WBUFB(buf,6) = auth_dat[i].sex;
  2004. charif_sendallwos(-1, buf, 7);
  2005. } else {
  2006. login_log("'ladmin': Modification of a sex, but the sex is already the good sex (account: %s, sex: %c, ip: %s)" RETCODE,
  2007. auth_dat[i].userid, sex, ip);
  2008. }
  2009. } else {
  2010. login_log("'ladmin': Attempt to modify the sex of an unknown account (account: %s, received sex: %c, ip: %s)" RETCODE,
  2011. account_name, sex, ip);
  2012. }
  2013. }
  2014. }
  2015. WFIFOSET(fd,30);
  2016. RFIFOSKIP(fd,27);
  2017. break;
  2018. case 0x793e: // Request to modify GM level
  2019. if (RFIFOREST(fd) < 27)
  2020. return 0;
  2021. WFIFOW(fd,0) = 0x793f;
  2022. WFIFOL(fd,2) = -1; // WTF???
  2023. account_name = (char*)RFIFOP(fd,2);
  2024. account_name[23] = '\0';
  2025. remove_control_chars((unsigned char *)account_name);
  2026. memcpy(WFIFOP(fd,6), account_name, 24);
  2027. {
  2028. char new_gm_level;
  2029. new_gm_level = RFIFOB(fd,26);
  2030. if (new_gm_level < 0 || new_gm_level > 99) {
  2031. login_log("'ladmin': Attempt to give an invalid GM level (account: %s, received GM level: %d, ip: %s)" RETCODE,
  2032. account_name, (int)new_gm_level, ip);
  2033. } else {
  2034. i = search_account_index(account_name);
  2035. if (i != -1) {
  2036. int acc = auth_dat[i].account_id;
  2037. memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
  2038. if (isGM(acc) != new_gm_level) {
  2039. // modification of the file
  2040. FILE *fp, *fp2;
  2041. int lock;
  2042. char line[512];
  2043. int GM_account, GM_level;
  2044. int modify_flag;
  2045. char tmpstr[24];
  2046. struct timeval tv;
  2047. if ((fp2 = lock_fopen(GM_account_filename, &lock)) != NULL) {
  2048. if ((fp = fopen(GM_account_filename, "r")) != NULL) {
  2049. gettimeofday(&tv, NULL);
  2050. strftime(tmpstr, 23, date_format, localtime((const time_t*)&(tv.tv_sec)));
  2051. modify_flag = 0;
  2052. // read/write GM file
  2053. while(fgets(line, sizeof(line)-1, fp)) {
  2054. while(line[0] != '\0' && (line[strlen(line)-1] == '\n' || line[strlen(line)-1] == '\r'))
  2055. line[strlen(line)-1] = '\0';
  2056. if ((line[0] == '/' && line[1] == '/') || line[0] == '\0')
  2057. fprintf(fp2, "%s" RETCODE, line);
  2058. else {
  2059. if (sscanf(line, "%d %d", &GM_account, &GM_level) != 2 && sscanf(line, "%d: %d", &GM_account, &GM_level) != 2)
  2060. fprintf(fp2, "%s" RETCODE, line);
  2061. else if (GM_account != acc)
  2062. fprintf(fp2, "%s" RETCODE, line);
  2063. else if (new_gm_level < 1) {
  2064. fprintf(fp2, "// %s: 'ladmin' GM level removed on account %d '%s' (previous level: %d)" RETCODE "//%d %d" RETCODE, tmpstr, acc, auth_dat[i].userid, GM_level, acc, new_gm_level);
  2065. modify_flag = 1;
  2066. } else {
  2067. fprintf(fp2, "// %s: 'ladmin' GM level on account %d '%s' (previous level: %d)" RETCODE "%d %d" RETCODE, tmpstr, acc, auth_dat[i].userid, GM_level, acc, new_gm_level);
  2068. modify_flag = 1;
  2069. }
  2070. }
  2071. }
  2072. if (modify_flag == 0)
  2073. fprintf(fp2, "// %s: 'ladmin' GM level on account %d '%s' (previous level: 0)" RETCODE "%d %d" RETCODE, tmpstr, acc, auth_dat[i].userid, acc, new_gm_level);
  2074. fclose(fp);
  2075. } else {
  2076. login_log("'ladmin': Attempt to modify of a GM level - impossible to read GM accounts file (account: %s (%d), received GM level: %d, ip: %s)" RETCODE,
  2077. auth_dat[i].userid, acc, (int)new_gm_level, ip);
  2078. }
  2079. if (lock_fclose(fp2, GM_account_filename, &lock) == 0) {
  2080. WFIFOL(fd,2) = acc;
  2081. login_log("'ladmin': Modification of a GM level (account: %s (%d), new GM level: %d, ip: %s)" RETCODE,
  2082. auth_dat[i].userid, acc, (int)new_gm_level, ip);
  2083. // read and send new GM informations
  2084. read_gm_account();
  2085. send_GM_accounts();
  2086. } else {
  2087. login_log("'ladmin': Attempt to modify of a GM level - impossible to write GM accounts file (account: %s (%d), received GM level: %d, ip: %s)" RETCODE,
  2088. auth_dat[i].userid, acc, (int)new_gm_level, ip);
  2089. }
  2090. } else {
  2091. login_log("'ladmin': Attempt to modify of a GM level - impossible to write GM accounts file (account: %s (%d), received GM level: %d, ip: %s)" RETCODE,
  2092. auth_dat[i].userid, acc, (int)new_gm_level, ip);
  2093. }
  2094. } else {
  2095. login_log("'ladmin': Attempt to modify of a GM level, but the GM level is already the good GM level (account: %s (%d), GM level: %d, ip: %s)" RETCODE,
  2096. auth_dat[i].userid, acc, (int)new_gm_level, ip);
  2097. }
  2098. } else {
  2099. login_log("'ladmin': Attempt to modify the GM level of an unknown account (account: %s, received GM level: %d, ip: %s)" RETCODE,
  2100. account_name, (int)new_gm_level, ip);
  2101. }
  2102. }
  2103. }
  2104. WFIFOSET(fd,30);
  2105. RFIFOSKIP(fd,27);
  2106. break;
  2107. case 0x7940: // Request to modify e-mail
  2108. if (RFIFOREST(fd) < 66)
  2109. return 0;
  2110. WFIFOW(fd,0) = 0x7941;
  2111. WFIFOL(fd,2) = -1; // WTF???
  2112. account_name = (char*)RFIFOP(fd,2);
  2113. account_name[23] = '\0';
  2114. remove_control_chars((unsigned char *)account_name);
  2115. memcpy(WFIFOP(fd,6), account_name, 24);
  2116. {
  2117. char email[40];
  2118. memcpy(email, RFIFOP(fd,26), 40);
  2119. if (e_mail_check(email) == 0) {
  2120. login_log("'ladmin': Attempt to give an invalid e-mail (account: %s, ip: %s)" RETCODE,
  2121. account_name, ip);
  2122. } else {
  2123. remove_control_chars((unsigned char *)email);
  2124. i = search_account_index(account_name);
  2125. if (i != -1) {
  2126. memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
  2127. memcpy(auth_dat[i].email, email, 40);
  2128. WFIFOL(fd,2) = auth_dat[i].account_id;
  2129. login_log("'ladmin': Modification of an email (account: %s, new e-mail: %s, ip: %s)" RETCODE,
  2130. auth_dat[i].userid, email, ip);
  2131. mmo_auth_sync();
  2132. } else {
  2133. login_log("'ladmin': Attempt to modify the e-mail of an unknown account (account: %s, received e-mail: %s, ip: %s)" RETCODE,
  2134. account_name, email, ip);
  2135. }
  2136. }
  2137. }
  2138. WFIFOSET(fd,30);
  2139. RFIFOSKIP(fd,66);
  2140. break;
  2141. case 0x7942: // Request to modify memo field
  2142. if (RFIFOREST(fd) < 28 || RFIFOREST(fd) < (28 + RFIFOW(fd,26)))
  2143. return 0;
  2144. WFIFOW(fd,0) = 0x7943;
  2145. WFIFOL(fd,2) = -1; // WTF???
  2146. account_name = (char*)RFIFOP(fd,2);
  2147. account_name[23] = '\0';
  2148. remove_control_chars((unsigned char *)account_name);
  2149. i = search_account_index(account_name);
  2150. if (i != -1) {
  2151. int size_of_memo = sizeof(auth_dat[i].memo);
  2152. memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
  2153. memset(auth_dat[i].memo, '\0', size_of_memo);
  2154. if (RFIFOW(fd,26) == 0) {
  2155. strncpy(auth_dat[i].memo, "-", size_of_memo);
  2156. } else if (RFIFOW(fd,26) > size_of_memo - 1) {
  2157. memcpy(auth_dat[i].memo, RFIFOP(fd,28), size_of_memo - 1);
  2158. } else {
  2159. memcpy(auth_dat[i].memo, RFIFOP(fd,28), RFIFOW(fd,26));
  2160. }
  2161. auth_dat[i].memo[size_of_memo - 1] = '\0';
  2162. remove_control_chars((unsigned char *)auth_dat[i].memo);
  2163. WFIFOL(fd,2) = auth_dat[i].account_id;
  2164. login_log("'ladmin': Modification of a memo field (account: %s, new memo: %s, ip: %s)" RETCODE,
  2165. auth_dat[i].userid, auth_dat[i].memo, ip);
  2166. mmo_auth_sync();
  2167. } else {
  2168. memcpy(WFIFOP(fd,6), account_name, 24);
  2169. login_log("'ladmin': Attempt to modify the memo field of an unknown account (account: %s, ip: %s)" RETCODE,
  2170. account_name, ip);
  2171. }
  2172. WFIFOSET(fd,30);
  2173. RFIFOSKIP(fd,28 + RFIFOW(fd,26));
  2174. break;
  2175. case 0x7944: // Request to found an account id
  2176. if (RFIFOREST(fd) < 26)
  2177. return 0;
  2178. WFIFOW(fd,0) = 0x7945;
  2179. WFIFOL(fd,2) = -1; // WTF???
  2180. account_name = (char*)RFIFOP(fd,2);
  2181. account_name[23] = '\0';
  2182. remove_control_chars((unsigned char *)account_name);
  2183. i = search_account_index(account_name);
  2184. if (i != -1) {
  2185. memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
  2186. WFIFOL(fd,2) = auth_dat[i].account_id;
  2187. login_log("'ladmin': Request (by the name) of an account id (account: %s, id: %d, ip: %s)" RETCODE,
  2188. auth_dat[i].userid, auth_dat[i].account_id, ip);
  2189. } else {
  2190. memcpy(WFIFOP(fd,6), account_name, 24);
  2191. login_log("'ladmin': ID request (by the name) of an unknown account (account: %s, ip: %s)" RETCODE,
  2192. account_name, ip);
  2193. }
  2194. WFIFOSET(fd,30);
  2195. RFIFOSKIP(fd,26);
  2196. break;
  2197. case 0x7946: // Request to found an account name
  2198. if (RFIFOREST(fd) < 6)
  2199. return 0;
  2200. WFIFOW(fd,0) = 0x7947;
  2201. WFIFOL(fd,2) = RFIFOL(fd,2);
  2202. memset(WFIFOP(fd,6), '\0', 24);
  2203. for(i = 0; i < auth_num; i++) {
  2204. if (auth_dat[i].account_id == RFIFOL(fd,2)) {
  2205. strncpy((char*)WFIFOP(fd,6), auth_dat[i].userid, 24);
  2206. login_log("'ladmin': Request (by id) of an account name (account: %s, id: %d, ip: %s)" RETCODE,
  2207. auth_dat[i].userid, RFIFOL(fd,2), ip);
  2208. break;
  2209. }
  2210. }
  2211. if (i == auth_num) {
  2212. login_log("'ladmin': Name request (by id) of an unknown account (id: %d, ip: %s)" RETCODE,
  2213. RFIFOL(fd,2), ip);
  2214. strncpy((char*)WFIFOP(fd,6), "", 24);
  2215. }
  2216. WFIFOSET(fd,30);
  2217. RFIFOSKIP(fd,6);
  2218. break;
  2219. case 0x7948: // Request to change the validity limit (timestamp) (absolute value)
  2220. if (RFIFOREST(fd) < 30)
  2221. return 0;
  2222. {
  2223. time_t timestamp;
  2224. char tmpstr[2048];
  2225. WFIFOW(fd,0) = 0x7949;
  2226. WFIFOL(fd,2) = -1; // WTF???
  2227. account_name = (char*)RFIFOP(fd,2);
  2228. account_name[23] = '\0';
  2229. remove_control_chars((unsigned char *)account_name);
  2230. timestamp = (time_t)RFIFOL(fd,26);
  2231. strftime(tmpstr, 24, date_format, localtime(&timestamp));
  2232. i = search_account_index(account_name);
  2233. if (i != -1) {
  2234. memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
  2235. login_log("'ladmin': Change of a validity limit (account: %s, new validity: %d (%s), ip: %s)" RETCODE,
  2236. auth_dat[i].userid, timestamp, (timestamp == 0 ? "unlimited" : tmpstr), ip);
  2237. auth_dat[i].connect_until_time = timestamp;
  2238. WFIFOL(fd,2) = auth_dat[i].account_id;
  2239. mmo_auth_sync();
  2240. } else {
  2241. memcpy(WFIFOP(fd,6), account_name, 24);
  2242. login_log("'ladmin': Attempt to change the validity limit of an unknown account (account: %s, received validity: %d (%s), ip: %s)" RETCODE,
  2243. account_name, timestamp, (timestamp == 0 ? "unlimited" : tmpstr), ip);
  2244. }
  2245. WFIFOL(fd,30) = timestamp;
  2246. }
  2247. WFIFOSET(fd,34);
  2248. RFIFOSKIP(fd,30);
  2249. break;
  2250. case 0x794a: // Request to change the final date of a banishment (timestamp) (absolute value)
  2251. if (RFIFOREST(fd) < 30)
  2252. return 0;
  2253. {
  2254. time_t timestamp;
  2255. char tmpstr[2048];
  2256. WFIFOW(fd,0) = 0x794b;
  2257. WFIFOL(fd,2) = -1; // WTF???
  2258. account_name = (char*)RFIFOP(fd,2);
  2259. account_name[23] = '\0';
  2260. remove_control_chars((unsigned char *)account_name);
  2261. timestamp = (time_t)RFIFOL(fd,26);
  2262. if (timestamp <= time(NULL))
  2263. timestamp = 0;
  2264. strftime(tmpstr, 24, date_format, localtime(&timestamp));
  2265. i = search_account_index(account_name);
  2266. if (i != -1) {
  2267. memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
  2268. WFIFOL(fd,2) = auth_dat[i].account_id;
  2269. login_log("'ladmin': Change of the final date of a banishment (account: %s, new final date of banishment: %d (%s), ip: %s)" RETCODE,
  2270. auth_dat[i].userid, timestamp, (timestamp == 0 ? "no banishment" : tmpstr), ip);
  2271. if (auth_dat[i].ban_until_time != timestamp) {
  2272. if (timestamp != 0) {
  2273. unsigned char buf[16];
  2274. WBUFW(buf,0) = 0x2731;
  2275. WBUFL(buf,2) = auth_dat[i].account_id;
  2276. WBUFB(buf,6) = 1; // 0: change of statut, 1: ban
  2277. WBUFL(buf,7) = timestamp; // status or final date of a banishment
  2278. charif_sendallwos(-1, buf, 11);
  2279. for(j = 0; j < AUTH_FIFO_SIZE; j++)
  2280. if (auth_fifo[j].account_id == auth_dat[i].account_id)
  2281. auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentification)
  2282. }
  2283. auth_dat[i].ban_until_time = timestamp;
  2284. mmo_auth_sync();
  2285. }
  2286. } else {
  2287. memcpy(WFIFOP(fd,6), account_name, 24);
  2288. login_log("'ladmin': Attempt to change the final date of a banishment of an unknown account (account: %s, received final date of banishment: %d (%s), ip: %s)" RETCODE,
  2289. account_name, timestamp, (timestamp == 0 ? "no banishment" : tmpstr), ip);
  2290. }
  2291. WFIFOL(fd,30) = timestamp;
  2292. }
  2293. WFIFOSET(fd,34);
  2294. RFIFOSKIP(fd,30);
  2295. break;
  2296. case 0x794c: // Request to change the final date of a banishment (timestamp) (relative change)
  2297. if (RFIFOREST(fd) < 38)
  2298. return 0;
  2299. {
  2300. time_t timestamp;
  2301. struct tm *tmtime;
  2302. char tmpstr[2048];
  2303. WFIFOW(fd,0) = 0x794d;
  2304. WFIFOL(fd,2) = -1; // WTF???
  2305. account_name = (char*)RFIFOP(fd,2);
  2306. account_name[23] = '\0';
  2307. remove_control_chars((unsigned char *)account_name);
  2308. i = search_account_index(account_name);
  2309. if (i != -1) {
  2310. WFIFOL(fd,2) = auth_dat[i].account_id;
  2311. memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
  2312. if (auth_dat[i].ban_until_time == 0 || auth_dat[i].ban_until_time < time(NULL))
  2313. timestamp = time(NULL);
  2314. else
  2315. timestamp = auth_dat[i].ban_until_time;
  2316. tmtime = localtime(&timestamp);
  2317. tmtime->tm_year = tmtime->tm_year + (short)RFIFOW(fd,26);
  2318. tmtime->tm_mon = tmtime->tm_mon + (short)RFIFOW(fd,28);
  2319. tmtime->tm_mday = tmtime->tm_mday + (short)RFIFOW(fd,30);
  2320. tmtime->tm_hour = tmtime->tm_hour + (short)RFIFOW(fd,32);
  2321. tmtime->tm_min = tmtime->tm_min + (short)RFIFOW(fd,34);
  2322. tmtime->tm_sec = tmtime->tm_sec + (short)RFIFOW(fd,36);
  2323. timestamp = mktime(tmtime);
  2324. if (timestamp != -1) {
  2325. if (timestamp <= time(NULL))
  2326. timestamp = 0;
  2327. strftime(tmpstr, 24, date_format, localtime(&timestamp));
  2328. login_log("'ladmin': Adjustment of a final date of a banishment (account: %s, (%+d y %+d m %+d d %+d h %+d mn %+d s) -> new validity: %d (%s), ip: %s)" RETCODE,
  2329. auth_dat[i].userid, (short)RFIFOW(fd,26), (short)RFIFOW(fd,28), (short)RFIFOW(fd,30), (short)RFIFOW(fd,32), (short)RFIFOW(fd,34), (short)RFIFOW(fd,36), timestamp, (timestamp == 0 ? "no banishment" : tmpstr), ip);
  2330. if (auth_dat[i].ban_until_time != timestamp) {
  2331. if (timestamp != 0) {
  2332. unsigned char buf[16];
  2333. WBUFW(buf,0) = 0x2731;
  2334. WBUFL(buf,2) = auth_dat[i].account_id;
  2335. WBUFB(buf,6) = 1; // 0: change of statut, 1: ban
  2336. WBUFL(buf,7) = timestamp; // status or final date of a banishment
  2337. charif_sendallwos(-1, buf, 11);
  2338. for(j = 0; j < AUTH_FIFO_SIZE; j++)
  2339. if (auth_fifo[j].account_id == auth_dat[i].account_id)
  2340. auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentification)
  2341. }
  2342. auth_dat[i].ban_until_time = timestamp;
  2343. mmo_auth_sync();
  2344. }
  2345. } else {
  2346. strftime(tmpstr, 24, date_format, localtime(&auth_dat[i].ban_until_time));
  2347. login_log("'ladmin': Impossible to adjust the final date of a banishment (account: %s, %d (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> ???, ip: %s)" RETCODE,
  2348. auth_dat[i].userid, auth_dat[i].ban_until_time, (auth_dat[i].ban_until_time == 0 ? "no banishment" : tmpstr), (short)RFIFOW(fd,26), (short)RFIFOW(fd,28), (short)RFIFOW(fd,30), (short)RFIFOW(fd,32), (short)RFIFOW(fd,34), (short)RFIFOW(fd,36), ip);
  2349. }
  2350. WFIFOL(fd,30) = (unsigned long)auth_dat[i].ban_until_time;
  2351. } else {
  2352. memcpy(WFIFOP(fd,6), account_name, 24);
  2353. login_log("'ladmin': Attempt to adjust the final date of a banishment of an unknown account (account: %s, ip: %s)" RETCODE,
  2354. account_name, ip);
  2355. WFIFOL(fd,30) = 0;
  2356. }
  2357. }
  2358. WFIFOSET(fd,34);
  2359. RFIFOSKIP(fd,38);
  2360. break;
  2361. case 0x794e: // Request to send a broadcast message
  2362. if (RFIFOREST(fd) < 8 || RFIFOREST(fd) < (8 + RFIFOL(fd,4)))
  2363. return 0;
  2364. WFIFOW(fd,0) = 0x794f;
  2365. WFIFOW(fd,2) = -1; // WTF???
  2366. if (RFIFOL(fd,4) < 1) {
  2367. login_log("'ladmin': Receiving a message for broadcast, but message is void (ip: %s)" RETCODE,
  2368. ip);
  2369. } else {
  2370. // at least 1 char-server
  2371. for(i = 0; i < MAX_SERVERS; i++)
  2372. if (server_fd[i] >= 0)
  2373. break;
  2374. if (i == MAX_SERVERS) {
  2375. login_log("'ladmin': Receiving a message for broadcast, but no char-server is online (ip: %s)" RETCODE,
  2376. ip);
  2377. } else {
  2378. unsigned char buf[32000];
  2379. char message[32000];
  2380. WFIFOW(fd,2) = 0;
  2381. memset(message, '\0', sizeof(message));
  2382. memcpy(message, RFIFOP(fd,8), RFIFOL(fd,4));
  2383. message[sizeof(message)-1] = '\0';
  2384. remove_control_chars((unsigned char *)message);
  2385. if (RFIFOW(fd,2) == 0)
  2386. login_log("'ladmin': Receiving a message for broadcast (message (in yellow): %s, ip: %s)" RETCODE,
  2387. message, ip);
  2388. else
  2389. login_log("'ladmin': Receiving a message for broadcast (message (in blue): %s, ip: %s)" RETCODE,
  2390. message, ip);
  2391. // send same message to all char-servers (no answer)
  2392. memcpy(WBUFP(buf,0), RFIFOP(fd,0), 8 + RFIFOL(fd,4));
  2393. WBUFW(buf,0) = 0x2726;
  2394. charif_sendallwos(-1, buf, 8 + RFIFOL(fd,4));
  2395. }
  2396. }
  2397. WFIFOSET(fd,4);
  2398. RFIFOSKIP(fd,8 + RFIFOL(fd,4));
  2399. break;
  2400. case 0x7950: // Request to change the validity limite (timestamp) (relative change)
  2401. if (RFIFOREST(fd) < 38)
  2402. return 0;
  2403. {
  2404. time_t timestamp;
  2405. struct tm *tmtime;
  2406. char tmpstr[2048];
  2407. char tmpstr2[2048];
  2408. WFIFOW(fd,0) = 0x7951;
  2409. WFIFOL(fd,2) = -1; // WTF???
  2410. account_name = (char*)RFIFOP(fd,2);
  2411. account_name[23] = '\0';
  2412. remove_control_chars((unsigned char *)account_name);
  2413. i = search_account_index(account_name);
  2414. if (i != -1) {
  2415. WFIFOL(fd,2) = auth_dat[i].account_id;
  2416. memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
  2417. timestamp = auth_dat[i].connect_until_time;
  2418. if (add_to_unlimited_account == 0 && timestamp == 0) {
  2419. login_log("'ladmin': Attempt to adjust the validity limit of an unlimited account (account: %s, ip: %s)" RETCODE,
  2420. auth_dat[i].userid, ip);
  2421. WFIFOL(fd,30) = 0;
  2422. } else {
  2423. if (timestamp == 0 || timestamp < time(NULL))
  2424. timestamp = time(NULL);
  2425. tmtime = localtime(&timestamp);
  2426. tmtime->tm_year = tmtime->tm_year + (short)RFIFOW(fd,26);
  2427. tmtime->tm_mon = tmtime->tm_mon + (short)RFIFOW(fd,28);
  2428. tmtime->tm_mday = tmtime->tm_mday + (short)RFIFOW(fd,30);
  2429. tmtime->tm_hour = tmtime->tm_hour + (short)RFIFOW(fd,32);
  2430. tmtime->tm_min = tmtime->tm_min + (short)RFIFOW(fd,34);
  2431. tmtime->tm_sec = tmtime->tm_sec + (short)RFIFOW(fd,36);
  2432. timestamp = mktime(tmtime);
  2433. if (timestamp != -1) {
  2434. strftime(tmpstr, 24, date_format, localtime(&auth_dat[i].connect_until_time));
  2435. strftime(tmpstr2, 24, date_format, localtime(&timestamp));
  2436. login_log("'ladmin': Adjustment of a validity limit (account: %s, %d (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> new validity: %d (%s), ip: %s)" RETCODE,
  2437. auth_dat[i].userid, auth_dat[i].connect_until_time, (auth_dat[i].connect_until_time == 0 ? "unlimited" : tmpstr), (short)RFIFOW(fd,26), (short)RFIFOW(fd,28), (short)RFIFOW(fd,30), (short)RFIFOW(fd,32), (short)RFIFOW(fd,34), (short)RFIFOW(fd,36), timestamp, (timestamp == 0 ? "unlimited" : tmpstr2), ip);
  2438. auth_dat[i].connect_until_time = timestamp;
  2439. mmo_auth_sync();
  2440. WFIFOL(fd,30) = (unsigned long)auth_dat[i].connect_until_time;
  2441. } else {
  2442. strftime(tmpstr, 24, date_format, localtime(&auth_dat[i].connect_until_time));
  2443. login_log("'ladmin': Impossible to adjust a validity limit (account: %s, %d (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> ???, ip: %s)" RETCODE,
  2444. auth_dat[i].userid, auth_dat[i].connect_until_time, (auth_dat[i].connect_until_time == 0 ? "unlimited" : tmpstr), (short)RFIFOW(fd,26), (short)RFIFOW(fd,28), (short)RFIFOW(fd,30), (short)RFIFOW(fd,32), (short)RFIFOW(fd,34), (short)RFIFOW(fd,36), ip);
  2445. WFIFOL(fd,30) = 0;
  2446. }
  2447. }
  2448. } else {
  2449. memcpy(WFIFOP(fd,6), account_name, 24);
  2450. login_log("'ladmin': Attempt to adjust the validity limit of an unknown account (account: %s, ip: %s)" RETCODE,
  2451. account_name, ip);
  2452. WFIFOL(fd,30) = 0;
  2453. }
  2454. }
  2455. WFIFOSET(fd,34);
  2456. RFIFOSKIP(fd,38);
  2457. break;
  2458. case 0x7952: // Request about informations of an account (by account name)
  2459. if (RFIFOREST(fd) < 26)
  2460. return 0;
  2461. WFIFOW(fd,0) = 0x7953;
  2462. WFIFOL(fd,2) = -1; // WTF???
  2463. account_name = (char*)RFIFOP(fd,2);
  2464. account_name[23] = '\0';
  2465. remove_control_chars((unsigned char *)account_name);
  2466. i = search_account_index(account_name);
  2467. if (i != -1) {
  2468. WFIFOL(fd,2) = auth_dat[i].account_id;
  2469. WFIFOB(fd,6) = (unsigned char)isGM(auth_dat[i].account_id);
  2470. memcpy(WFIFOP(fd,7), auth_dat[i].userid, 24);
  2471. WFIFOB(fd,31) = auth_dat[i].sex;
  2472. WFIFOL(fd,32) = auth_dat[i].logincount;
  2473. WFIFOL(fd,36) = auth_dat[i].state;
  2474. memcpy(WFIFOP(fd,40), auth_dat[i].error_message, 20);
  2475. memcpy(WFIFOP(fd,60), auth_dat[i].lastlogin, 24);
  2476. memcpy(WFIFOP(fd,84), auth_dat[i].last_ip, 16);
  2477. memcpy(WFIFOP(fd,100), auth_dat[i].email, 40);
  2478. WFIFOL(fd,140) = (unsigned long)auth_dat[i].connect_until_time;
  2479. WFIFOL(fd,144) = (unsigned long)auth_dat[i].ban_until_time;
  2480. WFIFOW(fd,148) = strlen(auth_dat[i].memo);
  2481. if (auth_dat[i].memo[0]) {
  2482. memcpy(WFIFOP(fd,150), auth_dat[i].memo, strlen(auth_dat[i].memo));
  2483. }
  2484. login_log("'ladmin': Sending information of an account (request by the name; account: %s, id: %d, ip: %s)" RETCODE,
  2485. auth_dat[i].userid, auth_dat[i].account_id, ip);
  2486. WFIFOSET(fd,150+strlen(auth_dat[i].memo));
  2487. } else {
  2488. memcpy(WFIFOP(fd,7), account_name, 24);
  2489. WFIFOW(fd,148) = 0;
  2490. login_log("'ladmin': Attempt to obtain information (by the name) of an unknown account (account: %s, ip: %s)" RETCODE,
  2491. account_name, ip);
  2492. WFIFOSET(fd,150);
  2493. }
  2494. RFIFOSKIP(fd,26);
  2495. break;
  2496. case 0x7954: // Request about information of an account (by account id)
  2497. if (RFIFOREST(fd) < 6)
  2498. return 0;
  2499. WFIFOW(fd,0) = 0x7953;
  2500. WFIFOL(fd,2) = RFIFOL(fd,2);
  2501. memset(WFIFOP(fd,7), '\0', 24);
  2502. for(i = 0; i < auth_num; i++) {
  2503. if (auth_dat[i].account_id == RFIFOL(fd,2)) {
  2504. login_log("'ladmin': Sending information of an account (request by the id; account: %s, id: %d, ip: %s)" RETCODE,
  2505. auth_dat[i].userid, RFIFOL(fd,2), ip);
  2506. WFIFOB(fd,6) = (unsigned char)isGM(auth_dat[i].account_id);
  2507. memcpy(WFIFOP(fd,7), auth_dat[i].userid, 24);
  2508. WFIFOB(fd,31) = auth_dat[i].sex;
  2509. WFIFOL(fd,32) = auth_dat[i].logincount;
  2510. WFIFOL(fd,36) = auth_dat[i].state;
  2511. memcpy(WFIFOP(fd,40), auth_dat[i].error_message, 20);
  2512. memcpy(WFIFOP(fd,60), auth_dat[i].lastlogin, 24);
  2513. memcpy(WFIFOP(fd,84), auth_dat[i].last_ip, 16);
  2514. memcpy(WFIFOP(fd,100), auth_dat[i].email, 40);
  2515. WFIFOL(fd,140) = (unsigned long)auth_dat[i].connect_until_time;
  2516. WFIFOL(fd,144) = (unsigned long)auth_dat[i].ban_until_time;
  2517. WFIFOW(fd,148) = strlen(auth_dat[i].memo);
  2518. if (auth_dat[i].memo[0]) {
  2519. memcpy(WFIFOP(fd,150), auth_dat[i].memo, strlen(auth_dat[i].memo));
  2520. }
  2521. WFIFOSET(fd,150+strlen(auth_dat[i].memo));
  2522. break;
  2523. }
  2524. }
  2525. if (i == auth_num) {
  2526. login_log("'ladmin': Attempt to obtain information (by the id) of an unknown account (id: %d, ip: %s)" RETCODE,
  2527. RFIFOL(fd,2), ip);
  2528. strncpy((char*)WFIFOP(fd,7), "", 24);
  2529. WFIFOW(fd,148) = 0;
  2530. WFIFOSET(fd,150);
  2531. }
  2532. RFIFOSKIP(fd,6);
  2533. break;
  2534. case 0x7955: // Request to reload GM file (no answer)
  2535. login_log("'ladmin': Request to re-load GM configuration file (ip: %s)." RETCODE, ip);
  2536. read_gm_account();
  2537. // send GM accounts to all char-servers
  2538. send_GM_accounts();
  2539. RFIFOSKIP(fd,2);
  2540. break;
  2541. default:
  2542. {
  2543. FILE *logfp;
  2544. char tmpstr[24];
  2545. struct timeval tv;
  2546. logfp = fopen(login_log_unknown_packets_filename, "a");
  2547. if (logfp) {
  2548. gettimeofday(&tv, NULL);
  2549. strftime(tmpstr, 23, date_format, localtime((const time_t*)&(tv.tv_sec)));
  2550. fprintf(logfp, "%s.%03d: receiving of an unknown packet -> disconnection" RETCODE, tmpstr, (int)tv.tv_usec / 1000);
  2551. fprintf(logfp, "parse_admin: connection #%d (ip: %s), packet: 0x%x (with being read: %d)." RETCODE, fd, ip, RFIFOW(fd,0), RFIFOREST(fd));
  2552. fprintf(logfp, "Detail (in hex):" RETCODE);
  2553. fprintf(logfp, "---- 00-01-02-03-04-05-06-07 08-09-0A-0B-0C-0D-0E-0F" RETCODE);
  2554. memset(tmpstr, '\0', sizeof(tmpstr));
  2555. for(i = 0; i < RFIFOREST(fd); i++) {
  2556. if ((i & 15) == 0)
  2557. fprintf(logfp, "%04X ",i);
  2558. fprintf(logfp, "%02x ", RFIFOB(fd,i));
  2559. if (RFIFOB(fd,i) > 0x1f)
  2560. tmpstr[i % 16] = RFIFOB(fd,i);
  2561. else
  2562. tmpstr[i % 16] = '.';
  2563. if ((i - 7) % 16 == 0) // -8 + 1
  2564. fprintf(logfp, " ");
  2565. else if ((i + 1) % 16 == 0) {
  2566. fprintf(logfp, " %s" RETCODE, tmpstr);
  2567. memset(tmpstr, '\0', sizeof(tmpstr));
  2568. }
  2569. }
  2570. if (i % 16 != 0) {
  2571. for(j = i; j % 16 != 0; j++) {
  2572. fprintf(logfp, " ");
  2573. if ((j - 7) % 16 == 0) // -8 + 1
  2574. fprintf(logfp, " ");
  2575. }
  2576. fprintf(logfp, " %s" RETCODE, tmpstr);
  2577. }
  2578. fprintf(logfp, RETCODE);
  2579. fclose(logfp);
  2580. }
  2581. }
  2582. login_log("'ladmin': End of connection, unknown packet (ip: %s)" RETCODE, ip);
  2583. session[fd]->eof = 1;
  2584. printf("Remote administration has been disconnected (unknown packet).\n");
  2585. return 0;
  2586. }
  2587. //WFIFOW(fd,0) = 0x791f;
  2588. //WFIFOSET(fd,2);
  2589. }
  2590. return 0;
  2591. }
  2592. //--------------------------------------------
  2593. // Test to know if an IP come from LAN or WAN.
  2594. //--------------------------------------------
  2595. int lan_ip_check(unsigned char *p) {
  2596. int i;
  2597. int lancheck = 1;
  2598. // printf("lan_ip_check: to compare: %d.%d.%d.%d, network: %d.%d.%d.%d/%d.%d.%d.%d\n",
  2599. // p[0], p[1], p[2], p[3],
  2600. // subneti[0], subneti[1], subneti[2], subneti[3],
  2601. // subnetmaski[0], subnetmaski[1], subnetmaski[2], subnetmaski[3]);
  2602. for(i = 0; i < 4; i++) {
  2603. if ((subneti[i] & subnetmaski[i]) != (p[i] & subnetmaski[i])) {
  2604. lancheck = 0;
  2605. break;
  2606. }
  2607. }
  2608. printf("LAN test (result): %s source\033[0m.\n", (lancheck) ? "\033[1;36mLAN" : "\033[1;32mWAN");
  2609. return lancheck;
  2610. }
  2611. //----------------------------------------------------------------------------------------
  2612. // Default packet parsing (normal players or administation/char-server connexion requests)
  2613. //----------------------------------------------------------------------------------------
  2614. int parse_login(int fd) {
  2615. struct mmo_account account;
  2616. int result, i, j;
  2617. unsigned char *p = (unsigned char *) &session[fd]->client_addr.sin_addr;
  2618. char ip[16];
  2619. sprintf(ip, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
  2620. memset(&account, 0, sizeof(account));
  2621. if (session[fd]->eof) {
  2622. close(fd);
  2623. delete_session(fd);
  2624. return 0;
  2625. }
  2626. while(RFIFOREST(fd) >= 2) {
  2627. if (display_parse_login == 1) {
  2628. if (RFIFOW(fd,0) == 0x64 || RFIFOW(fd,0) == 0x01dd) {
  2629. if (RFIFOREST(fd) >= ((RFIFOW(fd,0) == 0x64) ? 55 : 47))
  2630. printf("parse_login: connection #%d, packet: 0x%x (with being read: %d), account: %s.\n", fd, RFIFOW(fd,0), RFIFOREST(fd), RFIFOP(fd,6));
  2631. } else if (RFIFOW(fd,0) == 0x2710) {
  2632. if (RFIFOREST(fd) >= 86)
  2633. printf("parse_login: connection #%d, packet: 0x%x (with being read: %d), server: %s.\n", fd, RFIFOW(fd,0), RFIFOREST(fd), RFIFOP(fd,60));
  2634. } else
  2635. printf("parse_login: connection #%d, packet: 0x%x (with being read: %d).\n", fd, RFIFOW(fd,0), RFIFOREST(fd));
  2636. }
  2637. switch(RFIFOW(fd,0)) {
  2638. case 0x200: // New alive packet: structure: 0x200 <account.userid>.24B. used to verify if client is always alive.
  2639. if (RFIFOREST(fd) < 26)
  2640. return 0;
  2641. RFIFOSKIP(fd,26);
  2642. break;
  2643. case 0x204: // New alive packet: structure: 0x204 <encrypted.account.userid>.16B. (new ragexe from 22 june 2004)
  2644. if (RFIFOREST(fd) < 18)
  2645. return 0;
  2646. RFIFOSKIP(fd,18);
  2647. break;
  2648. case 0x64: // Ask connection of a client
  2649. case 0x01dd: // Ask connection of a client (encryption mode)
  2650. if (RFIFOREST(fd) < ((RFIFOW(fd,0) == 0x64) ? 55 : 47))
  2651. return 0;
  2652. account.version = RFIFOL(fd, 2); //for exe version check [Sirius]
  2653. account.userid = (char*)RFIFOP(fd,6);
  2654. account.userid[23] = '\0';
  2655. remove_control_chars((unsigned char *)account.userid);
  2656. if (RFIFOW(fd,0) == 0x64) {
  2657. memcpy(account.passwd, RFIFOP(fd,30), 24);
  2658. account.passwd[24] = '\0';
  2659. } else {
  2660. memcpy(account.passwd, RFIFOP(fd,30), 32);
  2661. account.passwd[32] = '\0';
  2662. }
  2663. remove_control_chars((unsigned char *)account.passwd);
  2664. #ifdef PASSWORDENC
  2665. account.passwdenc = (RFIFOW(fd,0) == 0x64) ? 0 : PASSWORDENC;
  2666. #else
  2667. account.passwdenc = 0;
  2668. #endif
  2669. if (RFIFOW(fd,0) == 0x64)
  2670. login_log("Request for connection (non encryption mode) of %s (ip: %s)." RETCODE, account.userid, ip);
  2671. else
  2672. login_log("Request for connection (encryption mode) of %s (ip: %s)." RETCODE, account.userid, ip);
  2673. if (!check_ip(session[fd]->client_addr.sin_addr.s_addr)) {
  2674. login_log("Connection refused: IP isn't authorised (deny/allow, ip: %s)." RETCODE, ip);
  2675. WFIFOW(fd,0) = 0x6a;
  2676. WFIFOB(fd,2) = 3; // 3 = Rejected from Server
  2677. WFIFOSET(fd,23);
  2678. RFIFOSKIP(fd,(RFIFOW(fd,0) == 0x64) ? 55 : 47);
  2679. break;
  2680. }
  2681. result = mmo_auth(&account, fd);
  2682. if (result == -1) {
  2683. int gm_level = isGM(account.account_id);
  2684. if (min_level_to_connect > gm_level) {
  2685. login_log("Connection refused: the minimum GM level for connection is %d (account: %s, GM level: %d, ip: %s)." RETCODE,
  2686. min_level_to_connect, account.userid, gm_level, ip);
  2687. WFIFOW(fd,0) = 0x81;
  2688. WFIFOL(fd,2) = 1; // 01 = Server closed
  2689. WFIFOSET(fd,3);
  2690. } else {
  2691. if (gm_level)
  2692. printf("Connection of the GM (level:%d) account '%s' accepted.\n", gm_level, account.userid);
  2693. else
  2694. printf("Connection of the account '%s' accepted.\n", account.userid);
  2695. server_num = 0;
  2696. for(i = 0; i < MAX_SERVERS; i++) {
  2697. if (server_fd[i] >= 0) {
  2698. if (lan_ip_check(p))
  2699. WFIFOL(fd,47+server_num*32) = inet_addr(lan_char_ip);
  2700. else
  2701. WFIFOL(fd,47+server_num*32) = server[i].ip;
  2702. WFIFOW(fd,47+server_num*32+4) = server[i].port;
  2703. memcpy(WFIFOP(fd,47+server_num*32+6), server[i].name, 20);
  2704. WFIFOW(fd,47+server_num*32+26) = server[i].users;
  2705. WFIFOW(fd,47+server_num*32+28) = server[i].maintenance;
  2706. WFIFOW(fd,47+server_num*32+30) = server[i].new_;
  2707. server_num++;
  2708. }
  2709. }
  2710. // if at least 1 char-server
  2711. if (server_num > 0) {
  2712. WFIFOW(fd,0) = 0x69;
  2713. WFIFOW(fd,2) = 47+32*server_num;
  2714. WFIFOL(fd,4) = account.login_id1;
  2715. WFIFOL(fd,8) = account.account_id;
  2716. WFIFOL(fd,12) = account.login_id2;
  2717. WFIFOL(fd,16) = 0; // in old version, that was for ip (not more used)
  2718. memcpy(WFIFOP(fd,20), account.lastlogin, 24); // in old version, that was for name (not more used)
  2719. WFIFOB(fd,46) = account.sex;
  2720. WFIFOSET(fd,47+32*server_num);
  2721. if (auth_fifo_pos >= AUTH_FIFO_SIZE)
  2722. auth_fifo_pos = 0;
  2723. auth_fifo[auth_fifo_pos].account_id = account.account_id;
  2724. auth_fifo[auth_fifo_pos].login_id1 = account.login_id1;
  2725. auth_fifo[auth_fifo_pos].login_id2 = account.login_id2;
  2726. auth_fifo[auth_fifo_pos].sex = account.sex;
  2727. auth_fifo[auth_fifo_pos].delflag = 0;
  2728. auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr.sin_addr.s_addr;
  2729. auth_fifo_pos++;
  2730. // if no char-server, don't send void list of servers, just disconnect the player with proper message
  2731. } else {
  2732. login_log("Connection refused: there is no char-server online (account: %s, ip: %s)." RETCODE,
  2733. account.userid, ip);
  2734. WFIFOW(fd,0) = 0x81;
  2735. WFIFOL(fd,2) = 1; // 01 = Server closed
  2736. WFIFOSET(fd,3);
  2737. }
  2738. }
  2739. } else {
  2740. memset(WFIFOP(fd,0), '\0', 23);
  2741. WFIFOW(fd,0) = 0x6a;
  2742. WFIFOB(fd,2) = result;
  2743. if (result == 6) { // 6 = Your are Prohibited to log in until %s
  2744. i = search_account_index(account.userid);
  2745. if (i != -1) {
  2746. if (auth_dat[i].ban_until_time != 0) { // if account is banned, we send ban timestamp
  2747. char tmpstr[256];
  2748. strftime(tmpstr, 20, date_format, localtime(&auth_dat[i].ban_until_time));
  2749. tmpstr[19] = '\0';
  2750. memcpy(WFIFOP(fd,3), tmpstr, 20);
  2751. } else { // we send error message
  2752. memcpy(WFIFOP(fd,3), auth_dat[i].error_message, 20);
  2753. }
  2754. }
  2755. }
  2756. WFIFOSET(fd,23);
  2757. }
  2758. RFIFOSKIP(fd,(RFIFOW(fd,0) == 0x64) ? 55 : 47);
  2759. break;
  2760. case 0x01db: // Sending request of the coding key
  2761. case 0x791a: // Sending request of the coding key (administration packet)
  2762. {
  2763. struct login_session_data *ld;
  2764. if (session[fd]->session_data) {
  2765. printf("login: abnormal request of MD5 key (already opened session).\n");
  2766. session[fd]->eof = 1;
  2767. return 0;
  2768. }
  2769. ld = (struct login_session_data*)aCalloc(1, sizeof(struct login_session_data));
  2770. session[fd]->session_data = ld;
  2771. if (!ld) {
  2772. printf("login: Request for md5 key: memory allocation failure (malloc)!\n");
  2773. session[fd]->eof = 1;
  2774. return 0;
  2775. }
  2776. if (RFIFOW(fd,0) == 0x01db)
  2777. login_log("Sending request of the coding key (ip: %s)" RETCODE, ip);
  2778. else
  2779. login_log("'ladmin': Sending request of the coding key (ip: %s)" RETCODE, ip);
  2780. // Creation of the coding key
  2781. memset(ld->md5key, '\0', sizeof(ld->md5key));
  2782. ld->md5keylen = rand() % 4 + 12;
  2783. for(i = 0; i < ld->md5keylen; i++)
  2784. ld->md5key[i] = rand() % 255 + 1;
  2785. RFIFOSKIP(fd,2);
  2786. WFIFOW(fd,0) = 0x01dc;
  2787. WFIFOW(fd,2) = 4 + ld->md5keylen;
  2788. memcpy(WFIFOP(fd,4), ld->md5key, ld->md5keylen);
  2789. WFIFOSET(fd,WFIFOW(fd,2));
  2790. }
  2791. break;
  2792. case 0x2710: // Connection request of a char-server
  2793. if (RFIFOREST(fd) < 86)
  2794. return 0;
  2795. {
  2796. int GM_value, len;
  2797. char* server_name;
  2798. account.userid = (char*)RFIFOP(fd,2);
  2799. account.userid[23] = '\0';
  2800. remove_control_chars((unsigned char *)account.userid);
  2801. memcpy(account.passwd, RFIFOP(fd,26), 24);
  2802. account.passwd[24] = '\0';
  2803. remove_control_chars((unsigned char *)account.passwd);
  2804. account.passwdenc = 0;
  2805. server_name = (char*)RFIFOP(fd,60);
  2806. server_name[19] = '\0';
  2807. remove_control_chars((unsigned char *)server_name);
  2808. login_log("Connection request of the char-server '%s' @ %d.%d.%d.%d:%d (ip: %s)" RETCODE,
  2809. server_name, RFIFOB(fd,54), RFIFOB(fd,55), RFIFOB(fd,56), RFIFOB(fd,57), RFIFOW(fd,58), ip);
  2810. result = mmo_auth(&account, fd);
  2811. if (result == -1 && account.sex == 2 && account.account_id < MAX_SERVERS && server_fd[account.account_id] == -1) {
  2812. login_log("Connection of the char-server '%s' accepted (account: %s, pass: %s, ip: %s)" RETCODE,
  2813. server_name, account.userid, account.passwd, ip);
  2814. printf("Connection of the char-server '%s' accepted.\n", server_name);
  2815. memset(&server[account.account_id], 0, sizeof(struct mmo_char_server));
  2816. server[account.account_id].ip = RFIFOL(fd,54);
  2817. server[account.account_id].port = RFIFOW(fd,58);
  2818. memcpy(server[account.account_id].name, server_name, 20);
  2819. server[account.account_id].users = 0;
  2820. server[account.account_id].maintenance = RFIFOW(fd,82);
  2821. server[account.account_id].new_ = RFIFOW(fd,84);
  2822. server_fd[account.account_id] = fd;
  2823. if(anti_freeze_enable)
  2824. server_freezeflag[account.account_id] = 5; // Char-server anti-freeze system. Counter. 5 ok, 4...0 freezed
  2825. WFIFOW(fd,0) = 0x2711;
  2826. WFIFOB(fd,2) = 0;
  2827. WFIFOSET(fd,3);
  2828. session[fd]->func_parse = parse_fromchar;
  2829. realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
  2830. // send GM account to char-server
  2831. len = 4;
  2832. WFIFOW(fd,0) = 0x2732;
  2833. for(i = 0; i < auth_num; i++)
  2834. // send only existing accounts. We can not create a GM account when server is online.
  2835. if ((GM_value = isGM(auth_dat[i].account_id)) > 0) {
  2836. WFIFOL(fd,len) = auth_dat[i].account_id;
  2837. WFIFOB(fd,len+4) = (unsigned char)GM_value;
  2838. len += 5;
  2839. }
  2840. WFIFOW(fd,2) = len;
  2841. WFIFOSET(fd,len);
  2842. } else {
  2843. if (server_fd[account.account_id] != -1) {
  2844. printf("Connection of the char-server '%s' REFUSED - already connected (account: %ld-%s, pass: %s, ip: %s)\n",
  2845. server_name, account.account_id, account.userid, account.passwd, ip);
  2846. printf("You must probably wait that the freeze system detect the disconnection.\n");
  2847. login_log("Connexion of the char-server '%s' REFUSED - already connected (account: %ld-%s, pass: %s, ip: %s)" RETCODE,
  2848. server_name, account.account_id, account.userid, account.passwd, ip);
  2849. login_log("You must probably wait that the freeze system detect the disconnection." RETCODE);
  2850. } else {
  2851. printf("Connection of the char-server '%s' REFUSED (account: %s, pass: %s, ip: %s).\n", server_name, account.userid, account.passwd, ip);
  2852. login_log("Connexion of the char-server '%s' REFUSED (account: %s, pass: %s, ip: %s)" RETCODE,
  2853. server_name, account.userid, account.passwd, ip);
  2854. }
  2855. WFIFOW(fd,0) = 0x2711;
  2856. WFIFOB(fd,2) = 3;
  2857. WFIFOSET(fd,3);
  2858. }
  2859. }
  2860. RFIFOSKIP(fd,86);
  2861. return 0;
  2862. case 0x7530: // Request of the server version
  2863. login_log("Sending of the server version (ip: %s)" RETCODE, ip);
  2864. WFIFOW(fd,0) = 0x7531;
  2865. WFIFOB(fd,2) = ATHENA_MAJOR_VERSION;
  2866. WFIFOB(fd,3) = ATHENA_MINOR_VERSION;
  2867. WFIFOB(fd,4) = ATHENA_REVISION;
  2868. WFIFOB(fd,5) = ATHENA_RELEASE_FLAG;
  2869. WFIFOB(fd,6) = ATHENA_OFFICIAL_FLAG;
  2870. WFIFOB(fd,7) = ATHENA_SERVER_LOGIN;
  2871. WFIFOW(fd,8) = ATHENA_MOD_VERSION;
  2872. WFIFOSET(fd,10);
  2873. RFIFOSKIP(fd,2);
  2874. break;
  2875. case 0x7532: // Request to end connection
  2876. login_log("End of connection (ip: %s)" RETCODE, ip);
  2877. session[fd]->eof = 1;
  2878. return 0;
  2879. case 0x7918: // Request for administation login
  2880. if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < ((RFIFOW(fd,2) == 0) ? 28 : 20))
  2881. return 0;
  2882. WFIFOW(fd,0) = 0x7919;
  2883. WFIFOB(fd,2) = 1;
  2884. if (!check_ladminip(session[fd]->client_addr.sin_addr.s_addr)) {
  2885. login_log("'ladmin'-login: Connection in administration mode refused: IP isn't authorised (ladmin_allow, ip: %s)." RETCODE, ip);
  2886. } else {
  2887. struct login_session_data *ld = (struct login_session_data*)session[fd]->session_data;
  2888. if (RFIFOW(fd,2) == 0) { // non encrypted password
  2889. char* password="";
  2890. memcpy(password, RFIFOP(fd,4), 24);
  2891. password[24] = '\0';
  2892. remove_control_chars((unsigned char *)password);
  2893. // If remote administration is enabled and password sent by client matches password read from login server configuration file
  2894. if ((admin_state == 1) && (strcmp(password, admin_pass) == 0)) {
  2895. login_log("'ladmin'-login: Connection in administration mode accepted (non encrypted password: %s, ip: %s)" RETCODE, password, ip);
  2896. printf("Connection of a remote administration accepted (non encrypted password).\n");
  2897. WFIFOB(fd,2) = 0;
  2898. session[fd]->func_parse = parse_admin;
  2899. } else if (admin_state != 1)
  2900. login_log("'ladmin'-login: Connection in administration mode REFUSED - remote administration is disabled (non encrypted password: %s, ip: %s)" RETCODE, password, ip);
  2901. else
  2902. login_log("'ladmin'-login: Connection in administration mode REFUSED - invalid password (non encrypted password: %s, ip: %s)" RETCODE, password, ip);
  2903. } else { // encrypted password
  2904. if (!ld)
  2905. printf("'ladmin'-login: error! MD5 key not created/requested for an administration login.\n");
  2906. else {
  2907. char md5str[64] = "", md5bin[32];
  2908. if (RFIFOW(fd,2) == 1) {
  2909. sprintf(md5str, "%s%s", ld->md5key, admin_pass); // 20 24
  2910. } else if (RFIFOW(fd,2) == 2) {
  2911. sprintf(md5str, "%s%s", admin_pass, ld->md5key); // 24 20
  2912. }
  2913. MD5_String2binary(md5str, md5bin);
  2914. // If remote administration is enabled and password hash sent by client matches hash of password read from login server configuration file
  2915. if ((admin_state == 1) && (memcmp(md5bin, RFIFOP(fd,4), 16) == 0)) {
  2916. login_log("'ladmin'-login: Connection in administration mode accepted (encrypted password, ip: %s)" RETCODE, ip);
  2917. printf("Connection of a remote administration accepted (encrypted password).\n");
  2918. WFIFOB(fd,2) = 0;
  2919. session[fd]->func_parse = parse_admin;
  2920. } else if (admin_state != 1)
  2921. login_log("'ladmin'-login: Connection in administration mode REFUSED - remote administration is disabled (encrypted password, ip: %s)" RETCODE, ip);
  2922. else
  2923. login_log("'ladmin'-login: Connection in administration mode REFUSED - invalid password (encrypted password, ip: %s)" RETCODE, ip);
  2924. }
  2925. }
  2926. }
  2927. WFIFOSET(fd,3);
  2928. RFIFOSKIP(fd, (RFIFOW(fd,2) == 0) ? 28 : 20);
  2929. break;
  2930. default:
  2931. if (save_unknown_packets) {
  2932. FILE *logfp;
  2933. char tmpstr[24];
  2934. struct timeval tv;
  2935. logfp = fopen(login_log_unknown_packets_filename, "a");
  2936. if (logfp) {
  2937. gettimeofday(&tv, NULL);
  2938. strftime(tmpstr, 23, date_format, localtime((const time_t*)&(tv.tv_sec)));
  2939. fprintf(logfp, "%s.%03d: receiving of an unknown packet -> disconnection" RETCODE, tmpstr, (int)tv.tv_usec / 1000);
  2940. fprintf(logfp, "parse_login: connection #%d (ip: %s), packet: 0x%x (with being read: %d)." RETCODE, fd, ip, RFIFOW(fd,0), RFIFOREST(fd));
  2941. fprintf(logfp, "Detail (in hex):" RETCODE);
  2942. fprintf(logfp, "---- 00-01-02-03-04-05-06-07 08-09-0A-0B-0C-0D-0E-0F" RETCODE);
  2943. memset(tmpstr, '\0', sizeof(tmpstr));
  2944. for(i = 0; i < RFIFOREST(fd); i++) {
  2945. if ((i & 15) == 0)
  2946. fprintf(logfp, "%04X ",i);
  2947. fprintf(logfp, "%02x ", RFIFOB(fd,i));
  2948. if (RFIFOB(fd,i) > 0x1f)
  2949. tmpstr[i % 16] = RFIFOB(fd,i);
  2950. else
  2951. tmpstr[i % 16] = '.';
  2952. if ((i - 7) % 16 == 0) // -8 + 1
  2953. fprintf(logfp, " ");
  2954. else if ((i + 1) % 16 == 0) {
  2955. fprintf(logfp, " %s" RETCODE, tmpstr);
  2956. memset(tmpstr, '\0', sizeof(tmpstr));
  2957. }
  2958. }
  2959. if (i % 16 != 0) {
  2960. for(j = i; j % 16 != 0; j++) {
  2961. fprintf(logfp, " ");
  2962. if ((j - 7) % 16 == 0) // -8 + 1
  2963. fprintf(logfp, " ");
  2964. }
  2965. fprintf(logfp, " %s" RETCODE, tmpstr);
  2966. }
  2967. fprintf(logfp, RETCODE);
  2968. fclose(logfp);
  2969. }
  2970. }
  2971. login_log("End of connection, unknown packet (ip: %s)" RETCODE, ip);
  2972. session[fd]->eof = 1;
  2973. return 0;
  2974. }
  2975. }
  2976. return 0;
  2977. }
  2978. //-----------------------
  2979. // Console Command Parser [Wizputer]
  2980. //-----------------------
  2981. int parse_console(char *buf) {
  2982. char command[256];
  2983. memset(command,0,sizeof(command));
  2984. sscanf(buf, "%[^\n]", command);
  2985. login_log("Console command :%s" RETCODE, command);
  2986. if(strcmpi("shutdown", command) == 0 ||
  2987. strcmpi("exit", command) == 0 ||
  2988. strcmpi("quit", command) == 0 ||
  2989. strcmpi("end", command) == 0)
  2990. exit(0);
  2991. else if(strcmpi("alive", command) == 0 ||
  2992. strcmpi("status", command) == 0)
  2993. printf("\033[0;36mConsole: \033[0m\033[1mI'm Alive.\033[0m\n");
  2994. else if(strcmpi("help", command) == 0) {
  2995. printf("\033[32mHelp of commands:\033[0m\n");
  2996. printf(" To shutdown the server:\n");
  2997. printf(" 'shutdown|exit|qui|end'\n");
  2998. printf(" To know if server is alive:\n");
  2999. printf(" 'alive|status'\n");
  3000. }
  3001. return 0;
  3002. }
  3003. //-------------------------------------------------
  3004. // Return numerical value of a switch configuration
  3005. // on/off, english, français, deutsch, español
  3006. //-------------------------------------------------
  3007. int config_switch(const char *str) {
  3008. if (strcmpi(str, "on") == 0 || strcmpi(str, "yes") == 0 || strcmpi(str, "oui") == 0 || strcmpi(str, "ja") == 0 || strcmpi(str, "si") == 0)
  3009. return 1;
  3010. if (strcmpi(str, "off") == 0 || strcmpi(str, "no") == 0 || strcmpi(str, "non") == 0 || strcmpi(str, "nein") == 0)
  3011. return 0;
  3012. return atoi(str);
  3013. }
  3014. //----------------------------------
  3015. // Reading Lan Support configuration
  3016. //----------------------------------
  3017. int login_lan_config_read(const char *lancfgName) {
  3018. int j;
  3019. struct hostent * h = NULL;
  3020. char line[1024], w1[1024], w2[1024];
  3021. FILE *fp;
  3022. // set default configuration
  3023. strncpy(lan_char_ip, "127.0.0.1", sizeof(lan_char_ip));
  3024. subneti[0] = 127;
  3025. subneti[1] = 0;
  3026. subneti[2] = 0;
  3027. subneti[3] = 1;
  3028. for(j = 0; j < 4; j++)
  3029. subnetmaski[j] = 255;
  3030. fp = fopen(lancfgName, "r");
  3031. if (fp == NULL) {
  3032. printf("***WARNING: LAN Support configuration file is not found: %s\n", lancfgName);
  3033. return 1;
  3034. }
  3035. printf("---Start reading Lan Support configuration file\n");
  3036. while(fgets(line, sizeof(line)-1, fp)) {
  3037. if (line[0] == '/' && line[1] == '/')
  3038. continue;
  3039. line[sizeof(line)-1] = '\0';
  3040. memset(w2, 0, sizeof(w2));
  3041. if (sscanf(line,"%[^:]: %[^\r\n]", w1, w2) != 2)
  3042. continue;
  3043. remove_control_chars((unsigned char *)w1);
  3044. remove_control_chars((unsigned char *)w2);
  3045. if (strcmpi(w1, "lan_char_ip") == 0) { // Read Char-Server Lan IP Address
  3046. memset(lan_char_ip, 0, sizeof(lan_char_ip));
  3047. h = gethostbyname(w2);
  3048. if (h != NULL) {
  3049. sprintf(lan_char_ip, "%d.%d.%d.%d", (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]);
  3050. } else {
  3051. strncpy(lan_char_ip, w2, sizeof(lan_char_ip));
  3052. lan_char_ip[sizeof(lan_char_ip)-1] = '\0';
  3053. }
  3054. printf("LAN IP of char-server: %s.\n", lan_char_ip);
  3055. } else if (strcmpi(w1, "subnet") == 0) { // Read Subnetwork
  3056. for(j = 0; j < 4; j++)
  3057. subneti[j] = 0;
  3058. h = gethostbyname(w2);
  3059. if (h != NULL) {
  3060. for(j = 0; j < 4; j++)
  3061. subneti[j] = (unsigned char)h->h_addr[j];
  3062. } else {
  3063. sscanf(w2, "%d.%d.%d.%d", &subneti[0], &subneti[1], &subneti[2], &subneti[3]);
  3064. }
  3065. printf("Sub-network of the char-server: %d.%d.%d.%d.\n", subneti[0], subneti[1], subneti[2], subneti[3]);
  3066. } else if (strcmpi(w1, "subnetmask") == 0) { // Read Subnetwork Mask
  3067. for(j = 0; j < 4; j++)
  3068. subnetmaski[j] = 255;
  3069. h = gethostbyname(w2);
  3070. if (h != NULL) {
  3071. for(j = 0; j < 4; j++)
  3072. subnetmaski[j] = (unsigned char)h->h_addr[j];
  3073. } else {
  3074. sscanf(w2, "%d.%d.%d.%d", &subnetmaski[0], &subnetmaski[1], &subnetmaski[2], &subnetmaski[3]);
  3075. }
  3076. printf("Sub-network mask of the char-server: %d.%d.%d.%d.\n", subnetmaski[0], subnetmaski[1], subnetmaski[2], subnetmaski[3]);
  3077. }
  3078. }
  3079. fclose(fp);
  3080. // log the LAN configuration
  3081. login_log("The LAN configuration of the server is set:" RETCODE);
  3082. login_log("- with LAN IP of char-server: %s." RETCODE, lan_char_ip);
  3083. login_log("- with the sub-network of the char-server: %d.%d.%d.%d/%d.%d.%d.%d." RETCODE,
  3084. subneti[0], subneti[1], subneti[2], subneti[3], subnetmaski[0], subnetmaski[1], subnetmaski[2], subnetmaski[3]);
  3085. // sub-network check of the char-server
  3086. {
  3087. unsigned int a0, a1, a2, a3;
  3088. unsigned char p[4];
  3089. sscanf(lan_char_ip, "%d.%d.%d.%d", &a0, &a1, &a2, &a3);
  3090. p[0] = a0; p[1] = a1; p[2] = a2; p[3] = a3;
  3091. printf("LAN test of LAN IP of the char-server: ");
  3092. if (lan_ip_check(p) == 0) {
  3093. printf("\033[1;31m***ERROR: LAN IP of the char-server doesn't belong to the specified Sub-network\033[0m\n");
  3094. login_log("***ERROR: LAN IP of the char-server doesn't belong to the specified Sub-network." RETCODE);
  3095. }
  3096. }
  3097. printf("---End reading of Lan Support configuration file\n");
  3098. return 0;
  3099. }
  3100. //-----------------------------------
  3101. // Reading general configuration file
  3102. //-----------------------------------
  3103. int login_config_read(const char *cfgName) {
  3104. char line[1024], w1[1024], w2[1024];
  3105. FILE *fp;
  3106. struct hostent *h = NULL;
  3107. bind_ip_str[0] = '\0';
  3108. if ((fp = fopen(cfgName, "r")) == NULL) {
  3109. printf("Configuration file (%s) not found.\n", cfgName);
  3110. return 1;
  3111. }
  3112. printf("---Start reading of Login Server configuration file (%s)\n", cfgName);
  3113. while(fgets(line, sizeof(line)-1, fp)) {
  3114. if (line[0] == '/' && line[1] == '/')
  3115. continue;
  3116. line[sizeof(line)-1] = '\0';
  3117. memset(w2, 0, sizeof(w2));
  3118. if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) == 2) {
  3119. remove_control_chars((unsigned char *)w1);
  3120. remove_control_chars((unsigned char *)w2);
  3121. if (strcmpi(w1, "admin_state") == 0) {
  3122. admin_state = config_switch(w2);
  3123. } else if (strcmpi(w1, "admin_pass") == 0) {
  3124. memset(admin_pass, 0, sizeof(admin_pass));
  3125. strncpy(admin_pass, w2, sizeof(admin_pass));
  3126. admin_pass[sizeof(admin_pass)-1] = '\0';
  3127. } else if (strcmpi(w1, "ladminallowip") == 0) {
  3128. if (strcmpi(w2, "clear") == 0) {
  3129. if (access_ladmin_allow)
  3130. aFree(access_ladmin_allow);
  3131. access_ladmin_allow = NULL;
  3132. access_ladmin_allownum = 0;
  3133. } else {
  3134. if (strcmpi(w2, "all") == 0) {
  3135. // reset all previous values
  3136. if (access_ladmin_allow)
  3137. aFree(access_ladmin_allow);
  3138. // set to all
  3139. access_ladmin_allow = (char*)aCalloc(ACO_STRSIZE, sizeof(char));
  3140. access_ladmin_allownum = 1;
  3141. access_ladmin_allow[0] = '\0';
  3142. } else if (w2[0] && !(access_ladmin_allownum == 1 && access_ladmin_allow[0] == '\0')) { // don't add IP if already 'all'
  3143. if (access_ladmin_allow)
  3144. access_ladmin_allow = (char*)aRealloc(access_ladmin_allow, (access_ladmin_allownum+1) * ACO_STRSIZE);
  3145. else
  3146. access_ladmin_allow = (char*)aCalloc(ACO_STRSIZE, sizeof(char));
  3147. strncpy(access_ladmin_allow + (access_ladmin_allownum++) * ACO_STRSIZE, w2, ACO_STRSIZE);
  3148. access_ladmin_allow[access_ladmin_allownum * ACO_STRSIZE - 1] = '\0';
  3149. }
  3150. }
  3151. } else if (strcmpi(w1, "gm_pass") == 0) {
  3152. memset(gm_pass, 0, sizeof(gm_pass));
  3153. strncpy(gm_pass, w2, sizeof(gm_pass));
  3154. gm_pass[sizeof(gm_pass)-1] = '\0';
  3155. } else if (strcmpi(w1, "level_new_gm") == 0) {
  3156. level_new_gm = atoi(w2);
  3157. } else if (strcmpi(w1, "new_account") == 0) {
  3158. new_account_flag = config_switch(w2);
  3159. } else if (strcmpi(w1, "bind_ip") == 0) {
  3160. //bind_ip_set_ = 1;
  3161. h = gethostbyname (w2);
  3162. if (h != NULL) {
  3163. printf("Login server binding IP address : %s -> %d.%d.%d.%d\n", w2, (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]);
  3164. sprintf(bind_ip_str, "%d.%d.%d.%d", (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]);
  3165. } else
  3166. memcpy(bind_ip_str,w2,16);
  3167. } else if (strcmpi(w1, "login_port") == 0) {
  3168. login_port = atoi(w2);
  3169. } else if (strcmpi(w1, "account_filename") == 0) {
  3170. memset(account_filename, 0, sizeof(account_filename));
  3171. strncpy(account_filename, w2, sizeof(account_filename));
  3172. account_filename[sizeof(account_filename)-1] = '\0';
  3173. } else if (strcmpi(w1, "gm_account_filename") == 0) {
  3174. memset(GM_account_filename, 0, sizeof(GM_account_filename));
  3175. strncpy(GM_account_filename, w2, sizeof(GM_account_filename));
  3176. GM_account_filename[sizeof(GM_account_filename)-1] = '\0';
  3177. } else if (strcmpi(w1, "gm_account_filename_check_timer") == 0) {
  3178. gm_account_filename_check_timer = atoi(w2);
  3179. } else if (strcmpi(w1, "use_MD5_passwords") == 0) {
  3180. use_md5_passwds = config_switch(w2);
  3181. } else if (strcmpi(w1, "login_log_filename") == 0) {
  3182. memset(login_log_filename, 0, sizeof(login_log_filename));
  3183. strncpy(login_log_filename, w2, sizeof(login_log_filename));
  3184. login_log_filename[sizeof(login_log_filename)-1] = '\0';
  3185. } else if (strcmpi(w1, "log_login") == 0) {
  3186. log_login = atoi(w2);
  3187. } else if (strcmpi(w1, "login_log_unknown_packets_filename") == 0) {
  3188. memset(login_log_unknown_packets_filename, 0, sizeof(login_log_unknown_packets_filename));
  3189. strncpy(login_log_unknown_packets_filename, w2, sizeof(login_log_unknown_packets_filename));
  3190. login_log_unknown_packets_filename[sizeof(login_log_unknown_packets_filename)-1] = '\0';
  3191. } else if (strcmpi(w1, "save_unknown_packets") == 0) {
  3192. save_unknown_packets = config_switch(w2);
  3193. } else if (strcmpi(w1, "display_parse_login") == 0) {
  3194. display_parse_login = config_switch(w2); // 0: no, 1: yes
  3195. } else if (strcmpi(w1, "display_parse_admin") == 0) {
  3196. display_parse_admin = config_switch(w2); // 0: no, 1: yes
  3197. } else if (strcmpi(w1, "display_parse_fromchar") == 0) {
  3198. display_parse_fromchar = config_switch(w2); // 0: no, 1: yes (without packet 0x2714), 2: all packets
  3199. } else if (strcmpi(w1, "date_format") == 0) { // note: never have more than 19 char for the date!
  3200. memset(date_format, 0, sizeof(date_format));
  3201. switch (atoi(w2)) {
  3202. case 0:
  3203. strcpy(date_format, "%d-%m-%Y %H:%M:%S"); // 31-12-2004 23:59:59
  3204. break;
  3205. case 1:
  3206. strcpy(date_format, "%m-%d-%Y %H:%M:%S"); // 12-31-2004 23:59:59
  3207. break;
  3208. case 2:
  3209. strcpy(date_format, "%Y-%d-%m %H:%M:%S"); // 2004-31-12 23:59:59
  3210. break;
  3211. case 3:
  3212. strcpy(date_format, "%Y-%m-%d %H:%M:%S"); // 2004-12-31 23:59:59
  3213. break;
  3214. }
  3215. } else if (strcmpi(w1, "min_level_to_connect") == 0) {
  3216. min_level_to_connect = atoi(w2);
  3217. } else if (strcmpi(w1, "add_to_unlimited_account") == 0) {
  3218. add_to_unlimited_account = config_switch(w2);
  3219. } else if (strcmpi(w1, "start_limited_time") == 0) {
  3220. start_limited_time = atoi(w2);
  3221. } else if (strcmpi(w1, "check_ip_flag") == 0) {
  3222. check_ip_flag = config_switch(w2);
  3223. } else if (strcmpi(w1, "order") == 0) {
  3224. access_order = atoi(w2);
  3225. if (strcmpi(w2, "deny,allow") == 0 ||
  3226. strcmpi(w2, "deny, allow") == 0) access_order = ACO_DENY_ALLOW;
  3227. if (strcmpi(w2, "allow,deny") == 0 ||
  3228. strcmpi(w2, "allow, deny") == 0) access_order = ACO_ALLOW_DENY;
  3229. if (strcmpi(w2, "mutual-failture") == 0 ||
  3230. strcmpi(w2, "mutual-failure") == 0) access_order = ACO_MUTUAL_FAILTURE;
  3231. } else if (strcmpi(w1, "allow") == 0) {
  3232. if (strcmpi(w2, "clear") == 0) {
  3233. if (access_allow)
  3234. aFree(access_allow);
  3235. access_allow = NULL;
  3236. access_allownum = 0;
  3237. } else {
  3238. if (strcmpi(w2, "all") == 0) {
  3239. // reset all previous values
  3240. if (access_allow)
  3241. aFree(access_allow);
  3242. // set to all
  3243. access_allow = (char*)aCalloc(ACO_STRSIZE, sizeof(char));
  3244. access_allownum = 1;
  3245. access_allow[0] = '\0';
  3246. } else if (w2[0] && !(access_allownum == 1 && access_allow[0] == '\0')) { // don't add IP if already 'all'
  3247. if (access_allow)
  3248. access_allow = (char*)aRealloc(access_allow, (access_allownum+1) * ACO_STRSIZE);
  3249. else
  3250. access_allow = (char*)aCalloc(ACO_STRSIZE, sizeof(char));
  3251. strncpy(access_allow + (access_allownum++) * ACO_STRSIZE, w2, ACO_STRSIZE);
  3252. access_allow[access_allownum * ACO_STRSIZE - 1] = '\0';
  3253. }
  3254. }
  3255. } else if (strcmpi(w1, "deny") == 0) {
  3256. if (strcmpi(w2, "clear") == 0) {
  3257. if (access_deny)
  3258. aFree(access_deny);
  3259. access_deny = NULL;
  3260. access_denynum = 0;
  3261. } else {
  3262. if (strcmpi(w2, "all") == 0) {
  3263. // reset all previous values
  3264. if (access_deny)
  3265. aFree(access_deny);
  3266. // set to all
  3267. access_deny = (char*)aCalloc(ACO_STRSIZE, sizeof(char));
  3268. access_denynum = 1;
  3269. access_deny[0] = '\0';
  3270. } else if (w2[0] && !(access_denynum == 1 && access_deny[0] == '\0')) { // don't add IP if already 'all'
  3271. if (access_deny)
  3272. access_deny = (char*)aRealloc(access_deny, (access_denynum+1) * ACO_STRSIZE);
  3273. else
  3274. access_deny = (char*)aCalloc(ACO_STRSIZE, sizeof(char));
  3275. strncpy(access_deny + (access_denynum++) * ACO_STRSIZE, w2, ACO_STRSIZE);
  3276. access_deny[access_denynum * ACO_STRSIZE - 1] = '\0';
  3277. }
  3278. }
  3279. // dynamic password error ban
  3280. } else if (strcmpi(w1, "dynamic_pass_failure_ban") == 0) {
  3281. dynamic_pass_failure_ban = config_switch(w2);
  3282. } else if (strcmpi(w1, "dynamic_pass_failure_ban_time") == 0) {
  3283. dynamic_pass_failure_ban_time = atoi(w2);
  3284. } else if (strcmpi(w1, "dynamic_pass_failure_ban_how_many") == 0) {
  3285. dynamic_pass_failure_ban_how_many = atoi(w2);
  3286. } else if (strcmpi(w1, "dynamic_pass_failure_ban_how_long") == 0) {
  3287. dynamic_pass_failure_ban_how_long = atoi(w2);
  3288. // Anti-Freeze
  3289. } else if(strcmpi(w1,"anti_freeze_enable")==0){
  3290. anti_freeze_enable = config_switch(w2);
  3291. } else if (strcmpi(w1, "anti_freeze_interval") == 0) {
  3292. ANTI_FREEZE_INTERVAL = atoi(w2);
  3293. if (ANTI_FREEZE_INTERVAL < 5)
  3294. ANTI_FREEZE_INTERVAL = 5; // minimum 5 seconds
  3295. } else if (strcmpi(w1, "import") == 0) {
  3296. login_config_read(w2);
  3297. } else if(strcmpi(w1,"imalive_on")==0) { //Added by Mugendai for I'm Alive mod
  3298. imalive_on = atoi(w2); //Added by Mugendai for I'm Alive mod
  3299. } else if(strcmpi(w1,"imalive_time")==0) { //Added by Mugendai for I'm Alive mod
  3300. imalive_time = atoi(w2); //Added by Mugendai for I'm Alive mod
  3301. } else if(strcmpi(w1,"flush_on")==0) { //Added by Mugendai for GUI
  3302. flush_on = atoi(w2); //Added by Mugendai for GUI
  3303. } else if(strcmpi(w1,"flush_time")==0) { //Added by Mugendai for GUI
  3304. flush_time = atoi(w2); //Added by Mugendai for GUI
  3305. } else if(strcmpi(w1, "check_client_version") == 0){ //Added by Sirius for client version check
  3306. if(strcmpi(w2,"on") == 0 || strcmpi(w2,"yes") == 0 ){
  3307. check_client_version = 1;
  3308. }
  3309. if(strcmpi(w2,"off") == 0 || strcmpi(w2,"no") == 0 ){
  3310. check_client_version = 0;
  3311. }
  3312. }else if(strcmpi(w1, "client_version_to_connect") == 0){ //Added by Sirius for client version check
  3313. client_version_to_connect = atoi(w2); //Added by Sirius for client version check
  3314. } else if (strcmpi(w1, "console") == 0) {
  3315. if(strcmpi(w2,"on") == 0 || strcmpi(w2,"yes") == 0 )
  3316. console = 1;
  3317. }
  3318. }
  3319. }
  3320. fclose(fp);
  3321. printf("---End reading of Login Server configuration file.\n");
  3322. return 0;
  3323. }
  3324. //-------------------------------------
  3325. // Displaying of configuration warnings
  3326. //-------------------------------------
  3327. void display_conf_warnings(void) {
  3328. if (admin_state != 0 && admin_state != 1) {
  3329. printf("***WARNING: Invalid value for admin_state parameter -> set to 0 (no remote admin).\n");
  3330. admin_state = 0;
  3331. }
  3332. if (admin_state == 1) {
  3333. if (admin_pass[0] == '\0') {
  3334. printf("***WARNING: Administrator password is void (admin_pass).\n");
  3335. } else if (strcmp(admin_pass, "admin") == 0) {
  3336. printf("***WARNING: You are using the default administrator password (admin_pass).\n");
  3337. printf(" We highly recommend that you change it.\n");
  3338. }
  3339. }
  3340. if (gm_pass[0] == '\0') {
  3341. printf("***WARNING: 'To GM become' password is void (gm_pass).\n");
  3342. printf(" We highly recommend that you set one password.\n");
  3343. } else if (strcmp(gm_pass, "gm") == 0) {
  3344. printf("***WARNING: You are using the default GM password (gm_pass).\n");
  3345. printf(" We highly recommend that you change it.\n");
  3346. }
  3347. if (level_new_gm < 0 || level_new_gm > 99) {
  3348. printf("***WARNING: Invalid value for level_new_gm parameter -> set to 60 (default).\n");
  3349. level_new_gm = 60;
  3350. }
  3351. if (new_account_flag != 0 && new_account_flag != 1) {
  3352. printf("***WARNING: Invalid value for new_account parameter -> set to 0 (no new account).\n");
  3353. new_account_flag = 0;
  3354. }
  3355. if (login_port < 1024 || login_port > 65535) {
  3356. printf("***WARNING: Invalid value for login_port parameter -> set to 6900 (default).\n");
  3357. login_port = 6900;
  3358. }
  3359. if (gm_account_filename_check_timer < 0) {
  3360. printf("***WARNING: Invalid value for gm_account_filename_check_timer parameter.\n");
  3361. printf(" -> set to 15 sec (default).\n");
  3362. gm_account_filename_check_timer = 15;
  3363. } else if (gm_account_filename_check_timer == 1) {
  3364. printf("***WARNING: Invalid value for gm_account_filename_check_timer parameter.\n");
  3365. printf(" -> set to 2 sec (minimum value).\n");
  3366. gm_account_filename_check_timer = 2;
  3367. }
  3368. if (save_unknown_packets != 0 && save_unknown_packets != 1) {
  3369. printf("WARNING: Invalid value for save_unknown_packets parameter -> set to 0-no save.\n");
  3370. save_unknown_packets = 0;
  3371. }
  3372. if (display_parse_login != 0 && display_parse_login != 1) { // 0: no, 1: yes
  3373. printf("***WARNING: Invalid value for display_parse_login parameter\n");
  3374. printf(" -> set to 0 (no display).\n");
  3375. display_parse_login = 0;
  3376. }
  3377. if (display_parse_admin != 0 && display_parse_admin != 1) { // 0: no, 1: yes
  3378. printf("***WARNING: Invalid value for display_parse_admin parameter\n");
  3379. printf(" -> set to 0 (no display).\n");
  3380. display_parse_admin = 0;
  3381. }
  3382. if (display_parse_fromchar < 0 || display_parse_fromchar > 2) { // 0: no, 1: yes (without packet 0x2714), 2: all packets
  3383. printf("***WARNING: Invalid value for display_parse_fromchar parameter\n");
  3384. printf(" -> set to 0 (no display).\n");
  3385. display_parse_fromchar = 0;
  3386. }
  3387. if (min_level_to_connect < 0) { // 0: all players, 1-99 at least gm level x
  3388. printf("***WARNING: Invalid value for min_level_to_connect (%d) parameter\n", min_level_to_connect);
  3389. printf(" -> set to 0 (any player).\n");
  3390. min_level_to_connect = 0;
  3391. } else if (min_level_to_connect > 99) { // 0: all players, 1-99 at least gm level x
  3392. printf("***WARNING: Invalid value for min_level_to_connect (%d) parameter\n", min_level_to_connect);
  3393. printf(" -> set to 99 (only GM level 99).\n");
  3394. min_level_to_connect = 99;
  3395. }
  3396. if (add_to_unlimited_account != 0 && add_to_unlimited_account != 1) { // 0: no, 1: yes
  3397. printf("***WARNING: Invalid value for add_to_unlimited_account parameter\n");
  3398. printf(" -> set to 0 (impossible to add a time to an unlimited account).\n");
  3399. add_to_unlimited_account = 0;
  3400. }
  3401. if (start_limited_time < -1) { // -1: create unlimited account, 0 or more: additionnal sec from now to create limited time
  3402. printf("***WARNING: Invalid value for start_limited_time parameter\n");
  3403. printf(" -> set to -1 (new accounts are created with unlimited time).\n");
  3404. start_limited_time = -1;
  3405. }
  3406. if (check_ip_flag != 0 && check_ip_flag != 1) { // 0: no, 1: yes
  3407. printf("***WARNING: Invalid value for check_ip_flag parameter\n");
  3408. printf(" -> set to 1 (check players ip between login-server & char-server).\n");
  3409. check_ip_flag = 1;
  3410. }
  3411. if (access_order == ACO_DENY_ALLOW) {
  3412. if (access_denynum == 1 && access_deny[0] == '\0') {
  3413. printf("***WARNING: The IP security order is 'deny,allow' (allow if not deny).\n");
  3414. printf(" And you refuse ALL IP.\n");
  3415. }
  3416. } else if (access_order == ACO_ALLOW_DENY) {
  3417. if (access_allownum == 0) {
  3418. printf("***WARNING: The IP security order is 'allow,deny' (deny if not allow).\n");
  3419. printf(" But, NO IP IS AUTHORISED!\n");
  3420. }
  3421. } else { // ACO_MUTUAL_FAILTURE
  3422. if (access_allownum == 0) {
  3423. printf("***WARNING: The IP security order is 'mutual-failture'\n");
  3424. printf(" (allow if in the allow list and not in the deny list).\n");
  3425. printf(" But, NO IP IS AUTHORISED!\n");
  3426. } else if (access_denynum == 1 && access_deny[0] == '\0') {
  3427. printf("***WARNING: The IP security order is mutual-failture\n");
  3428. printf(" (allow if in the allow list and not in the deny list).\n");
  3429. printf(" But, you refuse ALL IP!\n");
  3430. }
  3431. }
  3432. if (dynamic_pass_failure_ban != 0) {
  3433. if (dynamic_pass_failure_ban_time < 1) {
  3434. printf("***WARNING: Invalid value for dynamic_pass_failure_ban_time (%d) parameter\n", dynamic_pass_failure_ban_time);
  3435. printf(" -> set to 5 (5 minutes to look number of invalid passwords.\n");
  3436. dynamic_pass_failure_ban_time = 5;
  3437. }
  3438. if (dynamic_pass_failure_ban_how_many < 1) {
  3439. printf("***WARNING: Invalid value for dynamic_pass_failure_ban_how_many (%d) parameter\n", dynamic_pass_failure_ban_how_many);
  3440. printf(" -> set to 3 (3 invalid passwords before to temporarily ban.\n");
  3441. dynamic_pass_failure_ban_how_many = 3;
  3442. }
  3443. if (dynamic_pass_failure_ban_how_long < 1) {
  3444. printf("***WARNING: Invalid value for dynamic_pass_failure_ban_how_long (%d) parameter\n", dynamic_pass_failure_ban_how_long);
  3445. printf(" -> set to 1 (1 minute of temporarily ban.\n");
  3446. dynamic_pass_failure_ban_how_long = 1;
  3447. }
  3448. }
  3449. return;
  3450. }
  3451. //-------------------------------
  3452. // Save configuration in log file
  3453. //-------------------------------
  3454. void save_config_in_log(void) {
  3455. int i;
  3456. // a newline in the log...
  3457. login_log("");
  3458. login_log("The login-server starting..." RETCODE);
  3459. // save configuration in log file
  3460. login_log("The configuration of the server is set:" RETCODE);
  3461. if (admin_state != 1)
  3462. login_log("- with no remote administration." RETCODE);
  3463. else if (admin_pass[0] == '\0')
  3464. login_log("- with a remote administration with a VOID password." RETCODE);
  3465. else if (strcmp(admin_pass, "admin") == 0)
  3466. login_log("- with a remote administration with the DEFAULT password." RETCODE);
  3467. else
  3468. login_log("- with a remote administration with the password of %d character(s)." RETCODE, strlen(admin_pass));
  3469. if (access_ladmin_allownum == 0 || (access_ladmin_allownum == 1 && access_ladmin_allow[0] == '\0')) {
  3470. login_log("- to accept any IP for remote administration" RETCODE);
  3471. } else {
  3472. login_log("- to accept following IP for remote administration:" RETCODE);
  3473. for(i = 0; i < access_ladmin_allownum; i++)
  3474. login_log(" %s" RETCODE, (char *)(access_ladmin_allow + i * ACO_STRSIZE));
  3475. }
  3476. if (gm_pass[0] == '\0')
  3477. login_log("- with a VOID 'To GM become' password (gm_pass)." RETCODE);
  3478. else if (strcmp(gm_pass, "gm") == 0)
  3479. login_log("- with the DEFAULT 'To GM become' password (gm_pass)." RETCODE);
  3480. else
  3481. login_log("- with a 'To GM become' password (gm_pass) of %d character(s)." RETCODE, strlen(gm_pass));
  3482. if (level_new_gm == 0)
  3483. login_log("- to refuse any creation of GM with @gm." RETCODE);
  3484. else
  3485. login_log("- to create GM with level '%d' when @gm is used." RETCODE, level_new_gm);
  3486. if (new_account_flag == 1)
  3487. login_log("- to ALLOW new users (with _F/_M)." RETCODE);
  3488. else
  3489. login_log("- to NOT ALLOW new users (with _F/_M)." RETCODE);
  3490. login_log("- with port: %d." RETCODE, login_port);
  3491. login_log("- with the accounts file name: '%s'." RETCODE, account_filename);
  3492. login_log("- with the GM accounts file name: '%s'." RETCODE, GM_account_filename);
  3493. if (gm_account_filename_check_timer == 0)
  3494. login_log("- to NOT check GM accounts file modifications." RETCODE);
  3495. else
  3496. login_log("- to check GM accounts file modifications every %d seconds." RETCODE, gm_account_filename_check_timer);
  3497. if (use_md5_passwds == 0)
  3498. login_log("- to save password in plain text." RETCODE);
  3499. else
  3500. login_log("- to save password with MD5 encrypting." RETCODE);
  3501. // not necessary to log the 'login_log_filename', we are inside :)
  3502. login_log("- with the unknown packets file name: '%s'." RETCODE, login_log_unknown_packets_filename);
  3503. if (save_unknown_packets)
  3504. login_log("- to SAVE all unkown packets." RETCODE);
  3505. else
  3506. login_log("- to SAVE only unkown packets sending by a char-server or a remote administration." RETCODE);
  3507. if (display_parse_login)
  3508. login_log("- to display normal parse packets on console." RETCODE);
  3509. else
  3510. login_log("- to NOT display normal parse packets on console." RETCODE);
  3511. if (display_parse_admin)
  3512. login_log("- to display administration parse packets on console." RETCODE);
  3513. else
  3514. login_log("- to NOT display administration parse packets on console." RETCODE);
  3515. if (display_parse_fromchar)
  3516. login_log("- to display char-server parse packets on console." RETCODE);
  3517. else
  3518. login_log("- to NOT display char-server parse packets on console." RETCODE);
  3519. if (min_level_to_connect == 0) // 0: all players, 1-99 at least gm level x
  3520. login_log("- with no minimum level for connection." RETCODE);
  3521. else if (min_level_to_connect == 99)
  3522. login_log("- to accept only GM with level 99." RETCODE);
  3523. else
  3524. login_log("- to accept only GM with level %d or more." RETCODE, min_level_to_connect);
  3525. if (add_to_unlimited_account)
  3526. login_log("- to authorize adjustment (with timeadd ladmin) on an unlimited account." RETCODE);
  3527. else
  3528. login_log("- to refuse adjustment (with timeadd ladmin) on an unlimited account. You must use timeset (ladmin command) before." RETCODE);
  3529. if (start_limited_time < 0)
  3530. login_log("- to create new accounts with an unlimited time." RETCODE);
  3531. else if (start_limited_time == 0)
  3532. login_log("- to create new accounts with a limited time: time of creation." RETCODE);
  3533. else
  3534. login_log("- to create new accounts with a limited time: time of creation + %d second(s)." RETCODE, start_limited_time);
  3535. if (check_ip_flag)
  3536. login_log("- with control of players IP between login-server and char-server." RETCODE);
  3537. else
  3538. login_log("- to not check players IP between login-server and char-server." RETCODE);
  3539. if (access_order == ACO_DENY_ALLOW) {
  3540. if (access_denynum == 0) {
  3541. login_log("- with the IP security order: 'deny,allow' (allow if not deny). You refuse no IP." RETCODE);
  3542. } else if (access_denynum == 1 && access_deny[0] == '\0') {
  3543. login_log("- with the IP security order: 'deny,allow' (allow if not deny). You refuse ALL IP." RETCODE);
  3544. } else {
  3545. login_log("- with the IP security order: 'deny,allow' (allow if not deny). Refused IP are:" RETCODE);
  3546. for(i = 0; i < access_denynum; i++)
  3547. login_log(" %s" RETCODE, (char *)(access_deny + i * ACO_STRSIZE));
  3548. }
  3549. } else if (access_order == ACO_ALLOW_DENY) {
  3550. if (access_allownum == 0) {
  3551. login_log("- with the IP security order: 'allow,deny' (deny if not allow). But, NO IP IS AUTHORISED!" RETCODE);
  3552. } else if (access_allownum == 1 && access_allow[0] == '\0') {
  3553. login_log("- with the IP security order: 'allow,deny' (deny if not allow). You authorise ALL IP." RETCODE);
  3554. } else {
  3555. login_log("- with the IP security order: 'allow,deny' (deny if not allow). Authorised IP are:" RETCODE);
  3556. for(i = 0; i < access_allownum; i++)
  3557. login_log(" %s" RETCODE, (char *)(access_allow + i * ACO_STRSIZE));
  3558. }
  3559. } else { // ACO_MUTUAL_FAILTURE
  3560. login_log("- with the IP security order: 'mutual-failture' (allow if in the allow list and not in the deny list)." RETCODE);
  3561. if (access_allownum == 0) {
  3562. login_log(" But, NO IP IS AUTHORISED!" RETCODE);
  3563. } else if (access_denynum == 1 && access_deny[0] == '\0') {
  3564. login_log(" But, you refuse ALL IP!" RETCODE);
  3565. } else {
  3566. if (access_allownum == 1 && access_allow[0] == '\0') {
  3567. login_log(" You authorise ALL IP." RETCODE);
  3568. } else {
  3569. login_log(" Authorised IP are:" RETCODE);
  3570. for(i = 0; i < access_allownum; i++)
  3571. login_log(" %s" RETCODE, (char *)(access_allow + i * ACO_STRSIZE));
  3572. }
  3573. login_log(" Refused IP are:" RETCODE);
  3574. for(i = 0; i < access_denynum; i++)
  3575. login_log(" %s" RETCODE, (char *)(access_deny + i * ACO_STRSIZE));
  3576. }
  3577. // dynamic password error ban
  3578. if (dynamic_pass_failure_ban == 0)
  3579. login_log("- with NO dynamic password error ban." RETCODE);
  3580. else {
  3581. printf("- with a dynamic password error ban:" RETCODE);
  3582. printf(" After %d invalid password in %d minutes" RETCODE, dynamic_pass_failure_ban_how_many, dynamic_pass_failure_ban_time);
  3583. printf(" IP is banned for %d minutes" RETCODE, dynamic_pass_failure_ban_how_long);
  3584. }
  3585. }
  3586. }
  3587. //-----------------------------------------------------
  3588. //I'm Alive Alert
  3589. //Used to output 'I'm Alive' every few seconds
  3590. //Intended to let frontends know if the app froze
  3591. //-----------------------------------------------------
  3592. int imalive_timer(int tid, unsigned int tick, int id, int data){
  3593. printf("I'm Alive\n");
  3594. return 0;
  3595. }
  3596. //-----------------------------------------------------
  3597. //Flush stdout
  3598. //stdout buffer needs flushed to be seen in GUI
  3599. //-----------------------------------------------------
  3600. int flush_timer(int tid, unsigned int tick, int id, int data){
  3601. fflush(stdout);
  3602. return 0;
  3603. }
  3604. //--------------------------------------
  3605. // Function called at exit of the server
  3606. //--------------------------------------
  3607. void do_final(void) {
  3608. int i, fd;
  3609. printf("Terminating...\n");
  3610. fflush(stdout);
  3611. mmo_auth_sync();
  3612. if(auth_dat) aFree(auth_dat);
  3613. if(gm_account_db) aFree(gm_account_db);
  3614. if(access_ladmin_allow) aFree(access_ladmin_allow);
  3615. if(access_allow) aFree(access_allow);
  3616. if(access_deny) aFree(access_deny);
  3617. for (i = 0; i < MAX_SERVERS; i++) {
  3618. if ((fd = server_fd[i]) >= 0) {
  3619. server_fd[i] = -1;
  3620. memset(&server[i], 0, sizeof(struct mmo_char_server));
  3621. close(fd);
  3622. delete_session(fd);
  3623. }
  3624. }
  3625. close(login_fd);
  3626. delete_session(login_fd);
  3627. exit_dbn();
  3628. timer_final();
  3629. login_log("----End of login-server (normal end with closing of all files)." RETCODE);
  3630. if(log_fp)
  3631. fclose(log_fp);
  3632. printf("Finished.\n");
  3633. }
  3634. //------------------------------
  3635. // Main function of login-server
  3636. //------------------------------
  3637. int do_init(int argc, char **argv) {
  3638. int i, j;
  3639. // read login-server configuration
  3640. login_config_read((argc > 1) ? argv[1] : LOGIN_CONF_NAME);
  3641. display_conf_warnings(); // not in login_config_read, because we can use 'import' option, and display same message twice or more
  3642. save_config_in_log(); // not before, because log file name can be changed
  3643. login_lan_config_read((argc > 1) ? argv[1] : LAN_CONF_NAME);
  3644. srand(time(NULL));
  3645. for(i = 0; i< AUTH_FIFO_SIZE; i++)
  3646. auth_fifo[i].delflag = 1;
  3647. for(i = 0; i < MAX_SERVERS; i++)
  3648. server_fd[i] = -1;
  3649. //gm_account_db = numdb_init();
  3650. gm_account_db = NULL;
  3651. GM_num = 0;
  3652. GM_max = 0;
  3653. mmo_auth_init();
  3654. read_gm_account();
  3655. // set_termfunc(mmo_auth_sync);
  3656. set_defaultparse(parse_login);
  3657. if (bind_ip_str[0] != '\0')
  3658. bind_ip = inet_addr(bind_ip_str);
  3659. else
  3660. bind_ip = INADDR_ANY;
  3661. //login_fd = make_listen_port(login_port);
  3662. login_fd = make_listen_bind(bind_ip,login_port);
  3663. if(anti_freeze_enable > 0) {
  3664. add_timer_func_list(char_anti_freeze_system, "char_anti_freeze_system");
  3665. i = add_timer_interval(gettick() + 1000, char_anti_freeze_system, 0, 0, ANTI_FREEZE_INTERVAL * 1000);
  3666. }
  3667. add_timer_func_list(check_auth_sync, "check_auth_sync");
  3668. i = add_timer_interval(gettick() + 60000, check_auth_sync, 0, 0, 60000); // every 60 sec we check if we must save accounts file (only if necessary to save)
  3669. // add timer to check GM accounts file modification
  3670. j = gm_account_filename_check_timer;
  3671. if (j == 0) // if we would not to check, we check every 60 sec, just to have timer (if we change timer, is was not necessary to check if timer already exists)
  3672. j = 60;
  3673. //Added for Mugendais I'm Alive mod
  3674. if(imalive_on)
  3675. add_timer_interval(gettick()+10, imalive_timer,0,0,imalive_time*1000);
  3676. //Added by Mugendai for GUI support
  3677. if(flush_on)
  3678. add_timer_interval(gettick()+10, flush_timer,0,0,flush_time);
  3679. add_timer_func_list(check_GM_file, "check_GM_file");
  3680. i = add_timer_interval(gettick() + j * 1000, check_GM_file, 0, 0, j * 1000); // every x sec we check if gm file has been changed
  3681. if(console) {
  3682. set_defaultconsoleparse(parse_console);
  3683. start_console();
  3684. }
  3685. login_log("The login-server is ready (Server is listening on the port %d)." RETCODE, login_port);
  3686. printf("The login-server is \033[1;32mready\033[0m (Server is listening on the port %d).\n\n", login_port);
  3687. atexit(do_final);
  3688. return 0;
  3689. }