shell.c 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494
  1. /*
  2. * shell.c -- handles:
  3. *
  4. * All shell related functions
  5. * -shell_exec()
  6. * -botconfig parsing
  7. * -check_*()
  8. * -crontab functions
  9. *
  10. */
  11. #include "common.h"
  12. #include "shell.h"
  13. #include "cfg.h"
  14. #include "flags.h"
  15. #include "main.h"
  16. #include "dccutil.h"
  17. #include "modules.h"
  18. #include "misc.h"
  19. #include "misc_file.h"
  20. #include "bg.h"
  21. #include "stat.h"
  22. #include "users.h"
  23. #include <sys/types.h>
  24. #include <pwd.h>
  25. #include <signal.h>
  26. #ifdef S_ANTITRACE
  27. #include <sys/ptrace.h>
  28. #include <sys/wait.h>
  29. #endif /* S_ANTITRACE */
  30. #include <sys/utsname.h>
  31. #include <pwd.h>
  32. #include <errno.h>
  33. #include <net/if.h>
  34. #include <sys/ioctl.h>
  35. #include <sys/socket.h>
  36. #include <libgen.h>
  37. #include <ctype.h>
  38. #include <fcntl.h>
  39. #include <sys/stat.h>
  40. #include <unistd.h>
  41. #include <dirent.h>
  42. extern struct cfg_entry CFG_LOGIN, CFG_BADPROCESS, CFG_PROCESSLIST, CFG_PROMISC,
  43. CFG_TRACE, CFG_HIJACK;
  44. extern char tempdir[], origbotname[], botnetnick[], *binname, owneremail[],
  45. userfile[];
  46. extern time_t now;
  47. extern struct userrec *userlist;
  48. conf_t conf;
  49. void init_conf() {
  50. conf.bots = (conf_bot *) calloc(1, sizeof(conf_bot));
  51. conf.bots->nick = NULL;
  52. conf.bots->next = NULL;
  53. }
  54. /*
  55. * Return the PID of a bot if it is running, otherwise return 0
  56. */
  57. static int checkpid(char *nick) {
  58. FILE *f;
  59. int xx;
  60. char buf[DIRMAX], s[11];
  61. egg_snprintf(buf, sizeof buf, "%s.pid.%s", tempdir, nick);
  62. if ((f = fopen(buf, "r"))) {
  63. fgets(s, 10, f);
  64. fclose(f);
  65. xx = atoi(s);
  66. kill(xx, SIGCHLD);
  67. if (errno != ESRCH) /* PID is !running */
  68. return xx;
  69. }
  70. return 0;
  71. }
  72. static void conf_addbot(char *nick, char *ip, char *host, char *ip6, char *host6) {
  73. conf_bot *bot;
  74. for (bot = conf.bots; bot && bot->nick; bot = bot->next);
  75. bot->next = (conf_bot *) calloc(1, sizeof(conf_bot));
  76. bot->next->next = NULL;
  77. bot->nick = strdup(nick);
  78. if (bot == conf.bots) bot->localhub = 1; /* first bot */
  79. if (ip) bot->ip = strdup(ip);
  80. if (host) bot->host = strdup(host);
  81. if (ip6) bot->ip6 = strdup(ip6);
  82. if (host6) bot->host = strdup(host);
  83. bot->pid = checkpid(nick);
  84. }
  85. void free_conf() {
  86. conf_bot *bot, *bot_n;
  87. for (bot = conf.bots; bot; bot = bot_n) {
  88. bot_n = bot->next;
  89. free(bot->nick);
  90. if (bot->ip) free(bot->ip);
  91. if (bot->host) free(bot->host);
  92. if (bot->ip6) free(bot->ip6);
  93. if (bot->host6) free(bot->host6);
  94. /* must also free() anything malloc`d in addbot() */
  95. free(bot);
  96. }
  97. free(conf.uname);
  98. }
  99. int readconf()
  100. {
  101. /* conf.uid = READ;
  102. conf.uname = strdup(READ);
  103. */
  104. return 0;
  105. }
  106. int clear_tmp()
  107. {
  108. DIR *tmp;
  109. struct dirent *dir_ent;
  110. if (!(tmp = opendir(tempdir))) return 1;
  111. while ((dir_ent = readdir(tmp))) {
  112. if (strncmp(dir_ent->d_name, ".pid.", 4) && strncmp(dir_ent->d_name, ".u", 2) && strcmp(dir_ent->d_name, ".bin.old")
  113. && strcmp(dir_ent->d_name, ".") && strcmp(dir_ent->d_name, ".un") && strcmp(dir_ent->d_name, "..")) {
  114. char *file = malloc(strlen(dir_ent->d_name) + strlen(tempdir) + 1);
  115. file[0] = 0;
  116. strcat(file, tempdir);
  117. strcat(file, dir_ent->d_name);
  118. file[strlen(file)] = 0;
  119. unlink(file);
  120. free(file);
  121. }
  122. }
  123. closedir(tmp);
  124. return 0;
  125. }
  126. #ifdef S_LASTCHECK
  127. char last_buf[128]="";
  128. #endif /* S_LASTCHECK */
  129. void check_last() {
  130. #ifdef S_LASTCHECK
  131. char user[20];
  132. struct passwd *pw;
  133. if (!strcmp((char *) CFG_LOGIN.ldata ? CFG_LOGIN.ldata : CFG_LOGIN.gdata ? CFG_LOGIN.gdata : "ignore", "ignore"))
  134. return;
  135. pw = getpwuid(geteuid());
  136. if (!pw) return;
  137. strncpyz(user, pw->pw_name ? pw->pw_name : "" , sizeof(user));
  138. if (user[0]) {
  139. char *out;
  140. char buf[50];
  141. sprintf(buf, STR("last %s"), user);
  142. if (shell_exec(buf, NULL, &out, NULL)) {
  143. if (out) {
  144. char *p;
  145. p = strchr(out, '\n');
  146. if (p)
  147. *p = 0;
  148. if (strlen(out) > 10) {
  149. if (last_buf[0]) {
  150. if (strncmp(last_buf, out, sizeof(last_buf))) {
  151. char wrk[16384];
  152. sprintf(wrk, STR("Login: %s"), out);
  153. detected(DETECT_LOGIN, wrk);
  154. }
  155. }
  156. strncpyz(last_buf, out, sizeof(last_buf));
  157. }
  158. free(out);
  159. }
  160. }
  161. }
  162. #endif /* S_LASTCHECK */
  163. }
  164. void check_processes()
  165. {
  166. #ifdef S_PROCESSCHECK
  167. char *proclist,
  168. *out,
  169. *p,
  170. *np,
  171. *curp,
  172. buf[1024],
  173. bin[128];
  174. if (!strcmp((char *) CFG_BADPROCESS.ldata ? CFG_BADPROCESS.ldata : CFG_BADPROCESS.gdata ? CFG_BADPROCESS.gdata : "ignore", "ignore"))
  175. return;
  176. proclist = (char *) (CFG_PROCESSLIST.ldata && ((char *) CFG_PROCESSLIST.ldata)[0] ?
  177. CFG_PROCESSLIST.ldata : CFG_PROCESSLIST.gdata && ((char *) CFG_PROCESSLIST.gdata)[0] ? CFG_PROCESSLIST.gdata : NULL);
  178. if (!proclist)
  179. return;
  180. if (!shell_exec(STR("ps x"), NULL, &out, NULL))
  181. return;
  182. /* Get this binary's filename */
  183. strncpyz(buf, binname, sizeof(buf));
  184. p = strrchr(buf, '/');
  185. if (p) {
  186. p++;
  187. strncpyz(bin, p, sizeof(bin));
  188. } else {
  189. bin[0] = 0;
  190. }
  191. /* Fix up the "permitted processes" list */
  192. p = malloc(strlen(proclist) + strlen(bin) + 6);
  193. strcpy(p, proclist);
  194. strcat(p, " ");
  195. strcat(p, bin);
  196. strcat(p, " ");
  197. proclist = p;
  198. curp = out;
  199. while (curp) {
  200. np = strchr(curp, '\n');
  201. if (np)
  202. *np++ = 0;
  203. if (atoi(curp) > 0) {
  204. char *pid,
  205. *tty,
  206. *stat,
  207. *time,
  208. cmd[512],
  209. line[2048];
  210. strncpyz(line, curp, sizeof(line));
  211. /* it's a process line */
  212. /* Assuming format: pid tty stat time cmd */
  213. pid = newsplit(&curp);
  214. tty = newsplit(&curp);
  215. stat = newsplit(&curp);
  216. time = newsplit(&curp);
  217. strncpyz(cmd, curp, sizeof(cmd));
  218. /* skip any <defunct> procs "/bin/sh -c" crontab stuff and binname crontab stuff */
  219. if (!strstr(cmd, STR("<defunct>")) && !strncmp(cmd, STR("/bin/sh -c"), 10)
  220. && !strncmp(cmd, binname, strlen(binname))) {
  221. /* get rid of any args */
  222. if ((p = strchr(cmd, ' ')))
  223. *p = 0;
  224. /* remove [] or () */
  225. if (strlen(cmd)) {
  226. p = cmd + strlen(cmd) - 1;
  227. if (((cmd[0] == '(') && (*p == ')')) || ((cmd[0] == '[') && (*p == ']'))) {
  228. *p = 0;
  229. strcpy(buf, cmd + 1);
  230. strcpy(cmd, buf);
  231. }
  232. }
  233. /* remove path */
  234. if ((p = strrchr(cmd, '/'))) {
  235. p++;
  236. strcpy(buf, p);
  237. strcpy(cmd, buf);
  238. }
  239. /* skip "ps" */
  240. if (strcmp(cmd, "ps")) {
  241. /* see if proc's in permitted list */
  242. strcat(cmd, " ");
  243. if ((p = strstr(proclist, cmd))) {
  244. /* Remove from permitted list */
  245. while (*p != ' ')
  246. *p++ = 1;
  247. } else {
  248. char wrk[16384];
  249. sprintf(wrk, STR("Unexpected process: %s"), line);
  250. detected(DETECT_PROCESS, wrk);
  251. }
  252. }
  253. }
  254. }
  255. curp = np;
  256. }
  257. free(proclist);
  258. if (out)
  259. free(out);
  260. #endif /* S_PROCESSCHECK */
  261. }
  262. void check_promisc()
  263. {
  264. #ifdef S_PROMISC
  265. #ifdef SIOCGIFCONF
  266. char buf[8192];
  267. struct ifreq ifreq, *ifr;
  268. struct ifconf ifcnf;
  269. char *cp, *cplim;
  270. int sock;
  271. if (!strcmp((char *) CFG_PROMISC.ldata ? CFG_PROMISC.ldata : CFG_PROMISC.gdata ? CFG_PROMISC.gdata : "ignore", "ignore"))
  272. return;
  273. sock = socket(AF_INET, SOCK_STREAM, 0);
  274. ifcnf.ifc_len = 8191;
  275. ifcnf.ifc_buf = buf;
  276. if (ioctl(sock, SIOCGIFCONF, (char *) &ifcnf) < 0) {
  277. close(sock);
  278. return;
  279. }
  280. ifr = ifcnf.ifc_req;
  281. cplim = buf + ifcnf.ifc_len;
  282. for (cp = buf; cp < cplim; cp += sizeof(ifr->ifr_name) + sizeof(ifr->ifr_addr)) {
  283. ifr = (struct ifreq *) cp;
  284. ifreq = *ifr;
  285. if (!ioctl(sock, SIOCGIFFLAGS, (char *) &ifreq)) {
  286. if (ifreq.ifr_flags & IFF_PROMISC) {
  287. close(sock);
  288. detected(DETECT_PROMISC, STR("Detected promiscuous mode"));
  289. return;
  290. }
  291. }
  292. }
  293. close(sock);
  294. #endif /* SIOCGIFCONF */
  295. #endif /* S_PROMISC */
  296. }
  297. #ifdef S_ANTITRACE
  298. int traced = 0;
  299. static void got_trace(int z)
  300. {
  301. traced = 0;
  302. }
  303. #endif /* S_ANTITRACE */
  304. void check_trace()
  305. {
  306. #ifdef S_ANTITRACE
  307. int x, parent, i;
  308. struct sigaction sv, *oldsv = NULL;
  309. if (!strcmp((char *) CFG_TRACE.ldata ? CFG_TRACE.ldata : CFG_TRACE.gdata ? CFG_TRACE.gdata : "ignore", "ignore"))
  310. return;
  311. parent = getpid();
  312. #ifdef __linux__
  313. egg_bzero(&sv, sizeof(sv));
  314. sv.sa_handler = got_trace;
  315. sigemptyset(&sv.sa_mask);
  316. oldsv = NULL;
  317. sigaction(SIGTRAP, &sv, oldsv);
  318. traced = 1;
  319. asm("INT3");
  320. sigaction(SIGTRAP, oldsv, NULL);
  321. if (traced)
  322. detected(DETECT_TRACE, STR("I'm being traced!"));
  323. else {
  324. x = fork();
  325. if (x == -1)
  326. return;
  327. else if (x == 0) {
  328. i = ptrace(PTRACE_ATTACH, parent, 0, 0);
  329. if (i == (-1) && errno == EPERM)
  330. detected(DETECT_TRACE, STR("I'm being traced!"));
  331. else {
  332. waitpid(parent, &i, 0);
  333. kill(parent, SIGCHLD);
  334. ptrace(PTRACE_DETACH, parent, 0, 0);
  335. kill(parent, SIGCHLD);
  336. }
  337. exit(0);
  338. } else
  339. wait(&i);
  340. }
  341. #endif /* __linux__ */
  342. #ifdef __FreeBSD__
  343. x = fork();
  344. if (x == -1)
  345. return;
  346. else if (x == 0) {
  347. i = ptrace(PT_ATTACH, parent, 0, 0);
  348. if (i == (-1) && errno == EBUSY)
  349. detected(DETECT_TRACE, STR("I'm being traced"));
  350. else {
  351. wait(&i);
  352. i = ptrace(PT_CONTINUE, parent, (caddr_t) 1, 0);
  353. kill(parent, SIGCHLD);
  354. wait(&i);
  355. i = ptrace(PT_DETACH, parent, (caddr_t) 1, 0);
  356. wait(&i);
  357. }
  358. exit(0);
  359. } else
  360. waitpid(x, NULL, 0);
  361. #endif /* __FreeBSD__ */
  362. #ifdef __OpenBSD__
  363. x = fork();
  364. if (x == -1)
  365. return;
  366. else if (x == 0) {
  367. i = ptrace(PT_ATTACH, parent, 0, 0);
  368. if (i == (-1) && errno == EBUSY)
  369. detected(DETECT_TRACE, STR("I'm being traced"));
  370. else {
  371. wait(&i);
  372. i = ptrace(PT_CONTINUE, parent, (caddr_t) 1, 0);
  373. kill(parent, SIGCHLD);
  374. wait(&i);
  375. i = ptrace(PT_DETACH, parent, (caddr_t) 1, 0);
  376. wait(&i);
  377. }
  378. exit(0);
  379. } else
  380. waitpid(x, NULL, 0);
  381. #endif /* __OpenBSD__ */
  382. #endif /* S_ANTITRACE */
  383. }
  384. int shell_exec(char *cmdline, char *input, char **output, char **erroutput)
  385. {
  386. FILE *inpFile,
  387. *outFile,
  388. *errFile;
  389. char tmpfile[161];
  390. int x, fd;
  391. int parent = getpid();
  392. if (!cmdline)
  393. return 0;
  394. /* Set up temp files */
  395. /* always use mkstemp() when handling temp filess! -dizz */
  396. sprintf(tmpfile, STR("%s.in-XXXXXX"), tempdir);
  397. if ((fd = mkstemp(tmpfile)) == -1 || (inpFile = fdopen(fd, "w+")) == NULL) {
  398. if (fd != -1) {
  399. unlink(tmpfile);
  400. close(fd);
  401. }
  402. putlog(LOG_ERRORS, "*" , STR("exec: Couldn't open '%s': %s"), tmpfile, strerror(errno));
  403. return 0;
  404. }
  405. unlink(tmpfile);
  406. if (input) {
  407. if (fwrite(input, 1, strlen(input), inpFile) != strlen(input)) {
  408. fclose(inpFile);
  409. putlog(LOG_ERRORS, "*", STR("exec: Couldn't write to '%s': %s"), tmpfile, strerror(errno));
  410. return 0;
  411. }
  412. fseek(inpFile, 0, SEEK_SET);
  413. }
  414. unlink(tmpfile);
  415. sprintf(tmpfile, STR("%s.err-XXXXXX"), tempdir);
  416. if ((fd = mkstemp(tmpfile)) == -1 || (errFile = fdopen(fd, "w+")) == NULL) {
  417. if (fd != -1) {
  418. unlink(tmpfile);
  419. close(fd);
  420. }
  421. putlog(LOG_ERRORS, "*", STR("exec: Couldn't open '%s': %s"), tmpfile, strerror(errno));
  422. return 0;
  423. }
  424. unlink(tmpfile);
  425. sprintf(tmpfile, STR("%s.out-XXXXXX"), tempdir);
  426. if ((fd = mkstemp(tmpfile)) == -1 || (outFile = fdopen(fd, "w+")) == NULL) {
  427. if (fd != -1) {
  428. unlink(tmpfile);
  429. close(fd);
  430. }
  431. putlog(LOG_ERRORS, "*", STR("exec: Couldn't open '%s': %s"), tmpfile, strerror(errno));
  432. return 0;
  433. }
  434. unlink(tmpfile);
  435. x = fork();
  436. if (x == -1) {
  437. putlog(LOG_ERRORS, "*", STR("exec: fork() failed: %s"), strerror(errno));
  438. fclose(inpFile);
  439. fclose(errFile);
  440. fclose(outFile);
  441. return 0;
  442. }
  443. if (x) {
  444. /* Parent: wait for the child to complete */
  445. int st = 0;
  446. waitpid(x, &st, 0);
  447. /* Now read the files into the buffers */
  448. fclose(inpFile);
  449. fflush(outFile);
  450. fflush(errFile);
  451. if (erroutput) {
  452. char *buf;
  453. int fs;
  454. fseek(errFile, 0, SEEK_END);
  455. fs = ftell(errFile);
  456. if (fs == 0) {
  457. (*erroutput) = NULL;
  458. } else {
  459. buf = malloc(fs + 1);
  460. fseek(errFile, 0, SEEK_SET);
  461. fread(buf, 1, fs, errFile);
  462. buf[fs] = 0;
  463. (*erroutput) = buf;
  464. }
  465. }
  466. fclose(errFile);
  467. if (output) {
  468. char *buf;
  469. int fs;
  470. fseek(outFile, 0, SEEK_END);
  471. fs = ftell(outFile);
  472. if (fs == 0) {
  473. (*output) = NULL;
  474. } else {
  475. buf = malloc(fs + 1);
  476. fseek(outFile, 0, SEEK_SET);
  477. fread(buf, 1, fs, outFile);
  478. buf[fs] = 0;
  479. (*output) = buf;
  480. }
  481. }
  482. fclose(outFile);
  483. return 1;
  484. } else {
  485. /* Child: make fd's and set them up as std* */
  486. int ind,
  487. outd,
  488. errd;
  489. char *argv[4];
  490. ind = fileno(inpFile);
  491. outd = fileno(outFile);
  492. errd = fileno(errFile);
  493. if (dup2(ind, STDIN_FILENO) == (-1)) {
  494. kill(parent, SIGCHLD);
  495. exit(1);
  496. }
  497. if (dup2(outd, STDOUT_FILENO) == (-1)) {
  498. kill(parent, SIGCHLD);
  499. exit(1);
  500. }
  501. if (dup2(errd, STDERR_FILENO) == (-1)) {
  502. kill(parent, SIGCHLD);
  503. exit(1);
  504. }
  505. argv[0] = STR("sh");
  506. argv[1] = STR("-c");
  507. argv[2] = cmdline;
  508. argv[3] = NULL;
  509. execvp(argv[0], &argv[0]);
  510. kill(parent, SIGCHLD);
  511. exit(1);
  512. }
  513. }
  514. void detected(int code, char *msg)
  515. {
  516. #ifdef LEAF
  517. module_entry *me;
  518. #endif /* LEAF */
  519. char *p = NULL;
  520. char tmp[512];
  521. struct userrec *u;
  522. struct flag_record fr = { FR_GLOBAL, 0, 0 };
  523. int act;
  524. u = get_user_by_handle(userlist, botnetnick);
  525. #ifdef S_LASTCHECK
  526. if (code == DETECT_LOGIN)
  527. p = (char *) (CFG_LOGIN.ldata ? CFG_LOGIN.ldata : (CFG_LOGIN.gdata ? CFG_LOGIN.gdata : NULL));
  528. #endif /* S_LASTCHECK */
  529. #ifdef S_ANTITRACE
  530. if (code == DETECT_TRACE)
  531. p = (char *) (CFG_TRACE.ldata ? CFG_TRACE.ldata : (CFG_TRACE.gdata ? CFG_TRACE.gdata : NULL));
  532. #endif /* S_ANTITRACE */
  533. #ifdef S_PROMISC
  534. if (code == DETECT_PROMISC)
  535. p = (char *) (CFG_PROMISC.ldata ? CFG_PROMISC.ldata : (CFG_PROMISC.gdata ? CFG_PROMISC.gdata : NULL));
  536. #endif /* S_PROMISC */
  537. #ifdef S_PROCESSCHECK
  538. if (code == DETECT_PROCESS)
  539. p = (char *) (CFG_BADPROCESS.ldata ? CFG_BADPROCESS.ldata : (CFG_BADPROCESS.gdata ? CFG_BADPROCESS.gdata : NULL));
  540. #endif /* S_PROMISC */
  541. #ifdef S_HIJACKCHECK
  542. if (code == DETECT_SIGCONT)
  543. p = (char *) (CFG_HIJACK.ldata ? CFG_HIJACK.ldata : (CFG_HIJACK.gdata ? CFG_HIJACK.gdata : NULL));
  544. #endif /* S_PROMISC */
  545. if (!p)
  546. act = DET_WARN;
  547. else if (!strcmp(p, STR("die")))
  548. act = DET_DIE;
  549. else if (!strcmp(p, STR("reject")))
  550. act = DET_REJECT;
  551. else if (!strcmp(p, STR("suicide")))
  552. act = DET_SUICIDE;
  553. else if (!strcmp(p, STR("ignore")))
  554. act = DET_IGNORE;
  555. else
  556. act = DET_WARN;
  557. switch (act) {
  558. case DET_IGNORE:
  559. break;
  560. case DET_WARN:
  561. putlog(LOG_WARN, "*", msg);
  562. break;
  563. case DET_REJECT:
  564. do_fork();
  565. putlog(LOG_WARN, "*", STR("Setting myself +d: %s"), msg);
  566. sprintf(tmp, STR("+d: %s"), msg);
  567. set_user(&USERENTRY_COMMENT, u, tmp);
  568. get_user_flagrec(u, &fr, 0);
  569. fr.global = USER_DEOP | USER_BOT;
  570. set_user_flagrec(u, &fr, 0);
  571. sleep(1);
  572. break;
  573. case DET_DIE:
  574. putlog(LOG_WARN, "*", STR("Dying: %s"), msg);
  575. sprintf(tmp, STR("Dying: %s"), msg);
  576. set_user(&USERENTRY_COMMENT, u, tmp);
  577. #ifdef LEAF
  578. if ((me = module_find("server", 0, 0))) {
  579. Function *func = me->funcs;
  580. (func[SERVER_NUKESERVER]) ("BBL");
  581. }
  582. #endif /* LEAF */
  583. sleep(1);
  584. fatal(msg, 0);
  585. break;
  586. case DET_SUICIDE:
  587. putlog(LOG_WARN, "*", STR("Comitting suicide: %s"), msg);
  588. sprintf(tmp, STR("Suicide: %s"), msg);
  589. set_user(&USERENTRY_COMMENT, u, tmp);
  590. #ifdef LEAF
  591. if ((me = module_find("server", 0, 0))) {
  592. Function *func = me->funcs;
  593. (func[SERVER_NUKESERVER]) ("HARAKIRI!!");
  594. }
  595. #endif /* LEAF */
  596. sleep(1);
  597. unlink(binname);
  598. #ifdef HUB
  599. unlink(userfile);
  600. sprintf(tmp, STR("%s~"), userfile);
  601. unlink(tmp);
  602. #endif /* HUB */
  603. fatal(msg, 0);
  604. break;
  605. }
  606. }
  607. char *werr_tostr(int errnum)
  608. {
  609. switch (errnum) {
  610. case ERR_BINSTAT:
  611. return STR("Cannot access binary");
  612. case ERR_BINMOD:
  613. return STR("Cannot chmod() binary");
  614. case ERR_PASSWD:
  615. return STR("Cannot access the global passwd file");
  616. case ERR_WRONGBINDIR:
  617. return STR("Wrong directory/binary name");
  618. case ERR_CONFSTAT:
  619. #ifdef LEAF
  620. return STR("Cannot access config directory (~/.ssh/)");
  621. #else
  622. return STR("Cannot access config directory (./)");
  623. #endif /* LEAF */
  624. case ERR_TMPSTAT:
  625. #ifdef LEAF
  626. return STR("Cannot access tmp directory (~/.ssh/.../)");
  627. #else
  628. return STR("Cannot access config directory (./tmp/)");
  629. #endif /* LEAF */
  630. case ERR_CONFDIRMOD:
  631. #ifdef LEAF
  632. return STR("Cannot chmod() config directory (~/.ssh/)");
  633. #else
  634. return STR("Cannot chmod() config directory (./)");
  635. #endif /* LEAF */
  636. case ERR_CONFMOD:
  637. #ifdef LEAF
  638. return STR("Cannot chmod() config (~/.ssh/.known_hosts/)");
  639. #else
  640. return STR("Cannot chmod() config (./conf)");
  641. #endif /* LEAF */
  642. case ERR_TMPMOD:
  643. #ifdef LEAF
  644. return STR("Cannot chmod() tmp directory (~/.ssh/.../)");
  645. #else
  646. return STR("Cannot chmod() tmp directory (./tmp)");
  647. #endif /* LEAF */
  648. case ERR_NOCONF:
  649. #ifdef LEAF
  650. return STR("The local config is missing (~/.ssh/.known_hosts)");
  651. #else
  652. return STR("The local config is missing (./conf)");
  653. #endif /* LEAF */
  654. case ERR_CONFBADENC:
  655. return STR("Encryption in config is wrong/corrupt");
  656. case ERR_WRONGUID:
  657. return STR("UID in conf does not match getuid()");
  658. case ERR_WRONGUNAME:
  659. return STR("Uname in conf does not match uname()");
  660. case ERR_BADCONF:
  661. return STR("Config file is incomplete");
  662. default:
  663. return STR("Unforseen error");
  664. }
  665. }
  666. void werr(int errnum)
  667. {
  668. putlog(LOG_MISC, "*", STR("error #%d"), errnum);
  669. sdprintf(STR("error translates to: %s"), werr_tostr(errnum));
  670. printf(STR("(segmentation fault)\n"));
  671. fatal("", 0);
  672. }
  673. int email(char *subject, char *msg, int who)
  674. {
  675. struct utsname un;
  676. char open[2048], addrs[1024];
  677. int mail = 0, sendmail = 0;
  678. FILE *f;
  679. uname(&un);
  680. if (is_file("/usr/sbin/sendmail"))
  681. sendmail++;
  682. else if (is_file("/usr/bin/mail"))
  683. mail++;
  684. else {
  685. putlog(LOG_WARN, "*", "I Have no usable mail client.");
  686. return 1;
  687. }
  688. open[0] = addrs[0] = 0;
  689. if (who & EMAIL_OWNERS) {
  690. sprintf(addrs, "%s", replace(owneremail, ",", " "));
  691. }
  692. if (who & EMAIL_TEAM) {
  693. if (addrs[0])
  694. sprintf(addrs, "%s wraith@shatow.net", addrs);
  695. else
  696. sprintf(addrs, "wraith@shatow.net");
  697. }
  698. if (sendmail)
  699. sprintf(open, "/usr/sbin/sendmail -t");
  700. else if (mail)
  701. sprintf(open, "/usr/bin/mail %s -a \"From: %s@%s\" -s \"%s\" -a \"Content-Type: text/plain\"", addrs, (origbotname && origbotname[0]) ? origbotname : "none", un.nodename, subject);
  702. if ((f = popen(open, "w"))) {
  703. if (sendmail) {
  704. struct passwd *pw;
  705. pw = getpwuid(geteuid());
  706. fprintf(f, "To: %s\n", addrs);
  707. fprintf(f, "From: %s@%s\n", (origbotname && origbotname[0]) ? origbotname : pw->pw_name, un.nodename);
  708. fprintf(f, "Subject: %s\n", subject);
  709. fprintf(f, "Content-Type: text/plain\n");
  710. }
  711. fprintf(f, "%s\n", msg);
  712. if (fflush(f))
  713. return 1;
  714. if (pclose(f))
  715. return 1;
  716. } else
  717. return 1;
  718. return 0;
  719. }
  720. void baduname(char *conf, char *my_uname) {
  721. char *tmpfile = malloc(strlen(tempdir) + 3 + 1);
  722. int send = 0;
  723. tmpfile[0] = 0;
  724. sprintf(tmpfile, "%s.un", tempdir);
  725. sdprintf("CHECKING %s", tmpfile);
  726. if (is_file(tmpfile)) {
  727. struct stat ss;
  728. time_t diff;
  729. stat(tmpfile, &ss);
  730. diff = now - ss.st_mtime;
  731. if (diff >= 86400) send++; /* only send once a day */
  732. } else {
  733. FILE *fp;
  734. if ((fp = fopen(tmpfile, "w"))) {
  735. fprintf(fp, "\n");
  736. fflush(fp);
  737. fclose(fp);
  738. send++; /* only send if we could write the file. */
  739. }
  740. }
  741. if (send) {
  742. struct passwd *pw;
  743. struct utsname un;
  744. char msg[501], subject[31];
  745. pw = getpwuid(geteuid());
  746. if (!pw) return;
  747. uname(&un);
  748. egg_snprintf(subject, sizeof subject, "CONF/UNAME() mismatch notice");
  749. egg_snprintf(msg, sizeof msg, "This is an auto email from a wraith bot which has you in it's OWNER_EMAIL list..\n \nThe uname() output on this box has changed, probably due to a kernel upgrade...\nMy login is: %s\nConf : %s\nUname(): %s\n \nThis email will only be sent once a day while this error is present.\nYou need to login to my shell (%s) and fix my local config.\n", pw->pw_name, conf, my_uname, un.nodename);
  750. email(subject, msg, EMAIL_OWNERS);
  751. }
  752. free(tmpfile);
  753. }
  754. char *homedir()
  755. {
  756. static char homedir[DIRMAX] = "";
  757. if (!homedir || (homedir && !homedir[0])) {
  758. char tmp[DIRMAX];
  759. struct passwd *pw;
  760. sdprintf(STR("If the bot dies after this, try compiling on Debian."));
  761. Context;
  762. pw = getpwuid(geteuid());
  763. sdprintf(STR("End Debian suggestion."));
  764. if (!pw)
  765. werr(ERR_PASSWD);
  766. Context;
  767. egg_snprintf(tmp, sizeof tmp, "%s", pw->pw_dir);
  768. Context;
  769. realpath(tmp, homedir); /* this will convert lame home dirs of /home/blah->/usr/home/blah */
  770. }
  771. return homedir;
  772. }
  773. char *confdir()
  774. {
  775. static char confdir[DIRMAX] = "";
  776. if (!confdir || (confdir && !confdir[0])) {
  777. #ifdef LEAF
  778. {
  779. egg_snprintf(confdir, sizeof confdir, "%s/.ssh", homedir());
  780. }
  781. #endif /* LEAF */
  782. #ifdef HUB
  783. {
  784. char *buf = strdup(binname);
  785. egg_snprintf(confdir, sizeof confdir, "%s", dirname(buf));
  786. free(buf);
  787. }
  788. #endif /* HUB */
  789. }
  790. return confdir;
  791. }
  792. char *my_uname()
  793. {
  794. static char os_uname[250] = "";
  795. if (!os_uname || (os_uname && !os_uname[0])) {
  796. char *unix_n, *vers_n;
  797. struct utsname un;
  798. if (uname(&un) < 0) {
  799. unix_n = "*unkown*";
  800. vers_n = "";
  801. } else {
  802. unix_n = un.nodename;
  803. #ifdef __FreeBSD__
  804. vers_n = un.release;
  805. #else /* __linux__ */
  806. vers_n = un.version;
  807. #endif /* __FreeBSD__ */
  808. }
  809. egg_snprintf(os_uname, sizeof os_uname, "%s %s", unix_n, vers_n);
  810. }
  811. return os_uname;
  812. }
  813. void crontab_del() {
  814. char *tmpfile, *p, buf[2048];
  815. tmpfile = malloc(strlen(binname) + 100);
  816. strcpy(tmpfile, binname);
  817. if (!(p = strrchr(tmpfile, '/')))
  818. return;
  819. p++;
  820. strcpy(p, STR(".ctb"));
  821. sprintf(buf, STR("crontab -l | grep -v \"%s\" | grep -v \"^#\" | grep -v \"^\\$\" > %s"), binname, tmpfile);
  822. if (shell_exec(buf, NULL, NULL, NULL)) {
  823. sprintf(buf, STR("crontab %s"), tmpfile);
  824. shell_exec(buf, NULL, NULL, NULL);
  825. }
  826. unlink(tmpfile);
  827. }
  828. int crontab_exists() {
  829. char buf[2048] = "", *out = NULL;
  830. egg_snprintf(buf, sizeof buf, STR("crontab -l | grep \"%s\" | grep -v \"^#\""), binname);
  831. if (shell_exec(buf, NULL, &out, NULL)) {
  832. if (out && strstr(out, binname)) {
  833. free(out);
  834. return 1;
  835. } else {
  836. if (out)
  837. free(out);
  838. return 0;
  839. }
  840. } else
  841. return (-1);
  842. }
  843. void crontab_create(int interval) {
  844. char tmpfile[161] = "", buf[256] = "";
  845. FILE *f;
  846. int fd;
  847. /* always use mkstemp() when handling temp files! -dizz */
  848. egg_snprintf(tmpfile, sizeof tmpfile, "%s.crontab-XXXXXX", tempdir);
  849. if ((fd = mkstemp(tmpfile)) == -1) {
  850. unlink(tmpfile);
  851. return;
  852. }
  853. egg_snprintf(buf, sizeof buf, STR("crontab -l | grep -v \"%s\" | grep -v \"^#\" | grep -v \"^\\$\"> %s"), binname, tmpfile);
  854. if (shell_exec(buf, NULL, NULL, NULL) && (f = fdopen(fd, "a")) != NULL) {
  855. buf[0] = 0;
  856. if (interval == 1)
  857. strcpy(buf, "*");
  858. else {
  859. int i = 1;
  860. int si = random() % interval;
  861. while (i < 60) {
  862. if (buf[0])
  863. sprintf(buf + strlen(buf), STR(",%i"), (i + si) % 60);
  864. else
  865. sprintf(buf, "%i", (i + si) % 60);
  866. i += interval;
  867. }
  868. }
  869. egg_snprintf(buf + strlen(buf), sizeof buf, STR(" * * * * %s > /dev/null 2>&1"), binname);
  870. fseek(f, 0, SEEK_END);
  871. fprintf(f, STR("\n%s\n"), buf);
  872. fclose(f);
  873. sprintf(buf, STR("crontab %s"), tmpfile);
  874. shell_exec(buf, NULL, NULL, NULL);
  875. }
  876. close(fd);
  877. unlink(tmpfile);
  878. }
  879. #ifdef HEH
  880. int main(int argc, char **argv)
  881. {
  882. egg_timeval_t howlong;
  883. int xx, i;
  884. #ifdef LEAF
  885. int x = 1;
  886. #endif
  887. char buf[SGRAB + 9] = "", s[25] = "";
  888. FILE *f;
  889. #ifdef LEAF
  890. int skip = 0;
  891. int ok = 1;
  892. #endif
  893. init_debug();
  894. /* Version info! */
  895. egg_snprintf(ver, sizeof ver, "Wraith %s", egg_version);
  896. egg_snprintf(version, sizeof version, "Wraith %s (%u/%lu)", egg_version, egg_numver, buildts);
  897. #ifdef STOP_UAC
  898. {
  899. int nvpair[2];
  900. nvpair[0] = SSIN_UACPROC;
  901. nvpair[1] = UAC_NOPRINT;
  902. setsysinfo(SSI_NVPAIRS, (char *) nvpair, 1, NULL, 0);
  903. }
  904. #endif
  905. init_signals();
  906. Context;
  907. /* Initialize variables and stuff */
  908. now = time(NULL);
  909. chanset = NULL;
  910. #ifdef S_UTCTIME
  911. egg_memcpy(&nowtm, gmtime(&now), sizeof(struct tm));
  912. #else /* !S_UTCTIME */
  913. egg_memcpy(&nowtm, localtime(&now), sizeof(struct tm));
  914. #endif /* S_UTCTIME */
  915. lastmin = nowtm.tm_min;
  916. srandom(now % (getpid() + getppid()));
  917. myuid = geteuid();
  918. binname = getfullbinname(argv[0]);
  919. /* just load everything now, won't matter if it's loaded if the bot has to suicide on startup */
  920. init_settings();
  921. binds_init();
  922. core_binds_init();
  923. init_dcc_max();
  924. init_userent();
  925. init_bots();
  926. init_net();
  927. init_modules();
  928. init_tcl(argc, argv);
  929. init_auth();
  930. init_config();
  931. init_botcmd();
  932. link_statics();
  933. if (!can_stat(binname))
  934. werr(ERR_BINSTAT);
  935. if (!fixmod(binname))
  936. werr(ERR_BINMOD);
  937. if (argc) {
  938. sdprintf(STR("Calling dtx_arg with %d params."), argc);
  939. dtx_arg(argc, argv);
  940. }
  941. if (checktrace)
  942. check_trace_start();
  943. #ifdef HUB
  944. egg_snprintf(tempdir, sizeof tempdir, "%s/tmp/", confdir());
  945. #endif /* HUB */
  946. #ifdef LEAF
  947. {
  948. char newbin[DIRMAX];
  949. sdprintf(STR("my uid: %d my uuid: %d, my ppid: %d my pid: %d"), getuid(), geteuid(), getppid(), getpid());
  950. chdir(homedir());
  951. egg_snprintf(newbin, sizeof newbin, STR("%s/.sshrc"), homedir());
  952. egg_snprintf(tempdir, sizeof tempdir, "%s/.../", confdir());
  953. sdprintf(STR("newbin at: %s"), newbin);
  954. if (strcmp(binname,newbin) && !skip) { //running from wrong dir, or wrong bin name.. lets try to fix that :)
  955. sdprintf(STR("wrong dir, is: %s :: %s"), binname, newbin);
  956. unlink(newbin);
  957. if (copyfile(binname,newbin))
  958. ok = 0;
  959. if (ok)
  960. if (!can_stat(newbin)) {
  961. unlink(newbin);
  962. ok = 0;
  963. }
  964. if (ok)
  965. if (!fixmod(newbin)) {
  966. unlink(newbin);
  967. ok = 0;
  968. }
  969. if (!ok)
  970. werr(ERR_WRONGBINDIR);
  971. else {
  972. unlink(binname);
  973. system(newbin);
  974. sdprintf(STR("exiting to let new binary run..."));
  975. exit(0);
  976. }
  977. }
  978. /* Ok if we are here, then the binary is accessable and in the correct directory, now lets do the local config... */
  979. }
  980. #endif /* LEAF */
  981. {
  982. char tmp[DIRMAX];
  983. egg_snprintf(tmp, sizeof tmp, "%s/", confdir());
  984. if (!can_stat(tmp)) {
  985. #ifdef LEAF
  986. if (mkdir(tmp, S_IRUSR | S_IWUSR | S_IXUSR)) {
  987. unlink(confdir());
  988. if (!can_stat(confdir()))
  989. if (mkdir(confdir(), S_IRUSR | S_IWUSR | S_IXUSR))
  990. #endif /* LEAF */
  991. werr(ERR_CONFSTAT);
  992. #ifdef LEAF
  993. }
  994. #endif /* LEAF */
  995. }
  996. egg_snprintf(tmp, sizeof tmp, "%s", tempdir);
  997. if (!can_stat(tmp)) {
  998. if (mkdir(tmp, S_IRUSR | S_IWUSR | S_IXUSR)) {
  999. unlink(tempdir);
  1000. if (!can_stat(tempdir))
  1001. if (mkdir(tempdir, S_IRUSR | S_IWUSR | S_IXUSR))
  1002. werr(ERR_TMPSTAT);
  1003. }
  1004. }
  1005. }
  1006. if (!fixmod(confdir()))
  1007. werr(ERR_CONFDIRMOD);
  1008. if (!fixmod(tempdir))
  1009. werr(ERR_TMPMOD);
  1010. /* The config dir is accessable with correct permissions, lets read/write/create config file now.. */
  1011. { /* config shit */
  1012. char cfile[DIRMAX] = "", templine[8192] = "";
  1013. #ifdef LEAF
  1014. egg_snprintf(cfile, sizeof cfile, STR("%s/.known_hosts"), confdir());
  1015. #else /* HUB */
  1016. egg_snprintf(cfile, sizeof cfile, STR("%s/conf"), confdir());
  1017. #endif /* LEAF */
  1018. if (!can_stat(cfile))
  1019. werr(ERR_NOCONF);
  1020. if (!fixmod(cfile))
  1021. werr(ERR_CONFMOD);
  1022. #ifdef LEAF
  1023. if (localhub) {
  1024. #endif /* LEAF */
  1025. i = 0;
  1026. if (!(f = fopen(cfile, "r")))
  1027. werr(0);
  1028. Context;
  1029. while(fscanf(f, "%[^\n]\n", templine) != EOF) {
  1030. char *nick = NULL, *host = NULL, *ip = NULL, *ipsix = NULL, *temps, c[1024];
  1031. void *temp_ptr;
  1032. int skip = 0;
  1033. temps = temp_ptr = decrypt_string(SALT1, templine);
  1034. if (!strchr(STR("*#-+!abcdefghijklmnopqrstuvwxyzABDEFGHIJKLMNOPWRSTUVWXYZ"), temps[0])) {
  1035. sdprintf(STR("line %d, char %c "), i, temps[0]);
  1036. werr(ERR_CONFBADENC);
  1037. }
  1038. egg_snprintf(c, sizeof c, "%s", temps);
  1039. if (c[0] == '*') {
  1040. skip = 1;
  1041. } else if (c[0] == '-' && !skip) { /* uid */
  1042. newsplit(&temps);
  1043. if (geteuid() != atoi(temps)) {
  1044. sdprintf(STR("wrong uid, conf: %d :: %d"), atoi(temps), geteuid());
  1045. werr(ERR_WRONGUID);
  1046. }
  1047. } else if (c[0] == '+' && !skip) { /* uname */
  1048. int r = 0;
  1049. newsplit(&temps);
  1050. if ((r = strcmp(temps, my_uname()))) {
  1051. baduname(temps, my_uname());
  1052. sdprintf(STR("wrong uname, conf: %s :: %s"), temps, my_uname());
  1053. werr(ERR_WRONGUNAME);
  1054. }
  1055. } else if (c[0] == '!') { //local tcl exploit
  1056. if (c[1] == '-') { //dont use pscloak
  1057. #ifdef S_PSCLOAK
  1058. sdprintf(STR("NOT CLOAKING"));
  1059. #endif /* S_PSCLOAK */
  1060. pscloak = 0;
  1061. } else {
  1062. newsplit(&temps);
  1063. Tcl_Eval(interp, temps);
  1064. }
  1065. } else if (c[0] != '#') { //now to parse nick/hosts
  1066. /* we have the right uname/uid, safe to setup crontab now. */
  1067. i++;
  1068. nick = newsplit(&temps);
  1069. if (!nick || !nick[0])
  1070. werr(ERR_BADCONF);
  1071. sdprintf(STR("Read nick from config: %s"), nick);
  1072. if (temps[0])
  1073. ip = newsplit(&temps);
  1074. if (temps[0])
  1075. host = newsplit(&temps);
  1076. if (temps[0])
  1077. ipsix = newsplit(&temps);
  1078. if (i == 1) { //this is the first bot ran/parsed
  1079. strncpyz(s, ctime(&now), sizeof s);
  1080. strcpy(&s[11], &s[20]);
  1081. if (ip && ip[0] == '!') { //natip
  1082. ip++;
  1083. sprintf(natip, "%s",ip);
  1084. } else {
  1085. if (ip && ip[1]) //only copy ip if it is longer than 1 char (.)
  1086. egg_snprintf(myip, 120, "%s", ip);
  1087. }
  1088. egg_snprintf(origbotname, 10, "%s", nick);
  1089. #ifdef HUB
  1090. sprintf(userfile, "%s/.u", confdir());
  1091. #endif /* HUB */
  1092. /* log sprintf(logfile, "%s/.%s.log", confdir(), nick); */
  1093. if (host && host[1]) { //only copy host if it is longer than 1 char (.)
  1094. if (host[0] == '+') { //ip6 host
  1095. host++;
  1096. sprintf(hostname6, "%s",host);
  1097. } else //normal ip4 host
  1098. sprintf(hostname, "%s",host);
  1099. }
  1100. if (ipsix && ipsix[1]) { //only copy ipsix if it is longer than 1 char (.)
  1101. egg_snprintf(myip6, 120, "%s",ipsix);
  1102. }
  1103. } //First bot in conf
  1104. #ifdef LEAF
  1105. else { //these are the rest of the bots..
  1106. char buf2[DIRMAX] = "";
  1107. FILE *fp;
  1108. xx = 0, x = 0, errno = 0;
  1109. s[0] = '\0';
  1110. /* first let's determine if the bot is already running or not.. */
  1111. egg_snprintf(buf2, sizeof buf2, "%s.pid.%s", tempdir, nick);
  1112. fp = fopen(buf2, "r");
  1113. if (fp != NULL) {
  1114. fgets(s, 10, fp);
  1115. fclose(fp);
  1116. xx = atoi(s);
  1117. if (updating) {
  1118. x = kill(xx, SIGKILL); //try to kill the pid if we are updating.
  1119. unlink(buf2);
  1120. }
  1121. kill(xx, SIGCHLD);
  1122. if (errno == ESRCH || (updating && !x)) { //PID is !running, safe to run.
  1123. if (spawnbot(binname, nick, ip, host, ipsix, pscloak))
  1124. printf(STR("* Failed to spawn %s\n"), nick); //This probably won't ever happen.
  1125. } else if (!x)
  1126. sdprintf(STR("%s is already running, pid: %d"), nick, xx);
  1127. } else {
  1128. if (spawnbot(binname, nick, ip, host, ipsix, pscloak))
  1129. printf(STR("* Failed to spawn %s\n"), nick); //This probably won't ever happen.
  1130. }
  1131. }
  1132. #endif /* LEAF */
  1133. }
  1134. free(temp_ptr);
  1135. } /* while(fscan) */
  1136. fclose(f);
  1137. #ifdef LEAF
  1138. if (updating)
  1139. exit(0); /* let cron restart us. */
  1140. } /* localhub */
  1141. #endif /* LEAF */
  1142. }
  1143. dns_init();
  1144. module_load("channels");
  1145. #ifdef LEAF
  1146. module_load("server");
  1147. module_load("irc");
  1148. #endif /* LEAF */
  1149. module_load("transfer");
  1150. module_load("share");
  1151. update_init();
  1152. notes_init();
  1153. console_init();
  1154. ctcp_init();
  1155. module_load("compress");
  1156. chanprog();
  1157. clear_tmp();
  1158. #ifdef LEAF
  1159. if (localhub) {
  1160. sdprintf(STR("I am localhub (%s)"), origbotname);
  1161. #endif /* LEAF */
  1162. check_crontab();
  1163. #ifdef LEAF
  1164. }
  1165. #endif /* LEAF */
  1166. cache_miss = 0;
  1167. cache_hit = 0;
  1168. if (!pid_file[0])
  1169. egg_snprintf(pid_file, sizeof pid_file, "%s.pid.%s", tempdir, botnetnick);
  1170. if ((localhub && !updating) || !localhub) {
  1171. if ((f = fopen(pid_file, "r")) != NULL) {
  1172. fgets(s, 10, f);
  1173. xx = atoi(s);
  1174. kill(xx, SIGCHLD);
  1175. if (errno != ESRCH) { //!= is PID is running.
  1176. sdprintf(STR("%s is already running, pid: %d"), botnetnick, xx);
  1177. exit(1);
  1178. }
  1179. fclose(f);
  1180. }
  1181. }
  1182. #ifdef LEAF
  1183. #ifdef S_PSCLOAK
  1184. if (pscloak) {
  1185. int on = 0;
  1186. char *p = progname();
  1187. egg_memset(argv[0], 0, strlen(argv[0]));
  1188. strncpyz(argv[0], p, strlen(p) + 1);
  1189. for (on = 1; on < argc; on++) egg_memset(argv[on], 0, strlen(argv[on]));
  1190. }
  1191. #endif /* PSCLOAK */
  1192. #endif /* LEAF */
  1193. putlog(LOG_MISC, "*", STR("=== %s: %d users."), botnetnick, count_users(userlist));
  1194. /* Move into background? */
  1195. if (backgrd) {
  1196. #ifndef CYGWIN_HACKS
  1197. bg_do_split();
  1198. } else { /* !backgrd */
  1199. #endif /* CYGWIN_HACKS */
  1200. xx = getpid();
  1201. if (xx != 0) {
  1202. /* Write pid to file */
  1203. unlink(pid_file);
  1204. if ((f = fopen(pid_file, "w")) != NULL) {
  1205. fprintf(f, "%u\n", xx);
  1206. if (fflush(f)) {
  1207. /* Let the bot live since this doesn't appear to be a botchk */
  1208. printf(EGG_NOWRITE, pid_file);
  1209. unlink(pid_file);
  1210. fclose(f);
  1211. } else {
  1212. fclose(f);
  1213. }
  1214. } else
  1215. printf(EGG_NOWRITE, pid_file);
  1216. #ifdef CYGWIN_HACKS
  1217. printf(STR("Launched into the background (pid: %d)\n\n"), xx);
  1218. #endif /* CYGWIN_HACKS */
  1219. }
  1220. }
  1221. use_stderr = 0; /* Stop writing to stderr now */
  1222. if (backgrd) {
  1223. /* Ok, try to disassociate from controlling terminal (finger cross) */
  1224. #if HAVE_SETPGID && !defined(CYGWIN_HACKS)
  1225. setpgid(0, 0);
  1226. #endif
  1227. /* Tcl wants the stdin, stdout and stderr file handles kept open. */
  1228. freopen("/dev/null", "r", stdin);
  1229. freopen("/dev/null", "w", stdout);
  1230. freopen("/dev/null", "w", stderr);
  1231. #ifdef CYGWIN_HACKS
  1232. FreeConsole();
  1233. #endif /* CYGWIN_HACKS */
  1234. }
  1235. /* Terminal emulating dcc chat */
  1236. if (!backgrd && term_z) {
  1237. int n = new_dcc(&DCC_CHAT, sizeof(struct chat_info));
  1238. dcc[n].addr = iptolong(getmyip());
  1239. dcc[n].sock = STDOUT;
  1240. dcc[n].timeval = now;
  1241. dcc[n].u.chat->con_flags = conmask;
  1242. dcc[n].u.chat->strip_flags = STRIP_ALL;
  1243. dcc[n].status = STAT_ECHO;
  1244. strcpy(dcc[n].nick, "HQ");
  1245. strcpy(dcc[n].host, "llama@console");
  1246. dcc[n].user = get_user_by_handle(userlist, "HQ");
  1247. /* Make sure there's an innocuous HQ user if needed */
  1248. if (!dcc[n].user) {
  1249. userlist = adduser(userlist, "HQ", "none", "-", USER_ADMIN | USER_OWNER | USER_MASTER | USER_VOICE | USER_OP | USER_PARTY | USER_CHUBA | USER_HUBA);
  1250. dcc[n].user = get_user_by_handle(userlist, "HQ");
  1251. }
  1252. setsock(STDOUT, 0); /* Entry in net table */
  1253. dprintf(n, "\n### ENTERING DCC CHAT SIMULATION ###\n\n");
  1254. dcc_chatter(n);
  1255. }
  1256. then = now;
  1257. online_since = now;
  1258. autolink_cycle(NULL); /* Hurry and connect to tandem bots */
  1259. howlong.sec = 1;
  1260. howlong.usec = 0;
  1261. timer_create_repeater(&howlong, (Function) core_secondly);
  1262. add_hook(HOOK_10SECONDLY, (Function) core_10secondly);
  1263. add_hook(HOOK_30SECONDLY, (Function) expire_simuls);
  1264. add_hook(HOOK_MINUTELY, (Function) core_minutely);
  1265. add_hook(HOOK_HOURLY, (Function) core_hourly);
  1266. add_hook(HOOK_HALFHOURLY, (Function) core_halfhourly);
  1267. add_hook(HOOK_REHASH, (Function) event_rehash);
  1268. add_hook(HOOK_PRE_REHASH, (Function) event_prerehash);
  1269. add_hook(HOOK_USERFILE, (Function) event_save);
  1270. add_hook(HOOK_DAILY, (Function) event_resettraffic);
  1271. debug0(STR("main: entering loop"));
  1272. while (1) {
  1273. int socket_cleanup = 0;
  1274. /* Process a single tcl event */
  1275. Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT);
  1276. /* Lets move some of this here, reducing the numer of actual
  1277. * calls to periodic_timers
  1278. */
  1279. now = time(NULL);
  1280. timer_run();
  1281. if (now != then) { /* Once a second */
  1282. /* call_hook(HOOK_SECONDLY); */
  1283. then = now;
  1284. }
  1285. /* Only do this every so often. */
  1286. if (!socket_cleanup) {
  1287. socket_cleanup = 5;
  1288. /* Remove dead dcc entries. */
  1289. dcc_remove_lost();
  1290. /* Check for server or dcc activity. */
  1291. dequeue_sockets();
  1292. } else
  1293. socket_cleanup--;
  1294. buf[0] = 0;
  1295. xx = sockgets(buf, &i);
  1296. /* "chanprog()" bug is down here somewhere.... */
  1297. if (xx >= 0) { /* Non-error */
  1298. int idx;
  1299. for (idx = 0; idx < dcc_total; idx++)
  1300. if (dcc[idx].sock == xx) {
  1301. if (dcc[idx].type && dcc[idx].type->activity) {
  1302. /* Traffic stats */
  1303. if (dcc[idx].type->name) {
  1304. if (!strncmp(dcc[idx].type->name, "BOT", 3))
  1305. traffic.in_today.bn += strlen(buf) + 1;
  1306. else if (!strcmp(dcc[idx].type->name, "SERVER"))
  1307. traffic.in_today.irc += strlen(buf) + 1;
  1308. else if (!strncmp(dcc[idx].type->name, "CHAT", 4))
  1309. traffic.in_today.dcc += strlen(buf) + 1;
  1310. else if (!strncmp(dcc[idx].type->name, "FILES", 5))
  1311. traffic.in_today.dcc += strlen(buf) + 1;
  1312. else if (!strcmp(dcc[idx].type->name, "SEND"))
  1313. traffic.in_today.trans += strlen(buf) + 1;
  1314. else if (!strncmp(dcc[idx].type->name, "GET", 3))
  1315. traffic.in_today.trans += strlen(buf) + 1;
  1316. else
  1317. traffic.in_today.unknown += strlen(buf) + 1;
  1318. }
  1319. dcc[idx].type->activity(idx, buf, i);
  1320. } else
  1321. putlog(LOG_MISC, "*",
  1322. "!!! untrapped dcc activity: type %s, sock %d",
  1323. dcc[idx].type->name, dcc[idx].sock);
  1324. break;
  1325. }
  1326. } else if (xx == -1) { /* EOF from someone */
  1327. int idx;
  1328. if (i == STDOUT && !backgrd)
  1329. fatal(STR("END OF FILE ON TERMINAL"), 0);
  1330. for (idx = 0; idx < dcc_total; idx++)
  1331. if (dcc[idx].sock == i) {
  1332. if (dcc[idx].type && dcc[idx].type->eof)
  1333. dcc[idx].type->eof(idx);
  1334. else {
  1335. putlog(LOG_MISC, "*",
  1336. "*** ATTENTION: DEAD SOCKET (%d) OF TYPE %s UNTRAPPED",
  1337. i, dcc[idx].type ? dcc[idx].type->name : "*UNKNOWN*");
  1338. killsock(i);
  1339. lostdcc(idx);
  1340. }
  1341. idx = dcc_total + 1;
  1342. }
  1343. if (idx == dcc_total) {
  1344. putlog(LOG_MISC, "*",
  1345. "(@) EOF socket %d, not a dcc socket, not anything.", i);
  1346. close(i);
  1347. killsock(i);
  1348. }
  1349. } else if (xx == -2 && errno != EINTR) { /* select() error */
  1350. putlog(LOG_MISC, "*", STR("* Socket error #%d; recovering."), errno);
  1351. for (i = 0; i < dcc_total; i++) {
  1352. if ((fcntl(dcc[i].sock, F_GETFD, 0) == -1) && (errno = EBADF)) {
  1353. putlog(LOG_MISC, "*",
  1354. "DCC socket %d (type %d, name '%s') expired -- pfft",
  1355. dcc[i].sock, dcc[i].type, dcc[i].nick);
  1356. killsock(dcc[i].sock);
  1357. lostdcc(i);
  1358. i--;
  1359. }
  1360. }
  1361. } else if (xx == -3) {
  1362. call_hook(HOOK_IDLE);
  1363. socket_cleanup = 0; /* If we've been idle, cleanup & flush */
  1364. }
  1365. if (do_restart) {
  1366. rehash();
  1367. do_restart = 0;
  1368. }
  1369. }
  1370. }
  1371. #endif