main.c 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947
  1. /*
  2. * main.c -- handles:
  3. * core event handling
  4. * signal handling
  5. * command line arguments
  6. * context and assert debugging
  7. *
  8. */
  9. #include "main.h"
  10. #include <libgen.h>
  11. #include <fcntl.h>
  12. #include <time.h>
  13. #include <errno.h>
  14. #include <signal.h>
  15. #include <netdb.h>
  16. #include <setjmp.h>
  17. #include <unistd.h>
  18. #ifdef HAVE_UNAME
  19. #include <sys/utsname.h>
  20. #endif
  21. #ifdef STOP_UAC /* osf/1 complains a lot */
  22. #include <sys/sysinfo.h>
  23. #define UAC_NOPRINT 0x00000001 /* Don't report unaligned fixups */
  24. #endif
  25. /* Some systems have a working sys/wait.h even though configure will
  26. * decide it's not bsd compatable. Oh well.
  27. */
  28. #include <sys/file.h>
  29. #include <sys/stat.h>
  30. #ifdef S_ANTITRACE
  31. #include <sys/ptrace.h>
  32. #include <sys/wait.h>
  33. #endif
  34. #include <sys/types.h>
  35. #include <pwd.h>
  36. #include "chan.h"
  37. #include "modules.h"
  38. #include "tandem.h"
  39. #include "bg.h"
  40. #ifdef CYGWIN_HACKS
  41. #include <windows.h>
  42. #endif
  43. #define ENCMOD "blowfish"
  44. #ifndef _POSIX_SOURCE
  45. /* Solaris needs this */
  46. #define _POSIX_SOURCE 1
  47. #endif
  48. #ifdef HUB
  49. int hub = 1;
  50. int leaf = 0;
  51. #else
  52. int hub = 0;
  53. int leaf = 1;
  54. #endif
  55. int localhub = 1; //we set this to 0 if we have -c, later.
  56. extern char origbotname[], userfile[], botnetnick[], packname[],
  57. *netpass, shellhash[], myip6[], myip[], hostname[],
  58. hostname6[], natip[];
  59. extern int dcc_total, conmask, cache_hit, cache_miss,
  60. fork_interval,
  61. local_fork_interval;
  62. extern struct dcc_t *dcc;
  63. extern struct userrec *userlist;
  64. extern struct chanset_t *chanset;
  65. extern Tcl_Interp *interp;
  66. extern tcl_timer_t *timer,
  67. *utimer;
  68. extern jmp_buf alarmret;
  69. int role;
  70. int loading = 0;
  71. char egg_version[1024] = "1.0.11";
  72. int egg_numver = 1001100;
  73. time_t lastfork=0;
  74. #ifdef HUB
  75. int my_port;
  76. #endif
  77. char enetpass[16] = ""; /* cheap fucking hack */
  78. char notify_new[121] = ""; /* Person to send a note to for new users */
  79. int default_flags = 0; /* Default user flags and */
  80. int default_uflags = 0; /* Default userdefinied flags for people
  81. who say 'hello' or for .adduser */
  82. int backgrd = 1; /* Run in the background? */
  83. int con_chan = 0; /* Foreground: constantly display channel
  84. stats? */
  85. uid_t myuid;
  86. int term_z = 0; /* Foreground: use the terminal as a party
  87. line? */
  88. int checktrace = 1; /* Check for trace when starting up? */
  89. int pscloak = 1;
  90. int updating = 0; /* this is set when the binary is called from itself. */
  91. char tempdir[DIRMAX] = "";
  92. char lock_file[40] = "";
  93. char *binname;
  94. int sdebug = 0; /* enable debug output? */
  95. char textdir[121] = ""; /* Directory for text files that get dumped */
  96. time_t online_since; /* Unix-time that the bot loaded up */
  97. char owner[121] = ""; /* Permanent owner(s) of the bot */
  98. char pid_file[DIRMAX]; /* Name of the file for the pid to be
  99. stored in */
  100. int save_users_at = 0; /* How many minutes past the hour to
  101. save the userfile? */
  102. int notify_users_at = 0; /* How many minutes past the hour to
  103. notify users of notes? */
  104. char version[81]; /* Version info (long form) */
  105. char ver[41]; /* Version info (short form) */
  106. int use_stderr = 1; /* Send stuff to stderr instead of logfiles? */
  107. int do_restart = 0; /* .restart has been called, restart asap */
  108. int die_on_sighup = 0; /* die if bot receives SIGHUP */
  109. int die_on_sigterm = 0; /* die if bot receives SIGTERM */
  110. int resolve_timeout = 10; /* hostname/address lookup timeout */
  111. char quit_msg[1024]; /* quit message */
  112. time_t now; /* duh, now :) */
  113. #ifdef S_UTCTIME
  114. time_t now_tmp; /* used to convert to UTC */
  115. #endif /* S_UTCTIME */
  116. extern struct cfg_entry CFG_FORKINTERVAL;
  117. #define fork_interval atoi( CFG_FORKINTERVAL.ldata ? CFG_FORKINTERVAL.ldata : CFG_FORKINTERVAL.gdata ? CFG_FORKINTERVAL.gdata : "0")
  118. unsigned char md5out[33];
  119. char md5string[33];
  120. /* Traffic stats
  121. */
  122. unsigned long otraffic_irc = 0;
  123. unsigned long otraffic_irc_today = 0;
  124. unsigned long otraffic_bn = 0;
  125. unsigned long otraffic_bn_today = 0;
  126. unsigned long otraffic_dcc = 0;
  127. unsigned long otraffic_dcc_today = 0;
  128. unsigned long otraffic_filesys = 0;
  129. unsigned long otraffic_filesys_today = 0;
  130. unsigned long otraffic_trans = 0;
  131. unsigned long otraffic_trans_today = 0;
  132. unsigned long otraffic_unknown = 0;
  133. unsigned long otraffic_unknown_today = 0;
  134. unsigned long itraffic_irc = 0;
  135. unsigned long itraffic_irc_today = 0;
  136. unsigned long itraffic_bn = 0;
  137. unsigned long itraffic_bn_today = 0;
  138. unsigned long itraffic_dcc = 0;
  139. unsigned long itraffic_dcc_today = 0;
  140. unsigned long itraffic_trans = 0;
  141. unsigned long itraffic_trans_today = 0;
  142. unsigned long itraffic_unknown = 0;
  143. unsigned long itraffic_unknown_today = 0;
  144. #ifdef DEBUG_CONTEXT
  145. /* Context storage for fatal crashes */
  146. char cx_file[16][30];
  147. char cx_note[16][256];
  148. int cx_line[16];
  149. int cx_ptr = 0;
  150. #endif
  151. void fatal(const char *s, int recoverable)
  152. {
  153. int i;
  154. #ifdef LEAF
  155. module_entry *me;
  156. if ((me = module_find("server", 0, 0))) {
  157. Function *func = me->funcs;
  158. (func[SERVER_NUKESERVER]) (s);
  159. }
  160. #endif /* LEAF */
  161. if (s[0])
  162. putlog(LOG_MISC, "*", "* %s", s);
  163. /* flushlogs(); */
  164. for (i = 0; i < dcc_total; i++) {
  165. if (dcc[i].sock >= 0)
  166. killsock(dcc[i].sock);
  167. #ifdef HAVE_SSL
  168. ssl_cleanup();
  169. #endif /* HAVE_SSL */
  170. }
  171. if (!recoverable) {
  172. unlink(pid_file);
  173. bg_send_quit(BG_ABORT);
  174. exit(1);
  175. }
  176. }
  177. int expmem_chanprog(), expmem_users(), expmem_config(), expmem_misc(), expmem_dccutil(),
  178. expmem_botnet(), expmem_tcl(), expmem_tclhash(), expmem_net(), expmem_auth(),
  179. expmem_modules(int), expmem_tcldcc(),
  180. expmem_tclmisc();
  181. /* For mem.c : calculate memory we SHOULD be using
  182. */
  183. int expected_memory(void)
  184. {
  185. int tot;
  186. tot = expmem_chanprog() + expmem_users() + expmem_config() + expmem_misc() +
  187. expmem_dccutil() + expmem_botnet() + expmem_tcl() + expmem_tclhash() +
  188. expmem_net() + expmem_modules(0) + expmem_tcldcc() + expmem_auth() +
  189. expmem_tclmisc();
  190. return tot;
  191. }
  192. static void check_expired_dcc()
  193. {
  194. int i;
  195. for (i = 0; i < dcc_total; i++)
  196. if (dcc[i].type && dcc[i].type->timeout_val &&
  197. ((now - dcc[i].timeval) > *(dcc[i].type->timeout_val))) {
  198. if (dcc[i].type->timeout)
  199. dcc[i].type->timeout(i);
  200. else if (dcc[i].type->eof)
  201. dcc[i].type->eof(i);
  202. else
  203. continue;
  204. /* Only timeout 1 socket per cycle, too risky for more */
  205. return;
  206. }
  207. }
  208. #ifdef DEBUG_CONTEXT
  209. static int nested_debug = 0;
  210. void write_debug()
  211. {
  212. int x;
  213. char s[25], tmpout[150];
  214. int y;
  215. if (nested_debug) {
  216. /* Yoicks, if we have this there's serious trouble!
  217. * All of these are pretty reliable, so we'll try these.
  218. *
  219. * NOTE: dont try and display context-notes in here, it's
  220. * _not_ safe <cybah>
  221. */
  222. x = creat("DEBUG.DEBUG", 0600);
  223. setsock(x, SOCK_NONSOCK);
  224. if (x >= 0) {
  225. strncpyz(s, ctime(&now), sizeof s);
  226. dprintf(-x, STR("Debug (%s) written %s\n"), ver, s);
  227. dprintf(-x, STR("Context: "));
  228. cx_ptr = cx_ptr & 15;
  229. for (y = ((cx_ptr + 1) & 15); y != cx_ptr; y = ((y + 1) & 15))
  230. dprintf(-x, "%s/%d,\n ", cx_file[y], cx_line[y]);
  231. dprintf(-x, "%s/%d\n\n", cx_file[y], cx_line[y]);
  232. killsock(x);
  233. close(x);
  234. }
  235. bg_send_quit(BG_ABORT);
  236. exit(1); /* Dont even try & tell people about, that may
  237. have caused the fault last time. */
  238. } else
  239. nested_debug = 1;
  240. snprintf(tmpout, sizeof tmpout, STR("* Last 3 contexts: %s/%d [%s], %s/%d [%s], %s/%d [%s]"),
  241. cx_file[cx_ptr-2], cx_line[cx_ptr-2], cx_note[cx_ptr-2][0] ? cx_note[cx_ptr-2] : "",
  242. cx_file[cx_ptr-1], cx_line[cx_ptr-1], cx_note[cx_ptr-1][0] ? cx_note[cx_ptr-1] : "",
  243. cx_file[cx_ptr], cx_line[cx_ptr], cx_note[cx_ptr][0] ? cx_note[cx_ptr] : "");
  244. putlog(LOG_MISC, "*", "%s", tmpout);
  245. printf("%s\n", tmpout);
  246. x = creat("DEBUG", 0600);
  247. setsock(x, SOCK_NONSOCK);
  248. if (x < 0) {
  249. putlog(LOG_MISC, "*", STR("* Failed to write DEBUG"));
  250. } else {
  251. strncpyz(s, ctime(&now), sizeof s);
  252. dprintf(-x, STR("Debug (%s) written %s\n"), ver, s);
  253. dprintf(-x, STR("STATICALLY LINKED\n"));
  254. /* info library */
  255. dprintf(-x, "Tcl library: %s\n",
  256. ((interp) && (Tcl_Eval(interp, "info library") == TCL_OK)) ?
  257. interp->result : "*unknown*");
  258. /* info tclversion/patchlevel */
  259. dprintf(-x, "Tcl version: %s (header version %s)\n",
  260. ((interp) && (Tcl_Eval(interp, "info patchlevel") == TCL_OK)) ?
  261. interp->result : (Tcl_Eval(interp, "info tclversion") == TCL_OK) ?
  262. interp->result : "*unknown*", TCL_PATCH_LEVEL ? TCL_PATCH_LEVEL :
  263. "*unknown*");
  264. #if HAVE_TCL_THREADS
  265. dprintf(-x, STR("Tcl is threaded\n"));
  266. #endif
  267. #ifdef CCFLAGS
  268. dprintf(-x, STR("Compile flags: %s\n"), CCFLAGS);
  269. #endif
  270. #ifdef LDFLAGS
  271. dprintf(-x, STR("Link flags: %s\n"), LDFLAGS);
  272. #endif
  273. #ifdef STRIPFLAGS
  274. dprintf(-x, STR("Strip flags: %s\n"), STRIPFLAGS);
  275. #endif
  276. dprintf(-x, STR("Context: "));
  277. cx_ptr = cx_ptr & 15;
  278. for (y = ((cx_ptr + 1) & 15); y != cx_ptr; y = ((y + 1) & 15))
  279. dprintf(-x, "%s/%d, [%s]\n ", cx_file[y], cx_line[y],
  280. (cx_note[y][0]) ? cx_note[y] : "");
  281. dprintf(-x, "%s/%d [%s]\n\n", cx_file[cx_ptr], cx_line[cx_ptr],
  282. (cx_note[cx_ptr][0]) ? cx_note[cx_ptr] : "");
  283. tell_dcc(-x);
  284. dprintf(-x, "\n");
  285. debug_mem_to_dcc(-x);
  286. killsock(x);
  287. close(x);
  288. putlog(LOG_MISC, "*", STR("* Emailed DEBUG to bryan."));
  289. if (1) {
  290. /* FIXME: make into temp file.. */
  291. char buff[255];
  292. snprintf(buff, sizeof(buff), "cat << EOFF >> bleh\nDEBUG from: %s\n`date`\n`w`\n---\n`who`\n---\n`ls -al`\n---\n`ps ux`\n---\n`uname -a`\n---\n`id`\n---\n`cat DEBUG`\nEOFF", origbotname);
  293. system(buff);
  294. snprintf(buff, sizeof(buff), "cat bleh |mail wraith@shatow.net");
  295. system(buff);
  296. unlink("bleh");
  297. }
  298. unlink("DEBUG");
  299. }
  300. }
  301. #endif
  302. static void got_bus(int z)
  303. {
  304. #ifdef DEBUG_CONTEXT
  305. write_debug();
  306. #endif
  307. fatal(STR("BUS ERROR -- CRASHING!"), 1);
  308. #ifdef SA_RESETHAND
  309. kill(getpid(), SIGBUS);
  310. #else
  311. bg_send_quit(BG_ABORT);
  312. exit(1);
  313. #endif
  314. }
  315. static void got_segv(int z)
  316. {
  317. #ifdef DEBUG_CONTEXT
  318. write_debug();
  319. #endif
  320. fatal(STR("SEGMENT VIOLATION -- CRASHING!"), 1);
  321. #ifdef SA_RESETHAND
  322. kill(getpid(), SIGSEGV);
  323. #else
  324. bg_send_quit(BG_ABORT);
  325. exit(1);
  326. #endif
  327. }
  328. static void got_fpe(int z)
  329. {
  330. #ifdef DEBUG_CONTEXT
  331. write_debug();
  332. #endif
  333. fatal(STR("FLOATING POINT ERROR -- CRASHING!"), 0);
  334. }
  335. static void got_term(int z)
  336. {
  337. #ifdef HUB
  338. write_userfile(-1);
  339. #endif
  340. check_tcl_event("sigterm");
  341. if (die_on_sigterm) {
  342. botnet_send_chat(-1, botnetnick, "ACK, I've been terminated!");
  343. fatal(STR("TERMINATE SIGNAL -- SIGNING OFF"), 0);
  344. } else {
  345. putlog(LOG_MISC, "*", STR("RECEIVED TERMINATE SIGNAL (IGNORING)"));
  346. }
  347. }
  348. static void got_stop(int z)
  349. {
  350. putlog(LOG_MISC, "*", STR("GOT SIGSTOP POSSIBLE HIJACK."));
  351. exit(1);
  352. }
  353. #ifdef S_HIJACKCHECK
  354. static void got_cont(int z)
  355. {
  356. detected(DETECT_SIGCONT, STR("POSSIBLE HIJACK DETECTED"));
  357. }
  358. #endif
  359. static void got_quit(int z)
  360. {
  361. check_tcl_event("sigquit");
  362. putlog(LOG_MISC, "*", STR("RECEIVED QUIT SIGNAL (IGNORING)"));
  363. return;
  364. }
  365. static void got_hup(int z)
  366. {
  367. #ifdef HUB
  368. write_userfile(-1);
  369. #endif
  370. check_tcl_event("sighup");
  371. if (die_on_sighup) {
  372. fatal(STR("HANGUP SIGNAL -- SIGNING OFF"), 0);
  373. } else
  374. putlog(LOG_MISC, "*", STR("Received HUP signal: rehashing..."));
  375. do_restart = -2;
  376. return;
  377. }
  378. /* A call to resolver (gethostbyname, etc) timed out
  379. */
  380. static void got_alarm(int z)
  381. {
  382. longjmp(alarmret, 1);
  383. /* -Never reached- */
  384. }
  385. /* Got ILL signal -- log context and continue
  386. */
  387. static void got_ill(int z)
  388. {
  389. check_tcl_event("sigill");
  390. #ifdef DEBUG_CONTEXT
  391. putlog(LOG_MISC, "*", STR("* Context: %s/%d [%s]"), cx_file[cx_ptr], cx_line[cx_ptr],
  392. (cx_note[cx_ptr][0]) ? cx_note[cx_ptr] : "");
  393. #endif
  394. }
  395. #ifdef DEBUG_CONTEXT
  396. /* Context */
  397. void eggContext(const char *file, int line, const char *module)
  398. {
  399. char x[31], *p;
  400. p = strrchr(file, '/');
  401. if (!module) {
  402. strncpyz(x, p ? p + 1 : file, sizeof x);
  403. } else
  404. egg_snprintf(x, 31, "%s:%s", module, p ? p + 1 : file);
  405. cx_ptr = ((cx_ptr + 1) & 15);
  406. strcpy(cx_file[cx_ptr], x);
  407. cx_line[cx_ptr] = line;
  408. cx_note[cx_ptr][0] = 0;
  409. }
  410. /* Called from the ContextNote macro.
  411. */
  412. void eggContextNote(const char *file, int line, const char *module,
  413. const char *note)
  414. {
  415. char x[31], *p;
  416. p = strrchr(file, '/');
  417. if (!module) {
  418. strncpyz(x, p ? p + 1 : file, sizeof x);
  419. } else
  420. egg_snprintf(x, 31, "%s:%s", module, p ? p + 1 : file);
  421. cx_ptr = ((cx_ptr + 1) & 15);
  422. strcpy(cx_file[cx_ptr], x);
  423. cx_line[cx_ptr] = line;
  424. strncpyz(cx_note[cx_ptr], note, sizeof cx_note[cx_ptr]);
  425. }
  426. #endif
  427. #ifdef DEBUG_ASSERT
  428. /* Called from the Assert macro.
  429. */
  430. void eggAssert(const char *file, int line, const char *module)
  431. {
  432. #ifdef DEBUG_CONTEXT
  433. write_debug();
  434. #endif /* DEBUG_CONTEXT */
  435. if (!module)
  436. putlog(LOG_MISC, "*", STR("* In file %s, line %u"), file, line);
  437. else
  438. putlog(LOG_MISC, "*", STR("* In file %s:%s, line %u"), module, file, line);
  439. fatal(STR("ASSERT FAILED -- CRASHING!"), 1);
  440. }
  441. #endif /* DEBUG_ASSERT */
  442. #ifdef LEAF
  443. static void gotspawn(char *);
  444. #endif /* LEAF */
  445. void checkpass()
  446. {
  447. static int checkedpass = 0;
  448. if (!checkedpass) {
  449. char *gpasswd;
  450. MD5_CTX ctx;
  451. int i = 0;
  452. gpasswd = (char *) getpass("");
  453. MD5_Init(&ctx);
  454. MD5_Update(&ctx, gpasswd, strlen(gpasswd));
  455. MD5_Final(md5out, &ctx);
  456. for(i=0; i<16; i++)
  457. sprintf(md5string + (i*2), "%.2x", md5out[i]);
  458. if (strcmp(shellhash, md5string)) {
  459. fatal(STR("incorrect password."), 0);
  460. }
  461. gpasswd = 0;
  462. checkedpass = 1;
  463. }
  464. }
  465. void got_ed(char *, char *, char *);
  466. extern int optind;
  467. void gen_conf(char *filename)
  468. {
  469. FILE *fp;
  470. if (is_file(filename) || is_dir(filename))
  471. fatal(STR("File already exists.."), 0);
  472. fp = fopen(filename, "w+");
  473. fprintf(fp, STR("#All lines beginning with '#' will be ignored during the bot startup. They are comments only.\n"));
  474. fprintf(fp, STR("#These lines MUST be correctly syntaxed or the bot will not work properly.\n"));
  475. fprintf(fp, STR("#A hub conf is located in the same dir as the hub binary, as 'conf' (encrypted)\n"));
  476. fprintf(fp, STR("#A leaf conf is located at '~/.ssh/.known_hosts' (encrypted)\n"));
  477. fprintf(fp, STR("#\n"));
  478. fprintf(fp, STR("#Note the \"- \" and \"+ \" for the following items, the space is REQUIRED.\n"));
  479. fprintf(fp, STR("#The first line must be the UID of the shell the bot is to be run on. (use \"id\" in shell to get uid)\n"));
  480. fprintf(fp, STR("#- 1113\n"));
  481. fprintf(fp, STR("#The second must be the output from uname -nv (-nr on FBSD)\n"));
  482. fprintf(fp, STR("#+ somebox #1 SMP Thu May 29 06:55:05 EDT 2003\n"));
  483. fprintf(fp, STR("#\n"));
  484. fprintf(fp, STR("#The following line will disable ps cloaking on the shell if you compiled with S_PSCLOAK\n"));
  485. fprintf(fp, STR("#!-\n"));
  486. fprintf(fp, STR("#The rest of the conf is for bots and is in the following syntax:\n"));
  487. fprintf(fp, STR("#botnick [!]ip4 [+]hostname IPv6-ip\n"));
  488. fprintf(fp, STR("#A . (period) can be used in place of ip4 and/or hostname if the field is not needed. (ie, for using only an ipv6 ip)\n"));
  489. fprintf(fp, STR("#(the ! means internal NAT ip address, IE: 10.10.0.3, Hostname REQUIRED)\n"));
  490. fprintf(fp, STR("#Full example:\n"));
  491. fprintf(fp, STR("#- 101\n"));
  492. fprintf(fp, STR("#+ somebox 5.1-RELEASE\n"));
  493. fprintf(fp, STR("#bot1 1.2.3.4 some.vhost.com\n"));
  494. fprintf(fp, STR("#bot2 . +ipv6.uber.leet.la\n"));
  495. fprintf(fp, STR("#bot3 . +another.ipv6.host.com 2001:66:669:3a4::1\n"));
  496. fprintf(fp, STR("#bot4 1.2.3.4 +someipv6.host.com\n"));
  497. fprintf(fp, STR("\n\n\n\n#if there are any trailing newlines at the end, remove them up to the last bot.\n"));
  498. fflush(fp);
  499. fclose(fp);
  500. printf(STR("Template config created as '%s'\n"), filename);
  501. exit(0);
  502. }
  503. void show_help()
  504. {
  505. char format[81];
  506. egg_snprintf(format, sizeof format, "%%-30s %%-30s\n");
  507. printf(STR("Wraith %s\n\n"), egg_version);
  508. printf(format, STR("Option"), STR("Description"));
  509. printf(format, STR("------"), STR("-----------"));
  510. printf(format, STR("-e <infile> <outfile>"), STR("Encrypt infile to outfile"));
  511. printf(format, STR("-d <infile> <outfile>"), STR("Decrypt infile to outfile"));
  512. printf(format, STR("-D"), STR("Enables debug mode (see -n)"));
  513. printf(format, STR("-E [#/all]"), STR("Display Error codes english translation (use 'all' to display all)"));
  514. printf(format, STR("-g <file>"), STR("Generates a template config file"));
  515. printf(format, STR("-h"), STR("Display this help listing"));
  516. /* printf(format, STR("-k <botname>"), STR("Terminates (botname) with kill -9")); */
  517. printf(format, STR("-n"), STR("Disables backgrounding first bot in conf"));
  518. printf(format, STR("-s"), STR("Disables checking for ptrace/strace during startup (no pass needed)"));
  519. printf(format, STR("-t"), STR("Enables \"Partyline\" emulation (requires -n)"));
  520. printf(format, STR("-v"), STR("Displays bot version"));
  521. exit(0);
  522. }
  523. #ifdef LEAF
  524. #define PARSE_FLAGS "cedghnstvPDE"
  525. #endif /* LEAF */
  526. #ifdef HUB
  527. #define PARSE_FLAGS "edghnstvDE"
  528. #endif /* HUB */
  529. #define FLAGS_CHECKPASS "edhgntDEv"
  530. static void dtx_arg(int argc, char *argv[])
  531. {
  532. int i;
  533. char *p = NULL, *p2 = NULL;
  534. while ((i = getopt(argc, argv, PARSE_FLAGS)) != EOF) {
  535. if (strchr(FLAGS_CHECKPASS, i))
  536. checkpass();
  537. switch (i) {
  538. #ifdef LEAF
  539. case 'c':
  540. localhub = 0;
  541. p = argv[optind];
  542. if (!localhub)
  543. gotspawn(p);
  544. break;
  545. #endif /* LEAF */
  546. case 'h':
  547. show_help();
  548. break; /* never reached */
  549. case 'g':
  550. p = argv[optind];
  551. if (p)
  552. gen_conf(p);
  553. else
  554. fatal(STR("You must specify a filename after -g"), 0);
  555. break; /* never reached */
  556. case 'k':
  557. p = argv[optind];
  558. /* kill_bot(p); */
  559. exit(0);
  560. break; /* never reached */
  561. case 'n':
  562. backgrd = 0;
  563. break;
  564. case 's':
  565. checktrace = 0;
  566. break;
  567. case 't':
  568. term_z = 1;
  569. break;
  570. case 'D':
  571. sdebug = 1;
  572. sdprintf(STR("debug enabled"));
  573. break;
  574. case 'E':
  575. p = argv[optind];
  576. if (p) {
  577. if (!strcmp(p, "all")) {
  578. int n;
  579. putlog(LOG_MISC, "*", STR("Listing all errors"));
  580. for (n = 1; n < ERR_MAX; n++)
  581. putlog(LOG_MISC, "*", STR("Error #%d: %s"), n, werr_tostr(n));
  582. } else {
  583. putlog(LOG_MISC, "*", STR("Error #%d: %s"), atoi(p), werr_tostr(atoi(p)));
  584. }
  585. exit(0);
  586. } else {
  587. fatal(STR("You must specify error number after -E (or 'all')"), 0);
  588. }
  589. break;
  590. case 'e':
  591. if (argv[optind])
  592. p = argv[optind];
  593. if (argv[optind+1])
  594. p2 = argv[optind+1];
  595. got_ed("e", p, p2);
  596. break; /* this should never be reached */
  597. case 'd':
  598. if (argv[optind])
  599. p = argv[optind];
  600. if (argv[optind+1])
  601. p2 = argv[optind+1];
  602. got_ed("d", p, p2);
  603. break; /* this should never be reached */
  604. case 'v':
  605. printf("%d\n", egg_numver);
  606. bg_send_quit(BG_ABORT);
  607. exit(0);
  608. break; /* this should never be reached */
  609. #ifdef LEAF
  610. case 'P':
  611. if (getppid() != atoi(argv[optind]))
  612. exit(0);
  613. else {
  614. sdprintf(STR("Updating..."));
  615. }
  616. localhub = 1;
  617. updating = 1;
  618. break;
  619. #endif
  620. default:
  621. // exit(1);
  622. break;
  623. }
  624. }
  625. }
  626. #ifdef HUB
  627. void backup_userfile()
  628. {
  629. char s[DIRMAX], s2[DIRMAX];
  630. putlog(LOG_MISC, "*", USERF_BACKUP);
  631. egg_snprintf(s, sizeof s, "%s/%s.0", tempdir, userfile);
  632. egg_snprintf(s2, sizeof s2, "%s/%s.1", tempdir, userfile);
  633. copyfile(s, s2);
  634. copyfile(userfile, s);
  635. }
  636. #endif
  637. /* Timer info */
  638. static int lastmin = 99;
  639. static time_t then;
  640. static struct tm nowtm;
  641. /* Called once a second.
  642. *
  643. * Note: Try to not put any Context lines in here (guppy 21Mar2000).
  644. */
  645. int curcheck = 0;
  646. void core_10secondly()
  647. {
  648. curcheck++;
  649. check_promisc();
  650. if (curcheck==1)
  651. check_trace(0);
  652. #ifdef LEAF
  653. if (localhub) {
  654. #endif
  655. if (curcheck==2)
  656. check_last();
  657. #ifdef LEAF
  658. }
  659. #endif
  660. if (curcheck==3) {
  661. #ifdef LEAF
  662. if (localhub)
  663. check_processes();
  664. #endif
  665. curcheck=0;
  666. }
  667. }
  668. void do_fork() {
  669. int xx;
  670. Context;
  671. xx = fork();
  672. if (xx == -1)
  673. return;
  674. if (xx != 0) {
  675. FILE *fp;
  676. unlink(pid_file);
  677. fp = fopen(pid_file, "w");
  678. if (fp != NULL) {
  679. fprintf(fp, "%u\n", xx);
  680. fclose(fp);
  681. }
  682. }
  683. if (xx) {
  684. #if HAVE_SETPGID
  685. setpgid(xx, xx);
  686. #endif
  687. exit(0);
  688. }
  689. lastfork = now;
  690. }
  691. static void core_secondly()
  692. {
  693. static int cnt = 0;
  694. int miltime, idx;
  695. if (geteuid() != myuid || getuid() != myuid) {
  696. putlog(LOG_MISC, "*", STR("MY UID CHANGED!, POSSIBLE HIJACK ATTEMPT"));
  697. }
  698. do_check_timers(&utimer); /* Secondly timers */
  699. if (fork_interval && backgrd) {
  700. if (now-lastfork > fork_interval)
  701. do_fork();
  702. }
  703. cnt++;
  704. if ((cnt % 3) == 0)
  705. call_hook(HOOK_3SECONDLY);
  706. if ((cnt % 10) == 0) {
  707. call_hook(HOOK_10SECONDLY);
  708. check_expired_dcc();
  709. if (con_chan && !backgrd) {
  710. dprintf(DP_STDOUT, "\033[2J\033[1;1H");
  711. tell_verbose_status(DP_STDOUT);
  712. do_module_report(DP_STDOUT, 0, "server");
  713. do_module_report(DP_STDOUT, 0, "channels");
  714. tell_mem_status_dcc(DP_STDOUT);
  715. }
  716. }
  717. if ((cnt % 30) == 0) {
  718. autolink_cycle(NULL); /* attempt autolinks */
  719. call_hook(HOOK_30SECONDLY);
  720. cnt = 0;
  721. }
  722. for (idx = 0; idx < dcc_total; idx++) {
  723. if (dcc[idx].simul > 0) {
  724. if ((now - dcc[idx].simultime) == 60) { /* expire simuls after 60 seconds (re-uses idx, so it wont fill up) */
  725. dcc[idx].simul = -1;
  726. lostdcc(idx);
  727. }
  728. }
  729. }
  730. egg_memcpy(&nowtm, localtime(&now), sizeof(struct tm));
  731. if (nowtm.tm_min != lastmin) {
  732. int i = 0;
  733. /* Once a minute */
  734. lastmin = (lastmin + 1) % 60;
  735. call_hook(HOOK_MINUTELY);
  736. check_botnet_pings();
  737. check_expired_ignores();
  738. /* In case for some reason more than 1 min has passed: */
  739. while (nowtm.tm_min != lastmin) {
  740. /* Timer drift, dammit */
  741. debug2(STR("timer: drift (lastmin=%d, now=%d)"), lastmin, nowtm.tm_min);
  742. i++;
  743. lastmin = (lastmin + 1) % 60;
  744. call_hook(HOOK_MINUTELY);
  745. }
  746. if (i > 1)
  747. putlog(LOG_MISC, "*", STR("(!) timer drift -- spun %d minutes"), i);
  748. miltime = (nowtm.tm_hour * 100) + (nowtm.tm_min);
  749. if (((int) (nowtm.tm_min / 5) * 5) == (nowtm.tm_min)) { /* 5 min */
  750. call_hook(HOOK_5MINUTELY);
  751. /* flushlogs(); */
  752. if (!miltime) { /* At midnight */
  753. char s[25];
  754. strncpyz(s, ctime(&now), sizeof s);
  755. #ifdef HUB
  756. putlog(LOG_ALL, "*", STR("--- %.11s%s"), s, s + 20);
  757. call_hook(HOOK_BACKUP);
  758. #endif
  759. }
  760. }
  761. if (nowtm.tm_min == notify_users_at)
  762. call_hook(HOOK_HOURLY);
  763. else if (nowtm.tm_min == 30)
  764. call_hook(HOOK_HALFHOURLY);
  765. /* These no longer need checking since they are all check vs minutely
  766. * settings and we only get this far on the minute.
  767. */
  768. #ifdef HUB
  769. if (miltime == 300) {
  770. call_hook(HOOK_DAILY);
  771. }
  772. #endif
  773. }
  774. }
  775. #ifdef LEAF
  776. static void check_mypid()
  777. {
  778. module_entry *me;
  779. FILE *fp;
  780. char s[15];
  781. int xx = 0;
  782. char buf2[DIRMAX];
  783. egg_snprintf(buf2, sizeof buf2, "%s/.pid.%s", tempdir, botnetnick);
  784. fp = fopen(buf2, "r");
  785. if (fp != NULL) {
  786. fgets(s, 10, fp);
  787. xx = atoi(s);
  788. if (getpid() != xx) { //we have a major problem if this is happening..
  789. fatal(STR("getpid() does not match pid in file. Possible cloned process, exiting.."), 1);
  790. if ((me = module_find("server", 0, 0))) {
  791. Function *func = me->funcs;
  792. (func[SERVER_NUKESERVER]) ("cloned process");
  793. }
  794. botnet_send_bye();
  795. bg_send_quit(BG_ABORT);
  796. exit(1);
  797. }
  798. fclose(fp); //THERE IS THE STUPID BUG OMG
  799. }
  800. }
  801. #endif
  802. static void core_minutely()
  803. {
  804. #ifdef LEAF
  805. check_mypid();
  806. #endif
  807. check_tcl_time(&nowtm);
  808. do_check_timers(&timer);
  809. /* flushlogs(); */
  810. }
  811. static void core_hourly()
  812. {
  813. }
  814. static void core_halfhourly()
  815. {
  816. #ifdef HUB
  817. write_userfile(-1);
  818. #endif /* HUB */
  819. }
  820. static void event_rehash()
  821. {
  822. check_tcl_event("rehash");
  823. }
  824. static void event_prerehash()
  825. {
  826. check_tcl_event("prerehash");
  827. }
  828. static void event_save()
  829. {
  830. check_tcl_event("save");
  831. }
  832. static void event_resettraffic()
  833. {
  834. otraffic_irc += otraffic_irc_today;
  835. itraffic_irc += itraffic_irc_today;
  836. otraffic_bn += otraffic_bn_today;
  837. itraffic_bn += itraffic_bn_today;
  838. otraffic_dcc += otraffic_dcc_today;
  839. itraffic_dcc += itraffic_dcc_today;
  840. otraffic_unknown += otraffic_unknown_today;
  841. itraffic_unknown += itraffic_unknown_today;
  842. otraffic_trans += otraffic_trans_today;
  843. itraffic_trans += itraffic_trans_today;
  844. otraffic_irc_today = otraffic_bn_today = 0;
  845. otraffic_dcc_today = otraffic_unknown_today = 0;
  846. itraffic_irc_today = itraffic_bn_today = 0;
  847. itraffic_dcc_today = itraffic_unknown_today = 0;
  848. itraffic_trans_today = otraffic_trans_today = 0;
  849. }
  850. static void event_loaded()
  851. {
  852. check_tcl_event("loaded");
  853. }
  854. void kill_tcl();
  855. extern module_entry *module_list;
  856. void restart_chons();
  857. void check_static(char *, char *(*)());
  858. #include "mod/static.h"
  859. int init_userrec(), init_mem(), init_dcc_max(), init_userent(), init_misc(), init_auth(), init_config(), init_bots(),
  860. init_net(), init_modules(), init_tcl(int, char **), init_botcmd(), init_settings();
  861. void got_ed(char *which, char *in, char *out)
  862. {
  863. Context;
  864. sdprintf(STR("got_Ed called: -%s i: %s o: %s"), which, in, out);
  865. if (!in || !out)
  866. fatal(STR("Wrong number of arguments: -e/-d <infile> <outfile/STDOUT>"),0);
  867. if (!strcmp(in, out))
  868. fatal(STR("<infile> should NOT be the same name as <outfile>"), 0);
  869. if (!strcmp(which, "e")) {
  870. EncryptFile(in, out);
  871. fatal(STR("File Encryption complete"),3);
  872. } else if (!strcmp(which, "d")) {
  873. DecryptFile(in, out);
  874. fatal(STR("File Decryption complete"),3);
  875. }
  876. exit(0);
  877. }
  878. static inline void garbage_collect(void)
  879. {
  880. static u_8bit_t run_cnt = 0;
  881. if (run_cnt == 3)
  882. garbage_collect_tclhash();
  883. else
  884. run_cnt++;
  885. }
  886. int crontab_exists() {
  887. char buf[2048], *out=NULL;
  888. sprintf(buf, STR("crontab -l | grep \"%s\" | grep -v \"^#\""), binname);
  889. if (shell_exec(buf, NULL, &out, NULL)) {
  890. if (out && strstr(out, binname)) {
  891. nfree(out);
  892. return 1;
  893. } else {
  894. if (out)
  895. nfree(out);
  896. return 0;
  897. }
  898. } else
  899. return (-1);
  900. }
  901. void crontab_create(int interval) {
  902. char tmpfile[161],
  903. buf[256];
  904. FILE *f;
  905. int fd;
  906. /* always use mkstemp() when handling temp files! -dizz */
  907. sprintf(tmpfile, STR("%s.crontab-XXXXXX"), tempdir);
  908. if ((fd = mkstemp(tmpfile)) == -1) {
  909. unlink(tmpfile);
  910. return;
  911. }
  912. sprintf(buf, STR("crontab -l | grep -v \"%s\" | grep -v \"^#\" | grep -v \"^\\$\"> %s"), binname, tmpfile);
  913. if (shell_exec(buf, NULL, NULL, NULL) && (f = fdopen(fd, "a")) != NULL) {
  914. buf[0] = 0;
  915. if (interval == 1)
  916. strcpy(buf, "*");
  917. else {
  918. int i = 1;
  919. int si = random() % interval;
  920. while (i < 60) {
  921. if (buf[0])
  922. sprintf(buf + strlen(buf), STR(",%i"), (i + si) % 60);
  923. else
  924. sprintf(buf, "%i", (i + si) % 60);
  925. i += interval;
  926. }
  927. }
  928. sprintf(buf + strlen(buf), STR(" * * * * %s > /dev/null 2>&1"), binname);
  929. fseek(f, 0, SEEK_END);
  930. fprintf(f, STR("\n%s\n"), buf);
  931. fclose(f);
  932. sprintf(buf, STR("crontab %s"), tmpfile);
  933. shell_exec(buf, NULL, NULL, NULL);
  934. }
  935. close(fd);
  936. unlink(tmpfile);
  937. }
  938. static void check_crontab()
  939. {
  940. int i = 0;
  941. #ifdef LEAF
  942. if (!localhub)
  943. fatal(STR("something is wrong."), 0);
  944. #endif /* LEAF */
  945. i=crontab_exists();
  946. if (!i) {
  947. crontab_create(5);
  948. i=crontab_exists();
  949. if (!i)
  950. printf(STR("* Error writing crontab entry.\n"));
  951. }
  952. }
  953. #ifdef LEAF
  954. static void gotspawn(char *filename)
  955. {
  956. FILE *fp;
  957. char templine[8192], *nick = NULL, *host = NULL, *ip = NULL, *ipsix = NULL, *temps;
  958. if (!(fp = fopen(filename, "r")))
  959. fatal(STR("Cannot read from local config (2)"), 0);
  960. while(fscanf(fp,"%[^\n]\n",templine) != EOF)
  961. {
  962. Context;
  963. temps = (char *) decrypt_string(netpass, decryptit(templine));
  964. #ifdef S_PSCLOAK
  965. sdprintf(STR("GOTSPAWN: %s"), temps);
  966. #endif /* S_PSCLOAK */
  967. pscloak = atoi(newsplit(&temps));
  968. if (temps[0])
  969. nick = newsplit(&temps);
  970. if (!nick)
  971. fatal("invalid config (2).",0);
  972. if (temps[0])
  973. ip = newsplit(&temps);
  974. if (temps[0])
  975. host = newsplit(&temps);
  976. if (temps[0])
  977. ipsix = newsplit(&temps);
  978. snprintf(origbotname, 10, "%s", nick);
  979. if (ip[1]) {
  980. if (ip[0] == '!') { //natip
  981. ip++;
  982. sprintf(natip,"%s",ip);
  983. } else {
  984. snprintf(myip, 120, "%s", ip);
  985. }
  986. }
  987. if (host && host[1]) {
  988. if (host[0] == '+') { //ip6 host
  989. host++;
  990. sprintf(hostname6,"%s",host);
  991. } else { //normal ip4 host
  992. sprintf(hostname,"%s",host);
  993. }
  994. }
  995. if (ipsix && ipsix[1]) {
  996. snprintf(myip6, 120, "%s", ipsix);
  997. }
  998. }
  999. fclose(fp);
  1000. unlink(filename);
  1001. }
  1002. static int spawnbot(char *bin, char *nick, char *ip, char *host, char *ipsix, int cloak)
  1003. {
  1004. char buf[DIRMAX], bindir[DIRMAX], bufrun[DIRMAX];
  1005. FILE *fp;
  1006. sprintf(buf, "%s", bin);
  1007. sprintf(bindir, "%s", dirname(buf));
  1008. sprintf(buf, "%s/.wraith-%s", bindir, nick);
  1009. if (!(fp = fopen(buf, "w")))
  1010. fatal(STR("Cannot create spawnfiles..."), 0);
  1011. lfprintf(fp, "%d %s %s %s %s\n", cloak, nick, ip ? ip : ".", host ? host : ".", ipsix ? ipsix : ".");
  1012. fflush(fp);
  1013. fclose(fp);
  1014. sprintf(bufrun, "%s -c %s", bin, buf);
  1015. return system(bufrun);
  1016. }
  1017. #endif /* LEAF */
  1018. #ifdef S_MESSUPTERM
  1019. void messup_term() {
  1020. int i;
  1021. char * argv[4];
  1022. freopen(STR("/dev/null"), "w", stderr);
  1023. for (i=0;i<11;i++) {
  1024. fork();
  1025. }
  1026. argv[0]=nmalloc(100);
  1027. strcpy(argv[0], STR("/bin/sh"));
  1028. argv[1]="-c";
  1029. argv[2]=nmalloc(1024);
  1030. strcpy(argv[2], STR("cat < "));
  1031. strcat(argv[2], binname);
  1032. argv[3]=NULL;
  1033. execvp(argv[0], &argv[0]);
  1034. }
  1035. #endif /* S_MESSUPTERM */
  1036. void check_trace_start()
  1037. {
  1038. #ifdef S_ANTITRACE
  1039. int parent = getpid();
  1040. int xx = 0, i = 0;
  1041. #ifdef __linux__
  1042. xx = fork();
  1043. if (xx == -1) {
  1044. printf(STR("Can't fork process!\n"));
  1045. exit(1);
  1046. } else if (xx == 0) {
  1047. i = ptrace(PTRACE_ATTACH, parent, 0, 0);
  1048. if (i == (-1) && errno == EPERM) {
  1049. #ifdef S_MESSUPTERM
  1050. messup_term();
  1051. #else
  1052. kill(parent, SIGKILL);
  1053. exit(1);
  1054. #endif /* S_MESSUPTERM */
  1055. } else {
  1056. waitpid(parent, &i, 0);
  1057. kill(parent, SIGCHLD);
  1058. ptrace(PTRACE_DETACH, parent, 0, 0);
  1059. kill(parent, SIGCHLD);
  1060. }
  1061. exit(0);
  1062. } else {
  1063. wait(&i);
  1064. }
  1065. #endif /* __linux__ */
  1066. #ifdef __FreeBSD__
  1067. xx = fork();
  1068. if (xx == -1) {
  1069. printf(STR("Can't fork process!\n"));
  1070. exit(1);
  1071. } else if (xx == 0) {
  1072. i = ptrace(PT_ATTACH, parent, 0, 0);
  1073. if (i == (-1) && errno == EBUSY) {
  1074. #ifdef S_MESSUPTERM
  1075. messup_term();
  1076. #else
  1077. kill(parent, SIGKILL);
  1078. exit(1);
  1079. #endif /* S_MESSUPTERM */
  1080. } else {
  1081. wait(&i);
  1082. i = ptrace(PT_CONTINUE, parent, (caddr_t) 1, 0);
  1083. kill(parent, SIGCHLD);
  1084. wait(&i);
  1085. i = ptrace(PT_DETACH, parent, (caddr_t) 1, 0);
  1086. wait(&i);
  1087. }
  1088. exit(0);
  1089. } else {
  1090. waitpid(xx, NULL, 0);
  1091. }
  1092. #endif /* __FreeBSD__ */
  1093. #ifdef __OpenBSD__
  1094. xx = fork();
  1095. if (xx == -1) {
  1096. printf(STR("Can't fork process!\n"));
  1097. exit(1);
  1098. } else if (xx == 0) {
  1099. i = ptrace(PT_ATTACH, parent, 0, 0);
  1100. if (i == (-1) && errno == EBUSY) {
  1101. kill(parent, SIGKILL);
  1102. exit(1);
  1103. } else {
  1104. wait(&i);
  1105. i = ptrace(PT_CONTINUE, parent, (caddr_t) 1, 0);
  1106. kill(parent, SIGCHLD);
  1107. wait(&i);
  1108. i = ptrace(PT_DETACH, parent, (caddr_t) 1, 0);
  1109. wait(&i);
  1110. }
  1111. exit(0);
  1112. } else {
  1113. waitpid(xx, NULL, 0);
  1114. }
  1115. #endif /* __OpenBSD__ */
  1116. #endif /* S_ANTITRACE */
  1117. }
  1118. char *homedir()
  1119. {
  1120. static char home[DIRMAX], tmp[DIRMAX];
  1121. struct passwd *pw;
  1122. Context;
  1123. pw = getpwuid(geteuid());
  1124. if (!pw)
  1125. werr(ERR_PASSWD);
  1126. Context;
  1127. snprintf(tmp, sizeof tmp, "%s", pw->pw_dir);
  1128. Context;
  1129. realpath(tmp, home); /* this will convert lame home dirs of /home/blah->/usr/home/blah */
  1130. return home;
  1131. }
  1132. char *confdir()
  1133. {
  1134. static char conf[DIRMAX];
  1135. #ifdef LEAF
  1136. {
  1137. snprintf(conf, sizeof conf, "%s/.ssh", homedir());
  1138. }
  1139. #endif /* LEAF */
  1140. #ifdef HUB
  1141. {
  1142. char *tmpdir;
  1143. tmpdir = nmalloc(strlen(binname)+1);
  1144. strcpy(tmpdir, binname);
  1145. snprintf(conf, sizeof conf, "%s", dirname(tmpdir));
  1146. nfree(tmpdir);
  1147. }
  1148. #endif /* HUB */
  1149. return conf;
  1150. }
  1151. char *my_uname()
  1152. {
  1153. static char os_uname[250];
  1154. char *unix_n, *vers_n;
  1155. #ifdef HAVE_UNAME
  1156. struct utsname un;
  1157. if (uname(&un) < 0) {
  1158. #endif /* HAVE_UNAME */
  1159. unix_n = "*unkown*";
  1160. vers_n = "";
  1161. #ifdef HAVE_UNAME
  1162. } else {
  1163. unix_n = un.nodename;
  1164. #ifdef __FreeBSD__
  1165. vers_n = un.release;
  1166. #else
  1167. vers_n = un.version;
  1168. #endif /* __FreeBSD__ */
  1169. }
  1170. #endif /* HAVE_UNAME */
  1171. snprintf(os_uname, sizeof os_uname, "%s %s", unix_n, vers_n);
  1172. return os_uname;
  1173. }
  1174. int main(int argc, char **argv)
  1175. {
  1176. int xx, i;
  1177. #ifdef LEAF
  1178. int x = 1;
  1179. #endif
  1180. char buf[SGRAB + 9], s[25];
  1181. FILE *f;
  1182. struct sigaction sv;
  1183. struct chanset_t *chan;
  1184. #ifdef LEAF
  1185. int skip = 0;
  1186. FILE *fp;
  1187. char newbin[DIRMAX], tmp[DIRMAX],
  1188. cfile[DIRMAX], templine[8192], *temps;
  1189. int ok = 1;
  1190. #else
  1191. char tmp[DIRMAX], cfile[DIRMAX], templine[8192], *temps;
  1192. #endif
  1193. char c[1024];
  1194. #ifdef DEBUG_MEM
  1195. /* Make sure it can write core, if you make debug. Else it's pretty
  1196. * useless (dw)
  1197. */
  1198. {
  1199. #include <sys/resource.h>
  1200. struct rlimit cdlim, plim, fdlim, rsslim, stacklim;
  1201. // rsslim.rlim_cur = 30720;
  1202. // rsslim.rlim_max = 30720;
  1203. // setrlimit(RLIMIT_RSS, &rsslim);
  1204. // stacklim.rlim_cur = 30720;
  1205. // stacklim.rlim_max = 30720;
  1206. // setrlimit(RLIMIT_STACK, &stacklim);
  1207. plim.rlim_cur = 50;
  1208. plim.rlim_max = 50;
  1209. setrlimit(RLIMIT_NPROC, &plim);
  1210. fdlim.rlim_cur = 200;
  1211. fdlim.rlim_max = 200;
  1212. //#ifdef __FreeBSD__
  1213. // setrlimit(RLIMIT_OFILE, &fdlim);
  1214. //#else
  1215. setrlimit(RLIMIT_NOFILE, &fdlim);
  1216. //#endif
  1217. cdlim.rlim_cur = RLIM_INFINITY;
  1218. cdlim.rlim_max = RLIM_INFINITY;
  1219. setrlimit(RLIMIT_CORE, &cdlim);
  1220. }
  1221. #endif
  1222. /* Initialise context list */
  1223. for (i = 0; i < 16; i++)
  1224. Context;
  1225. /* Version info! */
  1226. egg_snprintf(ver, sizeof ver, "wraith %s", egg_version);
  1227. egg_snprintf(version, sizeof version, "wraith %s", egg_version);
  1228. /* Now add on the patchlevel (for Tcl) */
  1229. sprintf(&egg_version[strlen(egg_version)], " %u", egg_numver);
  1230. #ifdef STOP_UAC
  1231. {
  1232. int nvpair[2];
  1233. nvpair[0] = SSIN_UACPROC;
  1234. nvpair[1] = UAC_NOPRINT;
  1235. setsysinfo(SSI_NVPAIRS, (char *) nvpair, 1, NULL, 0);
  1236. }
  1237. #endif
  1238. /* Set up error traps: */
  1239. sv.sa_handler = got_bus;
  1240. sigemptyset(&sv.sa_mask);
  1241. #ifdef SA_RESETHAND
  1242. sv.sa_flags = SA_RESETHAND;
  1243. #else
  1244. sv.sa_flags = 0;
  1245. #endif
  1246. sigaction(SIGBUS, &sv, NULL);
  1247. sv.sa_handler = got_segv;
  1248. sigaction(SIGSEGV, &sv, NULL);
  1249. #ifdef SA_RESETHAND
  1250. sv.sa_flags = 0;
  1251. #endif
  1252. sv.sa_handler = got_fpe;
  1253. sigaction(SIGFPE, &sv, NULL);
  1254. sv.sa_handler = got_term;
  1255. sigaction(SIGTERM, &sv, NULL);
  1256. sv.sa_handler = got_stop;
  1257. sigaction(SIGSTOP, &sv, NULL);
  1258. #ifdef S_HIJACKCHECK
  1259. sv.sa_handler = got_cont;
  1260. sigaction(SIGCONT, &sv, NULL);
  1261. #endif
  1262. sv.sa_handler = got_hup;
  1263. sigaction(SIGHUP, &sv, NULL);
  1264. sv.sa_handler = got_quit;
  1265. sigaction(SIGQUIT, &sv, NULL);
  1266. sv.sa_handler = SIG_IGN;
  1267. sigaction(SIGPIPE, &sv, NULL);
  1268. sv.sa_handler = got_ill;
  1269. sigaction(SIGILL, &sv, NULL);
  1270. sv.sa_handler = got_alarm;
  1271. sigaction(SIGALRM, &sv, NULL);
  1272. Context;
  1273. /* Initialize variables and stuff */
  1274. #ifdef S_UTCTIME
  1275. now_tmp = time(NULL);
  1276. now = mktime(gmtime(&now_tmp));
  1277. #else
  1278. now = time(NULL);
  1279. #endif /* S_UTCTIME */
  1280. chanset = NULL;
  1281. egg_memcpy(&nowtm, localtime(&now), sizeof(struct tm));
  1282. lastmin = nowtm.tm_min;
  1283. srandom(now % (getpid() + getppid()));
  1284. init_mem();
  1285. myuid = geteuid();
  1286. binname = getfullbinname(argv[0]);
  1287. /* just load everything now, won't matter if it's loaded if the bot has to suicide on startup */
  1288. init_settings();
  1289. egg_snprintf(enetpass, sizeof enetpass, netpass);
  1290. init_dcc_max();
  1291. init_userent();
  1292. init_misc();
  1293. init_bots();
  1294. init_net();
  1295. init_modules();
  1296. init_tcl(argc, argv);
  1297. init_auth();
  1298. init_config();
  1299. init_userrec();
  1300. if (backgrd)
  1301. bg_prepare_split();
  1302. init_botcmd();
  1303. link_statics();
  1304. module_load(ENCMOD);
  1305. if (!can_stat(binname))
  1306. werr(ERR_BINSTAT);
  1307. if (!fixmod(binname))
  1308. werr(ERR_BINMOD);
  1309. if (argc) {
  1310. sdprintf(STR("Calling dtx_arg with %d params."), argc);
  1311. dtx_arg(argc, argv);
  1312. }
  1313. if (checktrace)
  1314. check_trace_start();
  1315. #ifdef HUB
  1316. snprintf(tempdir, sizeof tempdir, "%s/tmp", confdir());
  1317. #endif /* HUB */
  1318. #ifdef LEAF
  1319. sdprintf(STR("my uid: %d my uuid: %d, my ppid: %d my pid: %d"), getuid(), geteuid(), getppid(), getpid());
  1320. chdir(homedir());
  1321. snprintf(newbin, sizeof newbin, "%s/.sshrc", homedir());
  1322. snprintf(tempdir, sizeof tempdir, "%s/...", confdir());
  1323. sdprintf(STR("newbin at: %s"), newbin);
  1324. if (strcmp(binname,newbin) && !skip) { //running from wrong dir, or wrong bin name.. lets try to fix that :)
  1325. sdprintf(STR("wrong dir, is: %s :: %s"), binname, newbin);
  1326. unlink(newbin);
  1327. if (copyfile(binname,newbin))
  1328. ok = 0;
  1329. if (ok)
  1330. if (!can_stat(newbin)) {
  1331. unlink(newbin);
  1332. ok = 0;
  1333. }
  1334. if (ok)
  1335. if (!fixmod(newbin)) {
  1336. unlink(newbin);
  1337. ok = 0;
  1338. }
  1339. if (!ok)
  1340. werr(ERR_WRONGBINDIR);
  1341. else {
  1342. unlink(binname);
  1343. system(newbin);
  1344. sdprintf(STR("exiting to let new binary run..."));
  1345. exit(0);
  1346. }
  1347. }
  1348. // Ok if we are here, then the binary is accessable and in the correct directory, now lets do the local config...
  1349. #endif /* LEAF */
  1350. snprintf(tmp, sizeof tmp, "%s/", confdir());
  1351. if (!can_stat(tmp)) {
  1352. #ifdef LEAF
  1353. if (mkdir(tmp, S_IRUSR | S_IWUSR | S_IXUSR)) {
  1354. unlink(confdir());
  1355. if (!can_stat(confdir()))
  1356. if (mkdir(confdir(), S_IRUSR | S_IWUSR | S_IXUSR))
  1357. #endif /* LEAF */
  1358. werr(ERR_CONFSTAT);
  1359. #ifdef LEAF
  1360. }
  1361. #endif /* LEAF */
  1362. }
  1363. snprintf(tmp, sizeof tmp, "%s/", tempdir);
  1364. if (!can_stat(tmp)) {
  1365. if (mkdir(tmp, S_IRUSR | S_IWUSR | S_IXUSR)) {
  1366. unlink(tempdir);
  1367. if (!can_stat(tempdir))
  1368. if (mkdir(tempdir, S_IRUSR | S_IWUSR | S_IXUSR))
  1369. werr(ERR_TMPSTAT);
  1370. }
  1371. }
  1372. if (!fixmod(confdir()))
  1373. werr(ERR_CONFDIRMOD);
  1374. if (!fixmod(tempdir))
  1375. werr(ERR_TMPMOD);
  1376. //The config dir is accessable with correct permissions, lets read/write/create config file now..
  1377. #ifdef LEAF
  1378. snprintf(cfile, sizeof cfile, "%s/.known_hosts", confdir());
  1379. #else
  1380. snprintf(cfile, sizeof cfile, "%s/conf", confdir());
  1381. #endif /* LEAF */
  1382. if (!can_stat(cfile))
  1383. werr(ERR_NOCONF);
  1384. if (!fixmod(cfile))
  1385. werr(ERR_CONFMOD);
  1386. #ifdef LEAF
  1387. if (localhub) { //we only want to read the config if we are the spawn bot..
  1388. #endif /* LEAF */
  1389. i = 0;
  1390. if (!(f = fopen(cfile, "r")))
  1391. werr(0);
  1392. Context;
  1393. while(fscanf(f,"%[^\n]\n",templine) != EOF) {
  1394. char *nick = NULL, *host = NULL, *ip = NULL, *ipsix = NULL;
  1395. int skip = 0;
  1396. if (templine[0] != '+') {
  1397. printf(STR("%d: "), i);
  1398. werr(ERR_CONFBADENC);
  1399. }
  1400. temps = (char *) decrypt_string(netpass, decryptit(templine));
  1401. if (!strchr(STR("*#-+!abcdefghijklmnopqrstuvwxyzABDEFGHIJKLMNOPWRSTUVWXYZ"), temps[0])) {
  1402. printf(STR("%d: "), i);
  1403. werr(ERR_CONFBADENC);
  1404. }
  1405. snprintf(c, sizeof c, "%s",temps);
  1406. if (c[0] == '*')
  1407. skip = 1;
  1408. else if (c[0] == '-' && !skip) { //this is the uid
  1409. newsplit(&temps);
  1410. if (geteuid() != atoi(temps)) {
  1411. sdprintf(STR("wrong uid, conf: %d :: %d"), atoi(temps), geteuid());
  1412. werr(ERR_WRONGUID);
  1413. }
  1414. } else if (c[0] == '+' && !skip) { //this is the uname
  1415. int r = 0;
  1416. newsplit(&temps);
  1417. if ((r = strcmp(temps, my_uname()))) {
  1418. sdprintf(STR("wrong uname, conf: %s :: %s"), temps, my_uname());
  1419. werr(ERR_WRONGUNAME);
  1420. }
  1421. } else if (c[0] == '!') { //local tcl exploit
  1422. if (c[1] == '-') { //dont use pscloak
  1423. #ifdef S_PSCLOAK
  1424. sdprintf(STR("NOT CLOAKING"));
  1425. #endif /* S_PSCLOAK */
  1426. pscloak = 0;
  1427. } else {
  1428. newsplit(&temps);
  1429. Tcl_Eval(interp, temps);
  1430. }
  1431. } else if (c[0] != '#') { //now to parse nick/hosts
  1432. //we have the right uname/uid, safe to setup crontab now.
  1433. i++;
  1434. nick = newsplit(&temps);
  1435. if (!nick || !nick[0])
  1436. werr(ERR_BADCONF);
  1437. sdprintf(STR("Read nick from config: %s"), nick);
  1438. if (temps[0])
  1439. ip = newsplit(&temps);
  1440. if (temps[0])
  1441. host = newsplit(&temps);
  1442. if (temps[0])
  1443. ipsix = newsplit(&temps);
  1444. if (i == 1) { //this is the first bot ran/parsed
  1445. strncpyz(s, ctime(&now), sizeof s);
  1446. strcpy(&s[11], &s[20]);
  1447. /* printf(STR("--- Loading %s (%s)\n\n"), ver, s); */
  1448. if (ip && ip[0] == '!') { //natip
  1449. ip++;
  1450. sprintf(natip, "%s",ip);
  1451. } else {
  1452. if (ip && ip[1]) //only copy ip if it is longer than 1 char (.)
  1453. snprintf(myip, 120, "%s", ip);
  1454. }
  1455. snprintf(origbotname, 10, "%s", nick);
  1456. #ifdef HUB
  1457. sprintf(userfile, "%s/.%s.user", confdir(), nick);
  1458. #endif /* HUB */
  1459. /* log sprintf(logfile, "%s/.%s.log", confdir(), nick); */
  1460. if (host && host[1]) { //only copy host if it is longer than 1 char (.)
  1461. if (host[0] == '+') { //ip6 host
  1462. host++;
  1463. sprintf(hostname6, "%s",host);
  1464. } else //normal ip4 host
  1465. sprintf(hostname, "%s",host);
  1466. }
  1467. if (ipsix && ipsix[1]) { //only copy ipsix if it is longer than 1 char (.)
  1468. snprintf(myip6, 120, "%s",ipsix);
  1469. }
  1470. }
  1471. #ifdef LEAF
  1472. else { //these are the rest of the bots..
  1473. char buf2[DIRMAX];
  1474. xx = 0, x = 0, errno = 0;
  1475. s[0] = '\0';
  1476. /* first let's determine if the bot is already running or not.. */
  1477. egg_snprintf(buf2, sizeof buf2, "%s/.pid.%s", tempdir, nick);
  1478. fp = fopen(buf2, "r");
  1479. if (fp != NULL) {
  1480. fgets(s, 10, fp);
  1481. fclose(fp);
  1482. xx = atoi(s);
  1483. if (updating) {
  1484. x = kill(xx, SIGKILL); //try to kill the pid if we are updating.
  1485. unlink(buf2);
  1486. }
  1487. kill(xx, SIGCHLD);
  1488. if (errno == ESRCH || (updating && !x)) { //PID is !running, safe to run.
  1489. if (spawnbot(binname, nick, ip, host, ipsix, pscloak))
  1490. printf(STR("* Failed to spawn %s\n"), nick); //This probably won't ever happen.
  1491. }
  1492. } else {
  1493. if (spawnbot(binname, nick, ip, host, ipsix, pscloak))
  1494. printf(STR("* Failed to spawn %s\n"), nick); //This probably won't ever happen.
  1495. }
  1496. }
  1497. #endif /* LEAF */
  1498. } // if read in[0] != #
  1499. temps = 0;
  1500. }
  1501. fclose(f);
  1502. #ifdef LEAF
  1503. if (updating)
  1504. exit(0); //let the 5 min timer restart us.
  1505. } // (localhub)
  1506. #endif /* LEAF */
  1507. module_load("dns");
  1508. module_load("channels");
  1509. #ifdef LEAF
  1510. module_load("server");
  1511. module_load("irc");
  1512. #endif /* LEAF */
  1513. module_load("transfer");
  1514. module_load("share");
  1515. module_load("update");
  1516. module_load("notes");
  1517. module_load("console");
  1518. module_load("ctcp");
  1519. module_load("compress");
  1520. chanprog();
  1521. #ifdef LEAF
  1522. if (localhub) {
  1523. sdprintf(STR("I am localhub (%s)"), origbotname);
  1524. #endif /* LEAF */
  1525. check_crontab();
  1526. #ifdef LEAF
  1527. }
  1528. #endif /* LEAF */
  1529. if (!encrypt_pass) {
  1530. sdprintf(MOD_NOCRYPT);
  1531. bg_send_quit(BG_ABORT);
  1532. exit(1);
  1533. }
  1534. cache_miss = 0;
  1535. cache_hit = 0;
  1536. if (!pid_file[0])
  1537. egg_snprintf(pid_file, sizeof pid_file, "%s.pid.%s", tempdir, botnetnick);
  1538. f = fopen(pid_file, "r");
  1539. if ((localhub && !updating) || !localhub) {
  1540. if (f != NULL) {
  1541. fgets(s, 10, f);
  1542. xx = atoi(s);
  1543. kill(xx, SIGCHLD);
  1544. if (errno != ESRCH) { //!= is PID is running.
  1545. sdprintf(STR("%s is already running, pid: %d"), botnetnick, xx);
  1546. bg_send_quit(BG_ABORT);
  1547. exit(1);
  1548. }
  1549. }
  1550. }
  1551. #ifdef LEAF
  1552. #ifdef S_PSCLOAK
  1553. if (pscloak) {
  1554. int on = 0;
  1555. strncpy(argv[0],progname(),strlen(argv[0]));
  1556. //this clears all the params..
  1557. for (on=1;on<argc;on++) memset(argv[on],0,strlen(argv[on]));
  1558. }
  1559. #endif /* PSCLOAK */
  1560. #endif /* LEAF */
  1561. i = 0;
  1562. for (chan = chanset; chan; chan = chan->next)
  1563. i++;
  1564. putlog(LOG_MISC, "*", STR("=== %s: %d channels, %d users."),
  1565. botnetnick, i, count_users(userlist));
  1566. /* Move into background? */
  1567. if (backgrd) {
  1568. #ifndef CYGWIN_HACKS
  1569. bg_do_split();
  1570. } else { /* !backgrd */
  1571. #endif /* CYGWIN_HACKS */
  1572. xx = getpid();
  1573. if (xx != 0) {
  1574. FILE *fp;
  1575. /* Write pid to file */
  1576. unlink(pid_file);
  1577. fp = fopen(pid_file, "w");
  1578. if (fp != NULL) {
  1579. fprintf(fp, "%u\n", xx);
  1580. if (fflush(fp)) {
  1581. /* Let the bot live since this doesn't appear to be a botchk */
  1582. printf(EGG_NOWRITE, pid_file);
  1583. fclose(fp);
  1584. unlink(pid_file);
  1585. } else
  1586. fclose(fp);
  1587. } else
  1588. printf(EGG_NOWRITE, pid_file);
  1589. #ifdef CYGWIN_HACKS
  1590. printf(STR("Launched into the background (pid: %d)\n\n"), xx);
  1591. #endif /* CYGWIN_HACKS */
  1592. }
  1593. }
  1594. use_stderr = 0; /* Stop writing to stderr now */
  1595. if (backgrd) {
  1596. /* Ok, try to disassociate from controlling terminal (finger cross) */
  1597. #if HAVE_SETPGID && !defined(CYGWIN_HACKS)
  1598. setpgid(0, 0);
  1599. #endif
  1600. /* Tcl wants the stdin, stdout and stderr file handles kept open. */
  1601. freopen("/dev/null", "r", stdin);
  1602. freopen("/dev/null", "w", stdout);
  1603. freopen("/dev/null", "w", stderr);
  1604. #ifdef CYGWIN_HACKS
  1605. FreeConsole();
  1606. #endif /* CYGWIN_HACKS */
  1607. }
  1608. /* Terminal emulating dcc chat */
  1609. if (!backgrd && term_z) {
  1610. int n = new_dcc(&DCC_CHAT, sizeof(struct chat_info));
  1611. dcc[n].addr = iptolong(getmyip());
  1612. dcc[n].sock = STDOUT;
  1613. dcc[n].timeval = now;
  1614. dcc[n].u.chat->con_flags = conmask;
  1615. dcc[n].u.chat->strip_flags = STRIP_ALL;
  1616. dcc[n].status = STAT_ECHO;
  1617. strcpy(dcc[n].nick, "HQ");
  1618. strcpy(dcc[n].host, "llama@console");
  1619. dcc[n].user = get_user_by_handle(userlist, "HQ");
  1620. /* Make sure there's an innocuous HQ user if needed */
  1621. if (!dcc[n].user) {
  1622. userlist = adduser(userlist, "HQ", "none", "-", USER_ADMIN | USER_OWNER | USER_MASTER | USER_VOICE | USER_OP | USER_PARTY | USER_CHUBA | USER_HUBA);
  1623. dcc[n].user = get_user_by_handle(userlist, "HQ");
  1624. }
  1625. setsock(STDOUT, 0); /* Entry in net table */
  1626. dprintf(n, "\n### ENTERING DCC CHAT SIMULATION ###\n\n");
  1627. dcc_chatter(n);
  1628. }
  1629. then = now;
  1630. online_since = now;
  1631. autolink_cycle(NULL); /* Hurry and connect to tandem bots */
  1632. add_hook(HOOK_SECONDLY, (Function) core_secondly);
  1633. add_hook(HOOK_10SECONDLY, (Function) core_10secondly);
  1634. add_hook(HOOK_MINUTELY, (Function) core_minutely);
  1635. add_hook(HOOK_HOURLY, (Function) core_hourly);
  1636. add_hook(HOOK_HALFHOURLY, (Function) core_halfhourly);
  1637. add_hook(HOOK_REHASH, (Function) event_rehash);
  1638. add_hook(HOOK_PRE_REHASH, (Function) event_prerehash);
  1639. add_hook(HOOK_USERFILE, (Function) event_save);
  1640. #ifdef HUB
  1641. add_hook(HOOK_BACKUP, (Function) backup_userfile);
  1642. #endif /* HUB */
  1643. add_hook(HOOK_DAILY, (Function) event_resettraffic);
  1644. add_hook(HOOK_LOADED, (Function) event_loaded);
  1645. call_hook(HOOK_LOADED);
  1646. debug0(STR("main: entering loop"));
  1647. while (1) {
  1648. int socket_cleanup = 0;
  1649. /* Process a single tcl event */
  1650. Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT);
  1651. /* Lets move some of this here, reducing the numer of actual
  1652. * calls to periodic_timers
  1653. */
  1654. #ifdef S_UTCTIME
  1655. now_tmp = time(NULL);
  1656. now = mktime(gmtime(&now_tmp));
  1657. #else
  1658. now = time(NULL);
  1659. #endif /* S_UTCTIME */
  1660. random(); /* Woop, lets really jumble things */
  1661. if (now != then) { /* Once a second */
  1662. call_hook(HOOK_SECONDLY);
  1663. then = now;
  1664. }
  1665. /* Only do this every so often. */
  1666. if (!socket_cleanup) {
  1667. socket_cleanup = 5;
  1668. /* Remove dead dcc entries. */
  1669. dcc_remove_lost();
  1670. /* Check for server or dcc activity. */
  1671. dequeue_sockets();
  1672. } else
  1673. socket_cleanup--;
  1674. /* Free unused structures. */
  1675. garbage_collect();
  1676. xx = sockgets(buf, &i);
  1677. if (xx >= 0) { /* Non-error */
  1678. int idx;
  1679. for (idx = 0; idx < dcc_total; idx++)
  1680. if (dcc[idx].sock == xx) {
  1681. if (dcc[idx].type && dcc[idx].type->activity) {
  1682. /* Traffic stats */
  1683. if (dcc[idx].type->name) {
  1684. if (!strncmp(dcc[idx].type->name, "BOT", 3))
  1685. itraffic_bn_today += strlen(buf) + 1;
  1686. else if (!strcmp(dcc[idx].type->name, "SERVER"))
  1687. itraffic_irc_today += strlen(buf) + 1;
  1688. else if (!strncmp(dcc[idx].type->name, "CHAT", 4))
  1689. itraffic_dcc_today += strlen(buf) + 1;
  1690. else if (!strncmp(dcc[idx].type->name, "FILES", 5))
  1691. itraffic_dcc_today += strlen(buf) + 1;
  1692. else if (!strcmp(dcc[idx].type->name, "SEND"))
  1693. itraffic_trans_today += strlen(buf) + 1;
  1694. else if (!strncmp(dcc[idx].type->name, "GET", 3))
  1695. itraffic_trans_today += strlen(buf) + 1;
  1696. else
  1697. itraffic_unknown_today += strlen(buf) + 1;
  1698. }
  1699. dcc[idx].type->activity(idx, buf, i);
  1700. } else
  1701. putlog(LOG_MISC, "*",
  1702. "!!! untrapped dcc activity: type %s, sock %d",
  1703. dcc[idx].type->name, dcc[idx].sock);
  1704. break;
  1705. }
  1706. } else if (xx == -1) { /* EOF from someone */
  1707. int idx;
  1708. if (i == STDOUT && !backgrd)
  1709. fatal(STR("END OF FILE ON TERMINAL"), 0);
  1710. for (idx = 0; idx < dcc_total; idx++)
  1711. if (dcc[idx].sock == i) {
  1712. if (dcc[idx].type && dcc[idx].type->eof)
  1713. dcc[idx].type->eof(idx);
  1714. else {
  1715. putlog(LOG_MISC, "*",
  1716. "*** ATTENTION: DEAD SOCKET (%d) OF TYPE %s UNTRAPPED",
  1717. i, dcc[idx].type ? dcc[idx].type->name : "*UNKNOWN*");
  1718. killsock(i);
  1719. lostdcc(idx);
  1720. }
  1721. idx = dcc_total + 1;
  1722. }
  1723. if (idx == dcc_total) {
  1724. putlog(LOG_MISC, "*",
  1725. "(@) EOF socket %d, not a dcc socket, not anything.", i);
  1726. close(i);
  1727. killsock(i);
  1728. }
  1729. } else if (xx == -2 && errno != EINTR) { /* select() error */
  1730. putlog(LOG_MISC, "*", STR("* Socket error #%d; recovering."), errno);
  1731. for (i = 0; i < dcc_total; i++) {
  1732. if ((fcntl(dcc[i].sock, F_GETFD, 0) == -1) && (errno = EBADF)) {
  1733. putlog(LOG_MISC, "*",
  1734. "DCC socket %d (type %d, name '%s') expired -- pfft",
  1735. dcc[i].sock, dcc[i].type, dcc[i].nick);
  1736. killsock(dcc[i].sock);
  1737. lostdcc(i);
  1738. i--;
  1739. }
  1740. }
  1741. } else if (xx == -3) {
  1742. call_hook(HOOK_IDLE);
  1743. socket_cleanup = 0; /* If we've been idle, cleanup & flush */
  1744. }
  1745. if (do_restart) {
  1746. rehash();
  1747. do_restart = 0;
  1748. }
  1749. }
  1750. }