misc.c 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223
  1. /*
  2. * misc.c -- handles:
  3. * split() maskhost() dumplots() daysago() days() daysdur()
  4. * queueing output for the bot (msg and help)
  5. * resync buffers for sharebots
  6. * motd display and %var substitution
  7. *
  8. */
  9. #include "main.h"
  10. #include <sys/stat.h>
  11. #include <sys/types.h>
  12. #include <sys/wait.h>
  13. #include <ctype.h>
  14. #include <unistd.h>
  15. #include <fcntl.h>
  16. #include "chan.h"
  17. #include "tandem.h"
  18. #include "modules.h"
  19. #include <pwd.h>
  20. #include <errno.h>
  21. #ifdef S_ANTITRACE
  22. #include <sys/ptrace.h>
  23. #include <sys/wait.h>
  24. #endif /* S_ANTITRACE */
  25. #include <net/if.h>
  26. #include <sys/ioctl.h>
  27. #include <sys/socket.h>
  28. #include <signal.h>
  29. #ifdef HAVE_UNAME
  30. # include <sys/utsname.h>
  31. #endif /* HAVE_UNAME */
  32. #include "stat.h"
  33. #include "bg.h"
  34. extern struct userrec *userlist;
  35. extern struct dcc_t *dcc;
  36. extern struct chanset_t *chanset;
  37. extern tand_t *tandbot;
  38. extern char version[], origbotname[], botname[],
  39. admin[], network[], motdfile[], ver[], botnetnick[],
  40. bannerfile[], textdir[], userfile[], dcc_prefix[],
  41. *binname, pid_file[], tempdir[];
  42. extern int backgrd, con_chan, term_z, use_stderr, dcc_total, timesync, sdebug,
  43. #ifdef HUB
  44. my_port,
  45. #endif
  46. strict_host, loading,
  47. localhub;
  48. extern time_t now;
  49. extern Tcl_Interp *interp;
  50. extern struct cfg_entry CFG_MOTD, CFG_LOGIN, CFG_BADPROCESS, CFG_PROCESSLIST, CFG_PROMISC,
  51. CFG_TRACE, CFG_HIJACK;
  52. void detected(int, char *);
  53. int shtime = 1; /* Whether or not to display the time
  54. with console output */
  55. int conmask = LOG_MODES | LOG_CMDS | LOG_MISC; /* Console mask */
  56. int debug_output = 1; /* Disply output to server to LOG_SERVEROUT */
  57. int server_lag = 0; /* GUESS! */
  58. /* Expected memory usage
  59. */
  60. int expmem_misc()
  61. {
  62. int tot = 0;
  63. tot += strlen(binname) + 1;
  64. return tot;
  65. }
  66. void init_misc()
  67. {
  68. }
  69. /*
  70. * Misc functions
  71. */
  72. /* low-level stuff for other modules
  73. */
  74. /* This implementation wont overrun dst - 'max' is the max bytes that dst
  75. * can be, including the null terminator. So if 'dst' is a 128 byte buffer,
  76. * pass 128 as 'max'. The function will _always_ null-terminate 'dst'.
  77. *
  78. * Returns: The number of characters appended to 'dst'.
  79. *
  80. * Usage eg.
  81. *
  82. * char buf[128];
  83. * size_t bufsize = sizeof(buf);
  84. *
  85. * buf[0] = 0, bufsize--;
  86. *
  87. * while (blah && bufsize) {
  88. * bufsize -= egg_strcatn(buf, <some-long-string>, sizeof(buf));
  89. * }
  90. *
  91. * <Cybah>
  92. */
  93. int egg_strcatn(char *dst, const char *src, size_t max)
  94. {
  95. size_t tmpmax = 0;
  96. /* find end of 'dst' */
  97. while (*dst && max > 0) {
  98. dst++;
  99. max--;
  100. }
  101. /* Store 'max', so we can use it to workout how many characters were
  102. * written later on.
  103. */
  104. tmpmax = max;
  105. /* copy upto, but not including the null terminator */
  106. while (*src && max > 1) {
  107. *dst++ = *src++;
  108. max--;
  109. }
  110. /* null-terminate the buffer */
  111. *dst = 0;
  112. /* Don't include the terminating null in our count, as it will cumulate
  113. * in loops - causing a headache for the caller.
  114. */
  115. return tmpmax - max;
  116. }
  117. int my_strcpy(register char *a, register char *b)
  118. {
  119. register char *c = b;
  120. while (*b)
  121. *a++ = *b++;
  122. *a = *b;
  123. return b - c;
  124. }
  125. /* Split first word off of rest and put it in first
  126. */
  127. void splitc(char *first, char *rest, char divider)
  128. {
  129. char *p = strchr(rest, divider);
  130. if (p == NULL) {
  131. if (first != rest && first)
  132. first[0] = 0;
  133. return;
  134. }
  135. *p = 0;
  136. if (first != NULL)
  137. strcpy(first, rest);
  138. if (first != rest)
  139. /* In most circumstances, strcpy with src and dst being the same buffer
  140. * can produce undefined results. We're safe here, as the src is
  141. * guaranteed to be at least 2 bytes higher in memory than dest. <Cybah>
  142. */
  143. strcpy(rest, p + 1);
  144. }
  145. /* As above, but lets you specify the 'max' number of bytes (EXCLUDING the
  146. * terminating null).
  147. *
  148. * Example of use:
  149. *
  150. * char buf[HANDLEN + 1];
  151. *
  152. * splitcn(buf, input, "@", HANDLEN);
  153. *
  154. * <Cybah>
  155. */
  156. void splitcn(char *first, char *rest, char divider, size_t max)
  157. {
  158. char *p = strchr(rest, divider);
  159. if (p == NULL) {
  160. if (first != rest && first)
  161. first[0] = 0;
  162. return;
  163. }
  164. *p = 0;
  165. if (first != NULL)
  166. strncpyz(first, rest, max);
  167. if (first != rest)
  168. /* In most circumstances, strcpy with src and dst being the same buffer
  169. * can produce undefined results. We're safe here, as the src is
  170. * guaranteed to be at least 2 bytes higher in memory than dest. <Cybah>
  171. */
  172. strcpy(rest, p + 1);
  173. }
  174. char *splitnick(char **blah)
  175. {
  176. char *p = strchr(*blah, '!'), *q = *blah;
  177. if (p) {
  178. *p = 0;
  179. *blah = p + 1;
  180. return q;
  181. }
  182. return "";
  183. }
  184. void remove_crlf(char **line)
  185. {
  186. char *p;
  187. p = strchr(*line, '\n');
  188. if (p != NULL)
  189. *p = 0;
  190. p = strchr(*line, '\r');
  191. if (p != NULL)
  192. *p = 0;
  193. }
  194. char *newsplit(char **rest)
  195. {
  196. register char *o, *r;
  197. if (!rest)
  198. return *rest = "";
  199. o = *rest;
  200. while (*o == ' ')
  201. o++;
  202. r = o;
  203. while (*o && (*o != ' '))
  204. o++;
  205. if (*o)
  206. *o++ = 0;
  207. *rest = o;
  208. return r;
  209. }
  210. /* Convert "abc!user@a.b.host" into "*!user@*.b.host"
  211. * or "abc!user@1.2.3.4" into "*!user@1.2.3.*"
  212. * or "abc!user@0:0:0:0:0:ffff:1.2.3.4" into "*!user@0:0:0:0:0:ffff:1.2.3.*"
  213. * or "abc!user@3ffe:604:2:b02e:6174:7265:6964:6573" into
  214. * "*!user@3ffe:604:2:b02e:6174:7265:6964:*"
  215. */
  216. void maskhost(const char *s, char *nw)
  217. {
  218. register const char *p, *q, *e, *f;
  219. int i;
  220. *nw++ = '*';
  221. *nw++ = '!';
  222. p = (q = strchr(s, '!')) ? q + 1 : s;
  223. /* Strip of any nick, if a username is found, use last 8 chars */
  224. if ((q = strchr(p, '@'))) {
  225. int fl = 0;
  226. if ((q - p) > 9) {
  227. nw[0] = '*';
  228. p = q - 7;
  229. i = 1;
  230. } else
  231. i = 0;
  232. while (*p != '@') {
  233. if (!fl && strchr("~+-^=", *p)) {
  234. if (strict_host)
  235. nw[i] = '?';
  236. else
  237. i--;
  238. } else
  239. nw[i] = *p;
  240. fl++;
  241. p++;
  242. i++;
  243. }
  244. nw[i++] = '@';
  245. q++;
  246. } else {
  247. nw[0] = '*';
  248. nw[1] = '@';
  249. i = 2;
  250. q = s;
  251. }
  252. nw += i;
  253. e = NULL;
  254. /* Now q points to the hostname, i point to where to put the mask */
  255. if ((!(p = strchr(q, '.')) || !(e = strchr(p + 1, '.'))) && !strchr(q, ':'))
  256. /* TLD or 2 part host */
  257. strcpy(nw, q);
  258. else {
  259. if (e == NULL) { /* IPv6 address? */
  260. const char *mask_str;
  261. f = strrchr(q, ':');
  262. if (strchr(f, '.')) { /* IPv4 wrapped in an IPv6? */
  263. f = strrchr(f, '.');
  264. mask_str = ".*";
  265. } else /* ... no, true IPv6. */
  266. mask_str = ":*";
  267. strncpy(nw, q, f - q);
  268. /* No need to nw[f-q] = 0 here, as the strcpy below will
  269. * terminate the string for us.
  270. */
  271. nw += (f - q);
  272. strcpy(nw, mask_str);
  273. } else {
  274. for (f = e; *f; f++);
  275. f--;
  276. if (*f >= '0' && *f <= '9') { /* Numeric IP address */
  277. while (*f != '.')
  278. f--;
  279. strncpy(nw, q, f - q);
  280. /* No need to nw[f-q] = 0 here, as the strcpy below will
  281. * terminate the string for us.
  282. */
  283. nw += (f - q);
  284. strcpy(nw, ".*");
  285. } else { /* Normal host >= 3 parts */
  286. /* a.b.c -> *.b.c
  287. * a.b.c.d -> *.b.c.d if tld is a country (2 chars)
  288. * OR *.c.d if tld is com/edu/etc (3 chars)
  289. * a.b.c.d.e -> *.c.d.e etc
  290. */
  291. const char *x = strchr(e + 1, '.');
  292. if (!x)
  293. x = p;
  294. else if (strchr(x + 1, '.'))
  295. x = e;
  296. else if (strlen(x) == 3)
  297. x = p;
  298. else
  299. x = e;
  300. sprintf(nw, "*%s", x);
  301. }
  302. }
  303. }
  304. }
  305. /* Dump a potentially super-long string of text.
  306. */
  307. void dumplots(int idx, const char *prefix, char *data)
  308. {
  309. char *p = data, *q, *n, c;
  310. const int max_data_len = 500 - strlen(prefix);
  311. if (!*data) {
  312. dprintf(idx, "%s\n", prefix);
  313. return;
  314. }
  315. while (strlen(p) > max_data_len) {
  316. q = p + max_data_len;
  317. /* Search for embedded linefeed first */
  318. n = strchr(p, '\n');
  319. if (n && n < q) {
  320. /* Great! dump that first line then start over */
  321. *n = 0;
  322. dprintf(idx, "%s%s\n", prefix, p);
  323. *n = '\n';
  324. p = n + 1;
  325. } else {
  326. /* Search backwards for the last space */
  327. while (*q != ' ' && q != p)
  328. q--;
  329. if (q == p)
  330. q = p + max_data_len;
  331. c = *q;
  332. *q = 0;
  333. dprintf(idx, "%s%s\n", prefix, p);
  334. *q = c;
  335. p = q;
  336. if (c == ' ')
  337. p++;
  338. }
  339. }
  340. /* Last trailing bit: split by linefeeds if possible */
  341. n = strchr(p, '\n');
  342. while (n) {
  343. *n = 0;
  344. dprintf(idx, "%s%s\n", prefix, p);
  345. *n = '\n';
  346. p = n + 1;
  347. n = strchr(p, '\n');
  348. }
  349. if (*p)
  350. dprintf(idx, "%s%s\n", prefix, p); /* Last trailing bit */
  351. }
  352. /* Convert an interval (in seconds) to one of:
  353. * "19 days ago", "1 day ago", "18:12"
  354. */
  355. void daysago(time_t now, time_t then, char *out)
  356. {
  357. if (now - then > 86400) {
  358. int days = (now - then) / 86400;
  359. sprintf(out, "%d day%s ago", days, (days == 1) ? "" : "s");
  360. return;
  361. }
  362. #ifdef S_UTCTIME
  363. egg_strftime(out, 6, "%H:%M", gmtime(&then));
  364. #else /* !S_UTCTIME */
  365. egg_strftime(out, 6, "%H:%M", localtime(&then));
  366. #endif /* S_UTCTIME */
  367. }
  368. /* Convert an interval (in seconds) to one of:
  369. * "in 19 days", "in 1 day", "at 18:12"
  370. */
  371. void days(time_t now, time_t then, char *out)
  372. {
  373. if (now - then > 86400) {
  374. int days = (now - then) / 86400;
  375. sprintf(out, "in %d day%s", days, (days == 1) ? "" : "s");
  376. return;
  377. }
  378. #ifdef S_UTCTIME
  379. egg_strftime(out, 9, "at %H:%M", gmtime(&now));
  380. #else /* !S_UTCTIME */
  381. egg_strftime(out, 9, "at %H:%M", localtime(&now));
  382. #endif /* S_UTCTIME */
  383. }
  384. /* Convert an interval (in seconds) to one of:
  385. * "for 19 days", "for 1 day", "for 09:10"
  386. */
  387. void daysdur(time_t now, time_t then, char *out)
  388. {
  389. char s[81];
  390. int hrs, mins;
  391. if (now - then > 86400) {
  392. int days = (now - then) / 86400;
  393. sprintf(out, "for %d day%s", days, (days == 1) ? "" : "s");
  394. return;
  395. }
  396. strcpy(out, "for ");
  397. now -= then;
  398. hrs = (int) (now / 3600);
  399. mins = (int) ((now - (hrs * 3600)) / 60);
  400. sprintf(s, "%02d:%02d", hrs, mins);
  401. strcat(out, s);
  402. }
  403. /* show l33t banner */
  404. char *wbanner() {
  405. int r;
  406. r = random();
  407. switch (r % 9) {
  408. case 0: return STR(" .__ __ .__\n__ _ ______________ |__|/ |_| |__\n\\ \\/ \\/ /\\_ __ \\__ \\ | \\ __\\ | \\\n \\ / | | \\// __ \\| || | | Y \\\n \\/\\_/ |__| (____ /__||__| |___| /\n \\/ \\/\n");
  409. case 1: return STR(" _ _ _ \n__ ___ __ __ _(_) |_| |__ \n\\ \\ /\\ / / '__/ _` | | __| '_ \\ \n \\ V V /| | | (_| | | |_| | | |\n \\_/\\_/ |_| \\__,_|_|\\__|_| |_|\n");
  410. case 2: return STR("@@@ @@@ @@@ @@@@@@@ @@@@@@ @@@ @@@@@@@ @@@ @@@\n@@@ @@@ @@@ @@@@@@@@ @@@@@@@@ @@@ @@@@@@@ @@@ @@@\n@@! @@! @@! @@! @@@ @@! @@@ @@! @@! @@! @@@\n!@! !@! !@! !@! @!@ !@! @!@ !@! !@! !@! @!@\n@!! !!@ @!@ @!@!!@! @!@!@!@! !!@ @!! @!@!@!@!\n!@! !!! !@! !!@!@! !!!@!!!! !!! !!! !!!@!!!!\n!!: !!: !!: !!: :!! !!: !!! !!: !!: !!: !!!\n:!: :!: :!: :!: !:! :!: !:! :!: :!: :!: !:!\n :::: :: ::: :: ::: :: ::: :: :: :: :::\n :: : : : : : : : : : : : : : :\n");
  411. case 3: return STR(" o8o . oooo\n `'' .o8 `888\noooo oooo ooo oooo d8b .oooo. oooo .o888oo 888 .oo.\n `88. `88. .8' `888''8P `P )88b `888 888 888P'Y88b\n `88..]88..8' 888 .oP'888 888 888 888 888\n `888'`888' 888 d8( 888 888 888 . 888 888\n `8' `8' d888b `Y888''8o o888o '888' o888o o888o\n");
  412. case 4: return STR(" *\n * * **\n** *** ** **\n** * ** **\n ** *** **** *** **** ******** **\n ** *** *** * **** **** * **** *** ******** ** ***\n ** *** **** ** **** * *** * *** ** ** * ***\n ** ** ** ** * **** ** ** *** ***\n ** ** ** ** ** ** ** ** ** **\n ** ** ** ** ** ** ** ** ** **\n ** ** ** ** ** ** ** ** ** **\n ** ** * ** ** ** ** ** ** **\n ******* ******* *** ** ** ** ** ** **\n ***** ***** *** ***** ** *** * ** ** **\n *** ** *** ** **\n *\n *\n *\n *\n");
  413. case 5: return STR(" ::: === === :::==== :::==== ::: :::==== ::: ===\n ::: === === ::: === ::: === ::: :::==== ::: ===\n === === === ======= ======== === === ========\n =========== === === === === === === === ===\n ==== ==== === === === === === === === ===\n");
  414. case 6: return STR(" _ _ _ ______ _______ _____ _______ _ _\n | | | |_____/ |_____| | | |_____|\n |__|__| | \\_ | | __|__ | | |\n");
  415. case 7: return STR(" dBPdBPdBP dBBBBBb dBBBBBb dBP dBBBBBBP dBP dBP\n dBP BB\n dBPdBPdBP dBBBBK dBP BB dBP dBP dBBBBBP\n dBPdBPdBP dBP BB dBP BB dBP dBP dBP dBP\n dBBBBBBBP dBP dB' dBBBBBBB dBP dBP dBP dBP\n");
  416. case 8: return STR(" /\n # #/\n ### # ##\n## # ## ##\n## ## ##\n ## ### #### ### /### /### ### ########## /##\n ## ### ###/ ###/ #### / ###/ ########### ## / ###\n ## ### ### ## ###/ ### ## ## ##/ ###\n ## ## ## ## ## ## ## ## ## ##\n ## ## ## ## ## ## ## ## ## ##\n ## ## ## ## ## ## ## ## ## ##\n ## ## ## ## ## ## ## ## ## ##\n ## /# / ## ## /# ## ## ## ##\n ######/ ######/ ### ####/ ## ### /## ## ##\n ##### ##### ### ### ##/##/ ## ## ##\n /\n /\n /\n /");
  417. }
  418. return "";
  419. }
  420. void show_banner(int idx)
  421. {
  422. dumplots(-dcc[idx].sock, "", wbanner()); /* we use sock so that colors aren't applied to banner */
  423. dprintf(idx, "\n \n");
  424. dprintf(idx, STR("info, bugs, suggestions, comments:\n- http://www.shatow.net/wraith/ -\n"));
  425. }
  426. /* show motd to dcc chatter */
  427. void show_motd(int idx)
  428. {
  429. if (CFG_MOTD.gdata && *(char *) CFG_MOTD.gdata) {
  430. char *who, *buf, date[50];
  431. time_t time;
  432. void *buf_ptr;
  433. buf = buf_ptr = nmalloc(strlen((char *) CFG_MOTD.gdata) + 1);
  434. strcpy(buf, (char *) CFG_MOTD.gdata);
  435. who = newsplit(&buf);
  436. time = atoi(newsplit(&buf));
  437. #ifdef S_UTCTIME
  438. egg_strftime(date, sizeof date, "%c %Z", gmtime(&time));
  439. #else /* !S_UTCTIME */
  440. egg_strftime(date, sizeof date, "%c %Z", localtime(&time));
  441. #endif /* S_UTCTIME */
  442. dprintf(idx, "Motd set by \002%s\002 (%s)\n", who, date);
  443. dumplots(idx, "* ", replace(buf, "\\n", "\n"));
  444. nfree(buf_ptr);
  445. } else
  446. dprintf(idx, STR("Motd: none\n"));
  447. }
  448. void show_channels(int idx, char *handle)
  449. {
  450. struct chanset_t *chan;
  451. struct flag_record fr = { FR_CHAN | FR_GLOBAL, 0, 0, 0, 0 };
  452. struct userrec *u;
  453. int first = 0, l = 0, total = 0;
  454. char format[120];
  455. #ifdef LEAF
  456. module_entry *me = module_find("irc", 0, 0);
  457. Function *func = me->funcs;
  458. #endif /* LEAF */
  459. if (handle)
  460. u = get_user_by_handle(userlist, handle);
  461. else
  462. u = dcc[idx].user;
  463. for (chan = chanset;chan;chan = chan->next) {
  464. get_user_flagrec(u, &fr, chan->dname);
  465. if (l < strlen(chan->dname)) {
  466. l = strlen(chan->dname);
  467. }
  468. if (chk_op(fr, chan))
  469. total++;
  470. }
  471. egg_snprintf(format, sizeof format, " %%c%%-%us %%-s%%-s%%-s%%-s%%-s\n", (l+2));
  472. for (chan = chanset;chan;chan = chan->next) {
  473. #ifdef LEAF
  474. int opped = (func[16] (chan));
  475. #else /* !LEAF */
  476. int opped = 0;
  477. #endif /* LEAF */
  478. get_user_flagrec(u, &fr, chan->dname);
  479. if (chk_op(fr, chan)) {
  480. if (!first) {
  481. dprintf(idx, STR("%s %s access to %d channel%s:\n"), handle ? u->handle : "You", handle ? "has" : "have", total, (total > 1) ? "s" : "");
  482. first = 1;
  483. }
  484. dprintf(idx, format, opped ? '@' : ' ', chan->dname, !shouldjoin(chan) ? "(inactive) " : "",
  485. channel_private(chan) ? "(private) " : "", !channel_manop(chan) ? "(no manop) " : "",
  486. channel_bitch(chan) ? "(bitch) " : "", channel_closed(chan) ? "(closed)" : "");
  487. }
  488. }
  489. if (!first)
  490. dprintf(idx, STR("%s %s not have access to any channels.\n"), handle ? u->handle : "You", handle ? "does" : "do");
  491. }
  492. int getting_users()
  493. {
  494. int i;
  495. for (i = 0; i < dcc_total; i++)
  496. if ((dcc[i].type == &DCC_BOT) && (dcc[i].status & STAT_GETTING))
  497. return 1;
  498. return 0;
  499. }
  500. /*
  501. * Logging functions
  502. */
  503. /* Log something
  504. * putlog(level,channel_name,format,...);
  505. */
  506. void putlog EGG_VARARGS_DEF(int, arg1)
  507. {
  508. int i, type, tsl = 0, dohl = 0; //hl
  509. char *format, *chname, s[LOGLINELEN], *out, stamp[34], buf2[LOGLINELEN];
  510. va_list va;
  511. #ifdef HUB
  512. time_t now2 = time(NULL);
  513. #endif /* HUB */
  514. struct tm *t;
  515. #ifdef LEAF
  516. t = 0;
  517. #endif /* LEAF */
  518. type = EGG_VARARGS_START(int, arg1, va);
  519. chname = va_arg(va, char *);
  520. format = va_arg(va, char *);
  521. //The putlog should not be broadcast over bots, @ is *.
  522. if ((chname[0] == '*'))
  523. dohl = 1;
  524. #ifdef HUB
  525. #ifdef S_UTCTIME
  526. t = gmtime(&now2);
  527. #else /* !S_UTCTIME */
  528. t = localtime(&now2);
  529. #endif /* S_UTCTIME */
  530. if (shtime) {
  531. egg_strftime(stamp, sizeof(stamp) - 2, LOG_TS, t);
  532. strcat(stamp, " ");
  533. tsl = strlen(stamp);
  534. }
  535. #endif /* HUB */
  536. /* Format log entry at offset 'tsl,' then i can prepend the timestamp */
  537. out = s+tsl;
  538. /* No need to check if out should be null-terminated here,
  539. * just do it! <cybah>
  540. */
  541. egg_vsnprintf(out, LOGLINEMAX - tsl, format, va);
  542. out[LOGLINEMAX - tsl] = 0;
  543. /* Place the timestamp in the string to be printed */
  544. if ((out[0]) && (shtime)) {
  545. strncpy(s, stamp, tsl);
  546. out = s;
  547. }
  548. strcat(out, "\n");
  549. /* WRITE LOG HERE */
  550. /* echo line to hubs (not if it was on a +h though)*/
  551. if (dohl) {
  552. tand_t *bot;
  553. struct userrec *ubot;
  554. sprintf(buf2, "hl %d %s", type, out);
  555. if (userlist && !loading) {
  556. for (bot = tandbot ;bot ; bot = bot->next) {
  557. ubot = get_user_by_handle(userlist, bot->bot);
  558. if (ubot) {
  559. if (bot_hublevel(ubot) < 999) {
  560. putbot(ubot->handle, buf2);
  561. }
  562. }
  563. }
  564. } else {
  565. putallbots(buf2);
  566. }
  567. }
  568. for (i = 0; i < dcc_total; i++)
  569. if ((dcc[i].type == &DCC_CHAT && !dcc[i].simul) && (dcc[i].u.chat->con_flags & type)) {
  570. if ((chname[0] == '@') || (chname[0] == '*') || (dcc[i].u.chat->con_chan[0] == '*') ||
  571. (!rfc_casecmp(chname, dcc[i].u.chat->con_chan)))
  572. dprintf(i, "%s", out);
  573. }
  574. if ((!backgrd) && (!con_chan) && (!term_z))
  575. dprintf(DP_STDOUT, "%s", out);
  576. else if ((type & LOG_MISC) && use_stderr) {
  577. if (shtime)
  578. out += tsl;
  579. dprintf(DP_STDERR, "%s", s);
  580. }
  581. va_end(va);
  582. }
  583. char *extracthostname(char *hostmask)
  584. {
  585. char *p = strrchr(hostmask, '@');
  586. return p ? p + 1 : "";
  587. }
  588. /* Create a string with random letters and digits
  589. */
  590. void make_rand_str(char *s, int len)
  591. {
  592. int j, r = 0;
  593. for (j = 0; j < len; j++) {
  594. r = random();
  595. if (r % 4 == 0)
  596. s[j] = '0' + (random() % 10);
  597. else if (r % 4 == 1)
  598. s[j] = 'a' + (random() % 26);
  599. else if (r % 4 == 2)
  600. s[j] = 'A' + (random() % 26);
  601. else
  602. s[j] = '!' + (random() % 15);
  603. if (s[j] == 33 || s[j] == 37 || s[j] == 34 || s[j] == 40 || s[j] == 41 || s[j] == 38 || s[j] == 36) //no % ( ) &
  604. s[j] = 35;
  605. }
  606. s[len] = '\0';
  607. }
  608. /* Convert an octal string into a decimal integer value. If the string
  609. * is empty or contains non-octal characters, -1 is returned.
  610. */
  611. int oatoi(const char *octal)
  612. {
  613. register int i;
  614. if (!*octal)
  615. return -1;
  616. for (i = 0; ((*octal >= '0') && (*octal <= '7')); octal++)
  617. i = (i * 8) + (*octal - '0');
  618. if (*octal)
  619. return -1;
  620. return i;
  621. }
  622. /* Return an allocated buffer which contains a copy of the string
  623. * 'str', with all 'div' characters escaped by 'mask'. 'mask'
  624. * characters are escaped too.
  625. *
  626. * Remember to free the returned memory block.
  627. */
  628. char *str_escape(const char *str, const char div, const char mask)
  629. {
  630. const int len = strlen(str);
  631. int buflen = (2 * len), blen = 0;
  632. char *buf = nmalloc(buflen + 1), *b = buf;
  633. const char *s;
  634. if (!buf)
  635. return NULL;
  636. for (s = str; *s; s++) {
  637. /* Resize buffer. */
  638. if ((buflen - blen) <= 3) {
  639. buflen = (buflen * 2);
  640. buf = nrealloc(buf, buflen + 1);
  641. if (!buf)
  642. return NULL;
  643. b = buf + blen;
  644. }
  645. if (*s == div || *s == mask) {
  646. sprintf(b, "%c%02x", mask, *s);
  647. b += 3;
  648. blen += 3;
  649. } else {
  650. *(b++) = *s;
  651. blen++;
  652. }
  653. }
  654. *b = 0;
  655. return buf;
  656. }
  657. /* Is every character in a string a digit? */
  658. int str_isdigit(const char *str)
  659. {
  660. if (!*str)
  661. return 0;
  662. for(; *str; ++str) {
  663. if (!egg_isdigit(*str))
  664. return 0;
  665. }
  666. return 1;
  667. }
  668. /* Search for a certain character 'div' in the string 'str', while
  669. * ignoring escaped characters prefixed with 'mask'.
  670. *
  671. * The string
  672. *
  673. * "\\3a\\5c i am funny \\3a):further text\\5c):oink"
  674. *
  675. * as str, '\\' as mask and ':' as div would change the str buffer
  676. * to
  677. *
  678. * ":\\ i am funny :)"
  679. *
  680. * and return a pointer to "further text\\5c):oink".
  681. *
  682. * NOTE: If you look carefully, you'll notice that strchr_unescape()
  683. * behaves differently than strchr().
  684. */
  685. char *strchr_unescape(char *str, const char div, register const char esc_char)
  686. {
  687. char buf[3];
  688. register char *s, *p;
  689. buf[3] = 0;
  690. for (s = p = str; *s; s++, p++) {
  691. if (*s == esc_char) { /* Found escape character. */
  692. /* Convert code to character. */
  693. buf[0] = s[1], buf[1] = s[2];
  694. *p = (unsigned char) strtol(buf, NULL, 16);
  695. s += 2;
  696. } else if (*s == div) {
  697. *p = *s = 0;
  698. return (s + 1); /* Found searched for character. */
  699. } else
  700. *p = *s;
  701. }
  702. *p = 0;
  703. return NULL;
  704. }
  705. /* As strchr_unescape(), but converts the complete string, without
  706. * searching for a specific delimiter character.
  707. */
  708. void str_unescape(char *str, register const char esc_char)
  709. {
  710. (void) strchr_unescape(str, 0, esc_char);
  711. }
  712. /* Kills the bot. s1 is the reason shown to other bots,
  713. * s2 the reason shown on the partyline. (Sup 25Jul2001)
  714. */
  715. void kill_bot(char *s1, char *s2)
  716. {
  717. #ifdef HUB
  718. write_userfile(-1);
  719. #endif /* HUB */
  720. call_hook(HOOK_DIE);
  721. chatout("*** %s\n", s1);
  722. botnet_send_chat(-1, botnetnick, s1);
  723. botnet_send_bye();
  724. fatal(s2, 0);
  725. }
  726. int isupdatehub()
  727. {
  728. #ifdef HUB
  729. struct userrec *buser;
  730. buser = get_user_by_handle(userlist, botnetnick);
  731. if ((buser) && (buser->flags & USER_UPDATEHUB))
  732. return 1;
  733. else
  734. #endif /* HUB */
  735. return 0;
  736. }
  737. int ischanhub()
  738. {
  739. struct userrec *buser;
  740. buser = get_user_by_handle(userlist, botnetnick);
  741. if ((buser) && (buser->flags & USER_CHANHUB))
  742. return 1;
  743. else
  744. return 0;
  745. }
  746. int dovoice(struct chanset_t *chan)
  747. {
  748. struct userrec *user = NULL;
  749. struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0 };
  750. if (!chan) return 0;
  751. user = get_user_by_handle(userlist, botnetnick);
  752. get_user_flagrec(user, &fr, chan->dname);
  753. if (glob_dovoice(fr) || chan_dovoice(fr))
  754. return 1;
  755. return 0;
  756. }
  757. int dolimit(struct chanset_t *chan)
  758. {
  759. struct userrec *user = NULL;
  760. struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0 };
  761. if (!chan) return 0;
  762. user = get_user_by_handle(userlist, botnetnick);
  763. get_user_flagrec(user, &fr, chan->dname);
  764. if (glob_dolimit(fr) || chan_dolimit(fr))
  765. return 1;
  766. return 0;
  767. }
  768. #ifdef S_LASTCHECK
  769. char last_buf[128]="";
  770. #endif /* S_LASTCHECK */
  771. void check_last() {
  772. #ifdef S_LASTCHECK
  773. char user[20];
  774. struct passwd *pw;
  775. if (!strcmp((char *) CFG_LOGIN.ldata ? CFG_LOGIN.ldata : CFG_LOGIN.gdata ? CFG_LOGIN.gdata : "", STR("nocheck")))
  776. return;
  777. pw = getpwuid(geteuid());
  778. if (!pw) return;
  779. strncpyz(user, pw->pw_name ? pw->pw_name : "" , sizeof(user));
  780. if (user[0]) {
  781. char *out;
  782. char buf[50];
  783. sprintf(buf, STR("last %s"), user);
  784. if (shell_exec(buf, NULL, &out, NULL)) {
  785. if (out) {
  786. char *p;
  787. p = strchr(out, '\n');
  788. if (p)
  789. *p = 0;
  790. if (strlen(out) > 10) {
  791. if (last_buf[0]) {
  792. if (strncmp(last_buf, out, sizeof(last_buf))) {
  793. char wrk[16384];
  794. sprintf(wrk, STR("Login: %s"), out);
  795. detected(DETECT_LOGIN, wrk);
  796. }
  797. }
  798. strncpyz(last_buf, out, sizeof(last_buf));
  799. }
  800. nfree(out);
  801. }
  802. }
  803. }
  804. #endif /* S_LASTCHECK */
  805. }
  806. void check_processes()
  807. {
  808. #ifdef S_PROCESSCHECK
  809. char *proclist,
  810. *out,
  811. *p,
  812. *np,
  813. *curp,
  814. buf[1024],
  815. bin[128];
  816. if (!strcmp((char *) CFG_BADPROCESS.ldata ? CFG_BADPROCESS.ldata : CFG_BADPROCESS.gdata ? CFG_BADPROCESS.gdata : "", STR("nocheck")))
  817. return;
  818. proclist = (char *) (CFG_PROCESSLIST.ldata && ((char *) CFG_PROCESSLIST.ldata)[0] ?
  819. CFG_PROCESSLIST.ldata : CFG_PROCESSLIST.gdata && ((char *) CFG_PROCESSLIST.gdata)[0] ? CFG_PROCESSLIST.gdata : NULL);
  820. if (!proclist)
  821. return;
  822. if (!shell_exec(STR("ps x"), NULL, &out, NULL))
  823. return;
  824. /* Get this binary's filename */
  825. strncpyz(buf, binname, sizeof(buf));
  826. p = strrchr(buf, '/');
  827. if (p) {
  828. p++;
  829. strncpyz(bin, p, sizeof(bin));
  830. } else {
  831. bin[0] = 0;
  832. }
  833. /* Fix up the "permitted processes" list */
  834. p = nmalloc(strlen(proclist) + strlen(bin) + 6);
  835. strcpy(p, proclist);
  836. strcat(p, " ");
  837. strcat(p, bin);
  838. strcat(p, " ");
  839. proclist = p;
  840. curp = out;
  841. while (curp) {
  842. np = strchr(curp, '\n');
  843. if (np)
  844. *np++ = 0;
  845. if (atoi(curp) > 0) {
  846. char *pid,
  847. *tty,
  848. *stat,
  849. *time,
  850. cmd[512],
  851. line[2048];
  852. strncpyz(line, curp, sizeof(line));
  853. /* it's a process line */
  854. /* Assuming format: pid tty stat time cmd */
  855. pid = newsplit(&curp);
  856. tty = newsplit(&curp);
  857. stat = newsplit(&curp);
  858. time = newsplit(&curp);
  859. strncpyz(cmd, curp, sizeof(cmd));
  860. /* skip any <defunct> procs "/bin/sh -c" crontab stuff and binname crontab stuff */
  861. if (!strstr(cmd, STR("<defunct>")) && !strncmp(cmd, STR("/bin/sh -c"), 10)
  862. && !strncmp(cmd, binname, strlen(binname))) {
  863. /* get rid of any args */
  864. if ((p = strchr(cmd, ' ')))
  865. *p = 0;
  866. /* remove [] or () */
  867. if (strlen(cmd)) {
  868. p = cmd + strlen(cmd) - 1;
  869. if (((cmd[0] == '(') && (*p == ')')) || ((cmd[0] == '[') && (*p == ']'))) {
  870. *p = 0;
  871. strcpy(buf, cmd + 1);
  872. strcpy(cmd, buf);
  873. }
  874. }
  875. /* remove path */
  876. if ((p = strrchr(cmd, '/'))) {
  877. p++;
  878. strcpy(buf, p);
  879. strcpy(cmd, buf);
  880. }
  881. /* skip "ps" */
  882. if (strcmp(cmd, "ps")) {
  883. /* see if proc's in permitted list */
  884. strcat(cmd, " ");
  885. if ((p = strstr(proclist, cmd))) {
  886. /* Remove from permitted list */
  887. while (*p != ' ')
  888. *p++ = 1;
  889. } else {
  890. char wrk[16384];
  891. sprintf(wrk, STR("Unexpected process: %s"), line);
  892. detected(DETECT_PROCESS, wrk);
  893. }
  894. }
  895. }
  896. }
  897. curp = np;
  898. }
  899. nfree(proclist);
  900. if (out)
  901. nfree(out);
  902. #endif /* S_PROCESSCHECK */
  903. }
  904. void check_promisc()
  905. {
  906. #ifdef S_PROMISC
  907. #ifdef SIOCGIFCONF
  908. char buf[8192];
  909. struct ifreq ifreq, *ifr;
  910. struct ifconf ifcnf;
  911. char *cp, *cplim;
  912. int sock;
  913. if (!strcmp((char *) CFG_PROMISC.ldata ? CFG_PROMISC.ldata : CFG_PROMISC.gdata ? CFG_PROMISC.gdata : "", STR("nocheck")))
  914. return;
  915. sock = socket(AF_INET, SOCK_STREAM, 0);
  916. ifcnf.ifc_len = 8191;
  917. ifcnf.ifc_buf = buf;
  918. if (ioctl(sock, SIOCGIFCONF, (char *) &ifcnf) < 0) {
  919. close(sock);
  920. return;
  921. }
  922. ifr = ifcnf.ifc_req;
  923. cplim = buf + ifcnf.ifc_len;
  924. for (cp = buf; cp < cplim; cp += sizeof(ifr->ifr_name) + sizeof(ifr->ifr_addr)) {
  925. ifr = (struct ifreq *) cp;
  926. ifreq = *ifr;
  927. if (!ioctl(sock, SIOCGIFFLAGS, (char *) &ifreq)) {
  928. if (ifreq.ifr_flags & IFF_PROMISC) {
  929. close(sock);
  930. detected(DETECT_PROMISC, STR("Detected promiscuous mode"));
  931. return;
  932. }
  933. }
  934. }
  935. close(sock);
  936. #endif /* SIOCGIFCONF */
  937. #endif /* S_PROMISC */
  938. }
  939. #ifdef S_ANTITRACE
  940. int traced = 0;
  941. void got_trace(int z)
  942. {
  943. traced = 0;
  944. }
  945. #endif /* S_ANTITRACE */
  946. void check_trace(int n)
  947. {
  948. #ifdef S_ANTITRACE
  949. int x, parent, i;
  950. struct sigaction sv, *oldsv = NULL;
  951. if (n && !strcmp((char *) CFG_TRACE.ldata ? CFG_TRACE.ldata : CFG_TRACE.gdata ? CFG_TRACE.gdata : "", STR("nocheck")))
  952. return;
  953. parent = getpid();
  954. #ifdef __linux__
  955. egg_bzero(&sv, sizeof(sv));
  956. sv.sa_handler = got_trace;
  957. sigemptyset(&sv.sa_mask);
  958. oldsv = NULL;
  959. sigaction(SIGTRAP, &sv, oldsv);
  960. traced = 1;
  961. asm("INT3");
  962. sigaction(SIGTRAP, oldsv, NULL);
  963. if (traced)
  964. detected(DETECT_TRACE, STR("I'm being traced!"));
  965. else {
  966. x = fork();
  967. if (x == -1)
  968. return;
  969. else if (x == 0) {
  970. i = ptrace(PTRACE_ATTACH, parent, 0, 0);
  971. if (i == (-1) && errno == EPERM)
  972. detected(DETECT_TRACE, STR("I'm being traced!"));
  973. else {
  974. waitpid(parent, &i, 0);
  975. kill(parent, SIGCHLD);
  976. ptrace(PTRACE_DETACH, parent, 0, 0);
  977. kill(parent, SIGCHLD);
  978. }
  979. exit(0);
  980. } else
  981. wait(&i);
  982. }
  983. #endif /* __linux__ */
  984. #ifdef __FreeBSD__
  985. x = fork();
  986. if (x == -1)
  987. return;
  988. else if (x == 0) {
  989. i = ptrace(PT_ATTACH, parent, 0, 0);
  990. if (i == (-1) && errno == EBUSY)
  991. detected(DETECT_TRACE, STR("I'm being traced"));
  992. else {
  993. wait(&i);
  994. i = ptrace(PT_CONTINUE, parent, (caddr_t) 1, 0);
  995. kill(parent, SIGCHLD);
  996. wait(&i);
  997. i = ptrace(PT_DETACH, parent, (caddr_t) 1, 0);
  998. wait(&i);
  999. }
  1000. exit(0);
  1001. } else
  1002. waitpid(x, NULL, 0);
  1003. #endif /* __FreeBSD__ */
  1004. #ifdef __OpenBSD__
  1005. x = fork();
  1006. if (x == -1)
  1007. return;
  1008. else if (x == 0) {
  1009. i = ptrace(PT_ATTACH, parent, 0, 0);
  1010. if (i == (-1) && errno == EBUSY)
  1011. detected(DETECT_TRACE, STR("I'm being traced"));
  1012. else {
  1013. wait(&i);
  1014. i = ptrace(PT_CONTINUE, parent, (caddr_t) 1, 0);
  1015. kill(parent, SIGCHLD);
  1016. wait(&i);
  1017. i = ptrace(PT_DETACH, parent, (caddr_t) 1, 0);
  1018. wait(&i);
  1019. }
  1020. exit(0);
  1021. } else
  1022. waitpid(x, NULL, 0);
  1023. #endif /* __OpenBSD__ */
  1024. #endif /* S_ANTITRACE */
  1025. }
  1026. int shell_exec(char *cmdline, char *input, char **output, char **erroutput)
  1027. {
  1028. FILE *inpFile,
  1029. *outFile,
  1030. *errFile;
  1031. char tmpfile[161];
  1032. int x, fd;
  1033. int parent = getpid();
  1034. if (!cmdline)
  1035. return 0;
  1036. /* Set up temp files */
  1037. /* always use mkstemp() when handling temp filess! -dizz */
  1038. sprintf(tmpfile, STR("%s.in-XXXXXX"), tempdir);
  1039. if ((fd = mkstemp(tmpfile)) == -1 || (inpFile = fdopen(fd, "w+")) == NULL) {
  1040. if (fd != -1) {
  1041. unlink(tmpfile);
  1042. close(fd);
  1043. }
  1044. putlog(LOG_ERRORS, "*" , STR("exec: Couldn't open '%s': %s"), tmpfile, strerror(errno));
  1045. return 0;
  1046. }
  1047. unlink(tmpfile);
  1048. if (input) {
  1049. if (fwrite(input, 1, strlen(input), inpFile) != strlen(input)) {
  1050. fclose(inpFile);
  1051. putlog(LOG_ERRORS, "*", STR("exec: Couldn't write to '%s': %s"), tmpfile, strerror(errno));
  1052. return 0;
  1053. }
  1054. fseek(inpFile, 0, SEEK_SET);
  1055. }
  1056. unlink(tmpfile);
  1057. sprintf(tmpfile, STR("%s.err-XXXXXX"), tempdir);
  1058. if ((fd = mkstemp(tmpfile)) == -1 || (errFile = fdopen(fd, "w+")) == NULL) {
  1059. if (fd != -1) {
  1060. unlink(tmpfile);
  1061. close(fd);
  1062. }
  1063. putlog(LOG_ERRORS, "*", STR("exec: Couldn't open '%s': %s"), tmpfile, strerror(errno));
  1064. return 0;
  1065. }
  1066. unlink(tmpfile);
  1067. sprintf(tmpfile, STR("%s.out-XXXXXX"), tempdir);
  1068. if ((fd = mkstemp(tmpfile)) == -1 || (outFile = fdopen(fd, "w+")) == NULL) {
  1069. if (fd != -1) {
  1070. unlink(tmpfile);
  1071. close(fd);
  1072. }
  1073. putlog(LOG_ERRORS, "*", STR("exec: Couldn't open '%s': %s"), tmpfile, strerror(errno));
  1074. return 0;
  1075. }
  1076. unlink(tmpfile);
  1077. x = fork();
  1078. if (x == -1) {
  1079. putlog(LOG_ERRORS, "*", STR("exec: fork() failed: %s"), strerror(errno));
  1080. fclose(inpFile);
  1081. fclose(errFile);
  1082. fclose(outFile);
  1083. return 0;
  1084. }
  1085. if (x) {
  1086. /* Parent: wait for the child to complete */
  1087. int st = 0;
  1088. waitpid(x, &st, 0);
  1089. /* Now read the files into the buffers */
  1090. fclose(inpFile);
  1091. fflush(outFile);
  1092. fflush(errFile);
  1093. if (erroutput) {
  1094. char *buf;
  1095. int fs;
  1096. fseek(errFile, 0, SEEK_END);
  1097. fs = ftell(errFile);
  1098. if (fs == 0) {
  1099. (*erroutput) = NULL;
  1100. } else {
  1101. buf = nmalloc(fs + 1);
  1102. fseek(errFile, 0, SEEK_SET);
  1103. fread(buf, 1, fs, errFile);
  1104. buf[fs] = 0;
  1105. (*erroutput) = buf;
  1106. }
  1107. }
  1108. fclose(errFile);
  1109. if (output) {
  1110. char *buf;
  1111. int fs;
  1112. fseek(outFile, 0, SEEK_END);
  1113. fs = ftell(outFile);
  1114. if (fs == 0) {
  1115. (*output) = NULL;
  1116. } else {
  1117. buf = nmalloc(fs + 1);
  1118. fseek(outFile, 0, SEEK_SET);
  1119. fread(buf, 1, fs, outFile);
  1120. buf[fs] = 0;
  1121. (*output) = buf;
  1122. }
  1123. }
  1124. fclose(outFile);
  1125. return 1;
  1126. } else {
  1127. /* Child: make fd's and set them up as std* */
  1128. int ind,
  1129. outd,
  1130. errd;
  1131. char *argv[4];
  1132. ind = fileno(inpFile);
  1133. outd = fileno(outFile);
  1134. errd = fileno(errFile);
  1135. if (dup2(ind, STDIN_FILENO) == (-1)) {
  1136. kill(parent, SIGCHLD);
  1137. exit(1);
  1138. }
  1139. if (dup2(outd, STDOUT_FILENO) == (-1)) {
  1140. kill(parent, SIGCHLD);
  1141. exit(1);
  1142. }
  1143. if (dup2(errd, STDERR_FILENO) == (-1)) {
  1144. kill(parent, SIGCHLD);
  1145. exit(1);
  1146. }
  1147. argv[0] = STR("sh");
  1148. argv[1] = STR("-c");
  1149. argv[2] = cmdline;
  1150. argv[3] = NULL;
  1151. execvp(argv[0], &argv[0]);
  1152. kill(parent, SIGCHLD);
  1153. exit(1);
  1154. }
  1155. }
  1156. /* Update system code
  1157. */
  1158. int ucnt = 0;
  1159. void updatelocal(void)
  1160. {
  1161. #ifdef LEAF
  1162. module_entry *me;
  1163. #endif /* LEAF */
  1164. Context;
  1165. if (ucnt < 300) {
  1166. ucnt++;
  1167. return;
  1168. }
  1169. del_hook(HOOK_SECONDLY, (Function) updatelocal);
  1170. ucnt = 0;
  1171. /* let's drop the server connection ASAP */
  1172. #ifdef LEAF
  1173. if ((me = module_find("server", 0, 0))) {
  1174. Function *func = me->funcs;
  1175. (func[SERVER_NUKESERVER]) ("Updating...");
  1176. }
  1177. #endif /* LEAF */
  1178. botnet_send_chat(-1, botnetnick, "Updating...");
  1179. botnet_send_bye();
  1180. fatal("Updating...", 1);
  1181. usleep(2000 * 500);
  1182. bg_send_quit(BG_ABORT);
  1183. unlink(pid_file); //if this fails it is ok, cron will restart the bot, *hopefully*
  1184. system(binname); //start new bot.
  1185. exit(0);
  1186. }
  1187. int updatebin (int idx, char *par, int autoi)
  1188. {
  1189. char *path = NULL,
  1190. *newbin;
  1191. char buf[DIRMAX], old[DIRMAX], testbuf[DIRMAX];
  1192. struct stat sb;
  1193. int i;
  1194. #ifdef LEAF
  1195. module_entry *me;
  1196. #endif /* LEAF */
  1197. buf[0] = testbuf[0] = old[0] = 0;
  1198. path = newsplit(&par);
  1199. par = path;
  1200. if (!par[0]) {
  1201. if (idx)
  1202. dprintf(idx, STR("Not enough parameters.\n"));
  1203. return 1;
  1204. }
  1205. path = nmalloc(strlen(binname) + strlen(par));
  1206. strcpy(path, binname);
  1207. newbin = strrchr(path, '/');
  1208. if (!newbin) {
  1209. nfree(path);
  1210. if (idx)
  1211. dprintf(idx, STR("Don't know current binary name\n"));
  1212. return 1;
  1213. }
  1214. newbin++;
  1215. if (strchr(par, '/')) {
  1216. *newbin = 0;
  1217. if (idx)
  1218. dprintf(idx, STR("New binary must be in %s and name must be specified without path information\n"), path);
  1219. nfree(path);
  1220. return 1;
  1221. }
  1222. strcpy(newbin, par);
  1223. if (!strcmp(path, binname)) {
  1224. nfree(path);
  1225. if (idx)
  1226. dprintf(idx, STR("Can't update with the current binary\n"));
  1227. return 1;
  1228. }
  1229. if (stat(path, &sb)) {
  1230. if (idx)
  1231. dprintf(idx, STR("%s can't be accessed\n"), path);
  1232. nfree(path);
  1233. return 1;
  1234. }
  1235. if (chmod(path, S_IRUSR | S_IWUSR | S_IXUSR)) {
  1236. if (idx)
  1237. dprintf(idx, STR("Can't set mode 0600 on %s\n"), path);
  1238. nfree(path);
  1239. return 1;
  1240. }
  1241. //make a backup just in case.
  1242. egg_snprintf(old, sizeof old, "%s.bin.old", tempdir);
  1243. copyfile(binname, old);
  1244. /* The binary should return '2' when ran with -2, if not it's probably corrupt. */
  1245. snprintf(testbuf, sizeof testbuf, "%s -2", path);
  1246. i = system(testbuf);
  1247. if (i == -1 || WEXITSTATUS(i) != 2) {
  1248. if (idx)
  1249. dprintf(idx, STR("Couldn't restart new binary (error %d)\n"), i);
  1250. putlog(LOG_MISC, "*", STR("Couldn't restart new binary (error %d)\n"), i);
  1251. return i;
  1252. }
  1253. if (movefile(path, binname)) {
  1254. if (idx)
  1255. dprintf(idx, STR("Can't rename %s to %s\n"), path, binname);
  1256. nfree(path);
  1257. return 1;
  1258. }
  1259. sprintf(buf, "%s", binname);
  1260. #ifdef LEAF
  1261. if (localhub) {
  1262. /* if localhub = 1, this is the spawn bot and controls
  1263. * the spawning of new bots. */
  1264. sprintf(buf, "%s -L %s -P %d", buf, botnetnick, getpid());
  1265. }
  1266. #endif /* LEAF */
  1267. //safe to run new binary..
  1268. #ifdef LEAF
  1269. if (!autoi && !localhub) //dont delete pid for auto update!!!
  1270. #endif /* LEAF */
  1271. unlink(pid_file); //delete pid so new binary doesnt exit.
  1272. #ifdef HUB
  1273. listen_all(my_port, 1); //close the listening port...
  1274. usleep(5000);
  1275. #endif /* HUB */
  1276. putlog(LOG_DEBUG, "*", "Running for update: %s", buf);
  1277. #ifdef LEAF
  1278. if (!autoi && localhub) {
  1279. /* let's drop the server connection ASAP */
  1280. if ((me = module_find("server", 0, 0))) {
  1281. Function *func = me->funcs;
  1282. (func[SERVER_NUKESERVER]) ("Updating...");
  1283. }
  1284. #endif /* LEAF */
  1285. if (idx)
  1286. dprintf(idx, STR("Updating...bye\n"));
  1287. putlog(LOG_MISC, "*", STR("Updating...\n"));
  1288. botnet_send_chat(-1, botnetnick, "Updating...");
  1289. botnet_send_bye();
  1290. fatal("Updating...", 1);
  1291. usleep(2000 * 500);
  1292. bg_send_quit(BG_ABORT);
  1293. system(buf); /* run the binary, it SHOULD work from earlier tests.. */
  1294. exit(0);
  1295. #ifdef LEAF
  1296. } else {
  1297. if (localhub && autoi) {
  1298. add_hook(HOOK_SECONDLY, (Function) updatelocal);
  1299. return 0;
  1300. }
  1301. }
  1302. #endif /* LEAF */
  1303. /* this should never be reached */
  1304. return 2;
  1305. }
  1306. int bot_aggressive_to(struct userrec *u)
  1307. {
  1308. char mypval[20],
  1309. botpval[20];
  1310. link_pref_val(u, botpval);
  1311. link_pref_val(get_user_by_handle(userlist, botnetnick), mypval);
  1312. if (strcmp(mypval, botpval) < 0)
  1313. return 1;
  1314. else
  1315. return 0;
  1316. }
  1317. void detected(int code, char *msg)
  1318. {
  1319. #ifdef LEAF
  1320. module_entry *me;
  1321. #endif /* LEAF */
  1322. char *p = NULL;
  1323. char tmp[512];
  1324. struct userrec *u;
  1325. struct flag_record fr = { FR_GLOBAL, 0, 0 };
  1326. int act;
  1327. u = get_user_by_handle(userlist, botnetnick);
  1328. #ifdef S_LASTCHECK
  1329. if (code == DETECT_LOGIN)
  1330. p = (char *) (CFG_LOGIN.ldata ? CFG_LOGIN.ldata : (CFG_LOGIN.gdata ? CFG_LOGIN.gdata : NULL));
  1331. #endif /* S_LASTCHECK */
  1332. #ifdef S_ANTITRACE
  1333. if (code == DETECT_TRACE)
  1334. p = (char *) (CFG_TRACE.ldata ? CFG_TRACE.ldata : (CFG_TRACE.gdata ? CFG_TRACE.gdata : NULL));
  1335. #endif /* S_ANTITRACE */
  1336. #ifdef S_PROMISC
  1337. if (code == DETECT_PROMISC)
  1338. p = (char *) (CFG_PROMISC.ldata ? CFG_PROMISC.ldata : (CFG_PROMISC.gdata ? CFG_PROMISC.gdata : NULL));
  1339. #endif /* S_PROMISC */
  1340. #ifdef S_PROCESSCHECK
  1341. if (code == DETECT_PROCESS)
  1342. p = (char *) (CFG_BADPROCESS.ldata ? CFG_BADPROCESS.ldata : (CFG_BADPROCESS.gdata ? CFG_BADPROCESS.gdata : NULL));
  1343. #endif /* S_PROMISC */
  1344. #ifdef S_HIJACKCHECK
  1345. if (code == DETECT_SIGCONT)
  1346. p = (char *) (CFG_HIJACK.ldata ? CFG_HIJACK.ldata : (CFG_HIJACK.gdata ? CFG_HIJACK.gdata : NULL));
  1347. #endif /* S_PROMISC */
  1348. if (!p)
  1349. act = DET_WARN;
  1350. else if (!strcmp(p, STR("die")))
  1351. act = DET_DIE;
  1352. else if (!strcmp(p, STR("reject")))
  1353. act = DET_REJECT;
  1354. else if (!strcmp(p, STR("suicide")))
  1355. act = DET_SUICIDE;
  1356. else if (!strcmp(p, STR("nocheck")))
  1357. act = DET_NOCHECK;
  1358. else if (!strcmp(p, STR("ignore")))
  1359. act = DET_IGNORE;
  1360. else
  1361. act = DET_WARN;
  1362. switch (act) {
  1363. case DET_IGNORE:
  1364. break;
  1365. case DET_WARN:
  1366. putlog(LOG_WARN, "*", msg);
  1367. break;
  1368. case DET_REJECT:
  1369. do_fork();
  1370. putlog(LOG_WARN, "*", STR("Setting myself +d: %s"), msg);
  1371. sprintf(tmp, STR("+d: %s"), msg);
  1372. set_user(&USERENTRY_COMMENT, u, tmp);
  1373. get_user_flagrec(u, &fr, 0);
  1374. fr.global = USER_DEOP | USER_BOT;
  1375. set_user_flagrec(u, &fr, 0);
  1376. sleep(1);
  1377. break;
  1378. case DET_DIE:
  1379. putlog(LOG_WARN, "*", STR("Dying: %s"), msg);
  1380. sprintf(tmp, STR("Dying: %s"), msg);
  1381. set_user(&USERENTRY_COMMENT, u, tmp);
  1382. #ifdef LEAF
  1383. if ((me = module_find("server", 0, 0))) {
  1384. Function *func = me->funcs;
  1385. (func[SERVER_NUKESERVER]) ("BBL");
  1386. }
  1387. #endif /* LEAF */
  1388. sleep(1);
  1389. fatal(msg, 0);
  1390. break;
  1391. case DET_SUICIDE:
  1392. putlog(LOG_WARN, "*", STR("Comitting suicide: %s"), msg);
  1393. sprintf(tmp, STR("Suicide: %s"), msg);
  1394. set_user(&USERENTRY_COMMENT, u, tmp);
  1395. #ifdef LEAF
  1396. if ((me = module_find("server", 0, 0))) {
  1397. Function *func = me->funcs;
  1398. (func[SERVER_NUKESERVER]) ("HARAKIRI!!");
  1399. }
  1400. #endif /* LEAF */
  1401. sleep(1);
  1402. unlink(binname);
  1403. #ifdef HUB
  1404. unlink(userfile);
  1405. sprintf(tmp, STR("%s~"), userfile);
  1406. unlink(tmp);
  1407. #endif /* HUB */
  1408. fatal(msg, 0);
  1409. break;
  1410. case DET_NOCHECK:
  1411. break;
  1412. }
  1413. }
  1414. char kickprefix[25] = "";
  1415. char bankickprefix[25] = "";
  1416. char * kickreason(int kind) {
  1417. int r;
  1418. r=random();
  1419. switch (kind) {
  1420. case KICK_BANNED:
  1421. switch (r % 6) {
  1422. case 0: return STR("bye");
  1423. case 1: return STR("banned");
  1424. case 2: return STR("see you in hell");
  1425. case 3: return STR("go away");
  1426. case 4: return STR("cya around lewser");
  1427. case 5: return STR("unwanted!");
  1428. }
  1429. case KICK_KUSER:
  1430. switch (r % 4) {
  1431. case 0: return STR("not wanted");
  1432. case 1: return STR("something tells me you're annoying");
  1433. case 2: return STR("don't bug me lewser");
  1434. case 3: return STR("creep");
  1435. }
  1436. case KICK_KICKBAN:
  1437. switch (r % 4) {
  1438. case 0: return STR("gone");
  1439. case 1: return STR("stupid");
  1440. case 2: return STR("lewser");
  1441. case 3: return STR("...");
  1442. }
  1443. case KICK_MASSDEOP:
  1444. switch (r % 8) {
  1445. case 0: return STR("spammer!");
  1446. case 1: return STR("easy on the modes now");
  1447. case 2: return STR("mode this");
  1448. case 3: return STR("nice try");
  1449. case 4: return STR("really?");
  1450. case 5: return STR("you lose");
  1451. case 6: return STR("scary... really scary...");
  1452. case 7: return STR("i win kthx");
  1453. }
  1454. case KICK_BADOP:
  1455. switch (r % 5) {
  1456. case 0: return STR("neat...");
  1457. case 1: return STR("oh, no you don't. go away.");
  1458. case 2: return STR("didn't you forget something now?");
  1459. case 3: return STR("no");
  1460. case 4: return STR("hijack this");
  1461. }
  1462. case KICK_BADOPPED:
  1463. switch (r % 5) {
  1464. case 0: return STR("fuck off kid");
  1465. case 1: return STR("asl?");
  1466. case 2: return STR("whoa... what a hacker... skills!");
  1467. case 3: return STR("yes! yes! yes! hit me baby one more time!");
  1468. case 4: return STR("with your skills, you're better off jacking off than hijacking");
  1469. }
  1470. case KICK_MANUALOP:
  1471. switch (r % 6) {
  1472. case 0: return STR("naughty kid");
  1473. case 1: return STR("didn't someone tell you that is bad?");
  1474. case 2: return STR("want perm?");
  1475. case 3: return STR("see how much good that did you?");
  1476. case 4: return STR("not a smart move...");
  1477. case 5: return STR("jackass!");
  1478. }
  1479. case KICK_MANUALOPPED:
  1480. switch (r % 8) {
  1481. case 0: return STR("your pal got mean friends. like me.");
  1482. case 1: return STR("uhh now.. don't wake me up...");
  1483. case 2: return STR("hi hun. missed me?");
  1484. case 3: return STR("spammer! die!");
  1485. case 4: return STR("boo!");
  1486. case 5: return STR("that @ was useful, don't ya think?");
  1487. case 6: return STR("not in my book");
  1488. case 7: return STR("lol, really?");
  1489. }
  1490. case KICK_CLOSED:
  1491. switch (r % 17) {
  1492. case 0: return STR("locked");
  1493. case 1: return STR("later");
  1494. case 2: return STR("closed for now");
  1495. case 3: return STR("come back later");
  1496. case 4: return STR("better safe than sorry");
  1497. case 5: return STR("cleanup, come back later");
  1498. case 6: return STR("this channel is closed");
  1499. case 7: return STR("shutting down for now");
  1500. case 8: return STR("lockdown");
  1501. case 9: return STR("reopening later");
  1502. case 10: return STR("not for the public atm");
  1503. case 11: return STR("private channel for now");
  1504. case 12: return STR("might reopen soon, might reopen later");
  1505. case 13: return STR("you're not supposed to be here right now");
  1506. case 14: return STR("sorry, closed");
  1507. case 15: return STR("try us later, atm we're locked down");
  1508. case 16: return STR("closed. try tomorrow");
  1509. }
  1510. case KICK_FLOOD:
  1511. switch (r % 7) {
  1512. case 0: return STR("so much bullshit in such a short time. amazing.");
  1513. case 1: return STR("slow down. i'm trying to read here.");
  1514. case 2: return STR("uhm... you actually think irc is for talking?");
  1515. case 3: return STR("talk talk talk");
  1516. case 4: return STR("blabbering are we?");
  1517. case 5: return STR("... and i don't even like you!");
  1518. case 6: return STR("and you're outa here...");
  1519. }
  1520. case KICK_NICKFLOOD:
  1521. switch (r % 7) {
  1522. case 0: return STR("make up your mind?");
  1523. case 1: return STR("be schizofrenic elsewhere");
  1524. case 2: return STR("I'm loosing track of you... not!");
  1525. case 3: return STR("that is REALLY annoying");
  1526. case 4: return STR("try this: /NICK n00b");
  1527. case 5: return STR("playing hide 'n' seek?");
  1528. case 6: return STR("gotcha!");
  1529. }
  1530. case KICK_KICKFLOOD:
  1531. switch (r % 6) {
  1532. case 0: return STR("easier to just leave if you wan't to be alone");
  1533. case 1: return STR("cool down");
  1534. case 2: return STR("don't be so damned aggressive. that's my job.");
  1535. case 3: return STR("kicking's fun, isn't it?");
  1536. case 4: return STR("what's the rush?");
  1537. case 5: return STR("next time you do that, i'll kick you again");
  1538. }
  1539. case KICK_BOGUSUSERNAME:
  1540. return STR("bogus username");
  1541. case KICK_MEAN:
  1542. switch (r % 11) {
  1543. case 0: return STR("hey! that wasn't very nice!");
  1544. case 1: return STR("don't fuck with my pals");
  1545. case 2: return STR("meanie!");
  1546. case 3: return STR("I can be a bitch too...");
  1547. case 4: return STR("leave the bots alone, will ya?");
  1548. case 5: return STR("not very clever");
  1549. case 6: return STR("watch it");
  1550. case 7: return STR("fuck off");
  1551. case 8: return STR("easy now. that's a friend.");
  1552. case 9: return STR("abuse of power. leave that to me, will ya?");
  1553. case 10: return STR("there as some things you cannot do, and that was one of them...");
  1554. }
  1555. case KICK_BOGUSKEY:
  1556. return STR("I have a really hard time reading that key");
  1557. default:
  1558. return "OMFG@YUO";
  1559. }
  1560. }
  1561. void makeplaincookie(char *chname, char *nick, char *buf)
  1562. {
  1563. /*
  1564. plain cookie:
  1565. Last 6 digits of time
  1566. Last 5 chars of nick
  1567. Last 4 regular chars of chan
  1568. */
  1569. char work[256],
  1570. work2[256];
  1571. int i,
  1572. n;
  1573. sprintf(work, STR("%010li"), (now + timesync));
  1574. strcpy(buf, (char *) &work[4]);
  1575. work[0] = 0;
  1576. if (strlen(nick) < 5)
  1577. while (strlen(work) + strlen(nick) < 5)
  1578. strcat(work, " ");
  1579. else
  1580. strcpy(work, (char *) &nick[strlen(nick) - 5]);
  1581. strcat(buf, work);
  1582. n = 3;
  1583. for (i = strlen(chname) - 1; (i >= 0) && (n >= 0); i--)
  1584. if (((unsigned char) chname[i] < 128) && ((unsigned char) chname[i] > 32)) {
  1585. work2[n] = tolower(chname[i]);
  1586. n--;
  1587. }
  1588. while (n >= 0)
  1589. work2[n--] = ' ';
  1590. work2[4] = 0;
  1591. strcat(buf, work2);
  1592. }
  1593. int goodpass(char *pass, int idx, char *nick)
  1594. {
  1595. char *tell;
  1596. #ifdef S_NAZIPASS
  1597. int i, nalpha = 0, lcase = 0, ucase = 0, ocase = 0, tc;
  1598. #endif /* S_NAZIPASS */
  1599. if (!pass[0])
  1600. return 0;
  1601. tell = nmalloc(300);
  1602. #ifdef S_NAZIPASS
  1603. for (i = 0; i < strlen(pass); i++) {
  1604. tc = (int) pass[i];
  1605. if (tc < 58 && tc > 47)
  1606. ocase++; //number
  1607. else if (tc < 91 && tc > 64)
  1608. ucase++; //upper case
  1609. else if (tc < 123 && tc > 96)
  1610. lcase++; //lower case
  1611. else
  1612. nalpha++; //non-alphabet/number
  1613. }
  1614. /* if (ocase < 1 || lcase < 2 || ucase < 2 || nalpha < 1 || strlen(pass) < 8) { */
  1615. if (ocase < 1 || lcase < 2 || ucase < 2 || strlen(pass) < 8) {
  1616. #else /* !S_NAZIPASS */
  1617. if (strlen(pass) < 8) {
  1618. #endif /* S_NAZIPASS */
  1619. sprintf(tell, "Insecure pass, must be: ");
  1620. #ifdef S_NAZIPASS
  1621. if (ocase < 1)
  1622. strcat(tell, "\002>= 1 number\002, ");
  1623. else
  1624. strcat(tell, ">= 1 number, ");
  1625. if (lcase < 2)
  1626. strcat(tell, "\002>= 2 lcase\002, ");
  1627. else
  1628. strcat(tell, ">= 2 lowercase, ");
  1629. if (ucase < 2)
  1630. strcat(tell, "\002>= 2 ucase\002, ");
  1631. else
  1632. strcat(tell, ">= 2 uppercase, ");
  1633. /* This is annoying as hell
  1634. if (nalpha < 1)
  1635. strcat(tell, "\002>= 1 non-alpha/num\002, ");
  1636. else
  1637. strcat(tell, ">= 1 non-alpha/num, ");
  1638. */
  1639. #endif /* S_NAZIPASS */
  1640. if (strlen(pass) < 8)
  1641. strcat(tell, "\002>= 8 chars.\002");
  1642. else
  1643. strcat(tell, ">= 8 chars.");
  1644. if (idx)
  1645. dprintf(idx, "%s\n", tell);
  1646. else if (nick[0])
  1647. dprintf(DP_HELP, STR("NOTICE %s :%s\n"), nick, tell);
  1648. nfree(tell);
  1649. return 0;
  1650. }
  1651. nfree(tell);
  1652. return 1;
  1653. }
  1654. char *replace (char *string, char *oldie, char *newbie)
  1655. {
  1656. static char newstring[1024] = "";
  1657. int str_index, newstr_index, oldie_index, end, new_len, old_len, cpy_len;
  1658. char *c;
  1659. if (string == NULL) return "";
  1660. if ((c = (char *) strstr(string, oldie)) == NULL) return string;
  1661. new_len = strlen(newbie);
  1662. old_len = strlen(oldie);
  1663. end = strlen(string) - old_len;
  1664. oldie_index = c - string;
  1665. newstr_index = 0;
  1666. str_index = 0;
  1667. while(str_index <= end && c != NULL) {
  1668. cpy_len = oldie_index-str_index;
  1669. strncpy(newstring + newstr_index, string + str_index, cpy_len);
  1670. newstr_index += cpy_len;
  1671. str_index += cpy_len;
  1672. strcpy(newstring + newstr_index, newbie);
  1673. newstr_index += new_len;
  1674. str_index += old_len;
  1675. if((c = (char *) strstr(string + str_index, oldie)) != NULL)
  1676. oldie_index = c - string;
  1677. }
  1678. strcpy(newstring + newstr_index, string + str_index);
  1679. return (newstring);
  1680. }
  1681. char *getfullbinname(char *argv0)
  1682. {
  1683. char *cwd, *bin, *p, *p2;
  1684. bin = nmalloc(strlen(argv0) + 1);
  1685. strcpy(bin, argv0);
  1686. if (bin[0] == '/') {
  1687. return bin;
  1688. }
  1689. cwd = nmalloc(8192);
  1690. getcwd(cwd, 8191);
  1691. cwd[8191] = 0;
  1692. if (cwd[strlen(cwd) - 1] == '/')
  1693. cwd[strlen(cwd) - 1] = 0;
  1694. p = bin;
  1695. p2 = strchr(p, '/');
  1696. while (p) {
  1697. if (p2)
  1698. *p2++ = 0;
  1699. if (!strcmp(p, "..")) {
  1700. p = strrchr(cwd, '/');
  1701. if (p)
  1702. *p = 0;
  1703. } else if (strcmp(p, ".")) {
  1704. strcat(cwd, "/");
  1705. strcat(cwd, p);
  1706. }
  1707. p = p2;
  1708. if (p)
  1709. p2 = strchr(p, '/');
  1710. }
  1711. nfree(bin);
  1712. bin = nmalloc(strlen(cwd) + 1);
  1713. strcpy(bin, cwd);
  1714. nfree(cwd);
  1715. return bin;
  1716. }
  1717. void sdprintf EGG_VARARGS_DEF(char *, arg1)
  1718. {
  1719. if (sdebug) {
  1720. char *format;
  1721. char s[2001];
  1722. va_list va;
  1723. format = EGG_VARARGS_START(char *, arg1, va);
  1724. egg_vsnprintf(s, 2000, format, va);
  1725. va_end(va);
  1726. if (!backgrd)
  1727. dprintf(DP_STDOUT, "[D:%d] %s\n", getpid(), s);
  1728. else
  1729. putlog(LOG_MISC, "*", "[D:%d] %s", getpid(), s);
  1730. }
  1731. }
  1732. char *werr_tostr(int errnum)
  1733. {
  1734. switch (errnum) {
  1735. case ERR_BINSTAT:
  1736. return STR("Cannot access binary");
  1737. case ERR_BINMOD:
  1738. return STR("Cannot chmod() binary");
  1739. case ERR_PASSWD:
  1740. return STR("Cannot access the global passwd file");
  1741. case ERR_WRONGBINDIR:
  1742. return STR("Wrong directory/binary name");
  1743. case ERR_CONFSTAT:
  1744. #ifdef LEAF
  1745. return STR("Cannot access config directory (~/.ssh/)");
  1746. #else
  1747. return STR("Cannot access config directory (./)");
  1748. #endif /* LEAF */
  1749. case ERR_TMPSTAT:
  1750. #ifdef LEAF
  1751. return STR("Cannot access tmp directory (~/.ssh/.../)");
  1752. #else
  1753. return STR("Cannot access config directory (./tmp/)");
  1754. #endif /* LEAF */
  1755. case ERR_CONFDIRMOD:
  1756. #ifdef LEAF
  1757. return STR("Cannot chmod() config directory (~/.ssh/)");
  1758. #else
  1759. return STR("Cannot chmod() config directory (./)");
  1760. #endif /* LEAF */
  1761. case ERR_CONFMOD:
  1762. #ifdef LEAF
  1763. return STR("Cannot chmod() config (~/.ssh/.known_hosts/)");
  1764. #else
  1765. return STR("Cannot chmod() config (./conf)");
  1766. #endif /* LEAF */
  1767. case ERR_TMPMOD:
  1768. #ifdef LEAF
  1769. return STR("Cannot chmod() tmp directory (~/.ssh/.../)");
  1770. #else
  1771. return STR("Cannot chmod() tmp directory (./tmp)");
  1772. #endif /* LEAF */
  1773. case ERR_NOCONF:
  1774. #ifdef LEAF
  1775. return STR("The local config is missing (~/.ssh/.known_hosts)");
  1776. #else
  1777. return STR("The local config is missing (./conf)");
  1778. #endif /* LEAF */
  1779. case ERR_CONFBADENC:
  1780. return STR("Encryption in config is wrong/corrupt");
  1781. case ERR_WRONGUID:
  1782. return STR("UID in conf does not match getuid()");
  1783. case ERR_WRONGUNAME:
  1784. return STR("Uname in conf does not match uname()");
  1785. case ERR_BADCONF:
  1786. return STR("Config file is incomplete");
  1787. default:
  1788. return STR("Unforseen error");
  1789. }
  1790. }
  1791. void werr(int errnum)
  1792. {
  1793. putlog(LOG_MISC, "*", STR("error #%d"), errnum);
  1794. sdprintf(STR("error translates to: %s"), werr_tostr(errnum));
  1795. printf(STR("(segmentation fault)\n"));
  1796. fatal("", 0);
  1797. }
  1798. /* private returns 0 if user has access, and 1 if they dont because of +private
  1799. * This function does not check if the user has "op" access, it only checks if the user is
  1800. * restricted by +private for the channel
  1801. */
  1802. int private(struct flag_record fr, struct chanset_t *chan, int type)
  1803. {
  1804. if (!channel_private(chan) || glob_bot(fr) || glob_owner(fr))
  1805. return 0; /* user is implicitly not restricted by +private, they may however be lacking other flags */
  1806. if (type == PRIV_OP) {
  1807. /* |o implies all flags above. n| has access to all +private. Bots are exempt. */
  1808. if (chan_op(fr))
  1809. return 0;
  1810. } else if (type == PRIV_VOICE) {
  1811. if (chan_voice(fr))
  1812. return 0;
  1813. }
  1814. return 1; /* user is restricted by +private */
  1815. }
  1816. int chk_op(struct flag_record fr, struct chanset_t *chan)
  1817. {
  1818. if (!private(fr, chan, PRIV_OP) && !chk_deop(fr, chan)) {
  1819. if (chan_op(fr) || (glob_op(fr) && !chan_deop(fr)))
  1820. return 1;
  1821. }
  1822. return 0;
  1823. }
  1824. int chk_deop(struct flag_record fr, struct chanset_t *chan)
  1825. {
  1826. if (chan_deop(fr) || (glob_deop(fr) && !chan_op(fr)))
  1827. return 1;
  1828. else
  1829. return 0;
  1830. }
  1831. int chk_voice(struct flag_record fr, struct chanset_t *chan)
  1832. {
  1833. if (!private(fr, chan, PRIV_VOICE) && !chk_devoice(fr, chan)) {
  1834. if (chan_voice(fr) || (glob_voice(fr) && !chan_quiet(fr)))
  1835. return 1;
  1836. }
  1837. return 0;
  1838. }
  1839. int chk_devoice(struct flag_record fr, struct chanset_t *chan)
  1840. {
  1841. if (chan_quiet(fr) || (glob_quiet(fr) && !chan_voice(fr)))
  1842. return 1;
  1843. else
  1844. return 0;
  1845. }
  1846. void local_check_should_lock()
  1847. {
  1848. module_entry *me;
  1849. if ((me = module_find("channels", 0, 0))) {
  1850. Function *func = me->funcs;
  1851. /* check_should_lock() */
  1852. (func[51]) ();
  1853. }
  1854. }
  1855. /* convert binary hashes to hex */
  1856. char *btoh(const unsigned char *md, int len)
  1857. {
  1858. int i;
  1859. char buf[100], *ret;
  1860. for (i = 0; i < len; i++)
  1861. sprintf(&(buf[i*2]), "%02x", md[i]);
  1862. ret = buf;
  1863. return ret;
  1864. }
  1865. #define HELP_BOLD 1
  1866. #define HELP_REV 2
  1867. #define HELP_UNDER 4
  1868. #define HELP_FLASH 8
  1869. void showhelp (int idx, struct flag_record *flags, char *string)
  1870. {
  1871. static int help_flags;
  1872. struct flag_record tr = {FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0};
  1873. static char helpstr[8092] = "", tmp[2] = "", flagstr[10] = "";
  1874. int ok = 1;
  1875. Context;
  1876. helpstr[0] = 0;
  1877. while ((string) && (string[0])) {
  1878. if ((*string == '%')) {
  1879. if (!strncmp(string + 1, "{+", 2)) {
  1880. while ((*string) && (*string != '+')) {
  1881. string++;
  1882. }
  1883. flagstr[0] = 0;
  1884. while ((*string) && (*string != '}')) {
  1885. sprintf(tmp, "%c", *string);
  1886. strcat(flagstr, tmp);
  1887. string++;
  1888. }
  1889. string++;
  1890. break_down_flags(flagstr, &tr, NULL);
  1891. if (flagrec_ok(&tr, flags)) {
  1892. ok = 1;
  1893. while ((*string) && (*string != '%')) {
  1894. sprintf(tmp, "%c", *string);
  1895. strcat(helpstr, tmp);
  1896. string++;
  1897. }
  1898. if (!strncmp(string + 1, "{-", 2)) {
  1899. ok = 1;
  1900. while ((*string) && (*string != '}')) {
  1901. string++;
  1902. }
  1903. }
  1904. string++;
  1905. } else {
  1906. ok = 0;
  1907. }
  1908. } else if (!strncmp(string + 1, "{-", 2)) {
  1909. ok = 1;
  1910. while ((*string) && (*string != '}')) {
  1911. string++;
  1912. }
  1913. string++;
  1914. } else if (*string == '{') {
  1915. while ((*string) && (*string != '}')) {
  1916. string++;
  1917. }
  1918. } else if (*(string + 1) == 'b') {
  1919. string += 2;
  1920. if (help_flags & HELP_BOLD) {
  1921. help_flags &= ~HELP_BOLD;
  1922. strcat(helpstr, color(idx, BOLD_CLOSE, 0));
  1923. } else {
  1924. help_flags |= HELP_BOLD;
  1925. strcat(helpstr, color(idx, BOLD_OPEN, 0));
  1926. }
  1927. } else if (*(string + 1) == 'f') {
  1928. string += 2;
  1929. if (help_flags & HELP_FLASH) {
  1930. strcat(helpstr, color(idx, FLASH_CLOSE, 0));
  1931. help_flags &= ~HELP_FLASH;
  1932. } else {
  1933. help_flags |= HELP_FLASH;
  1934. strcat(helpstr, color(idx, FLASH_OPEN, 0));
  1935. }
  1936. } else if (*(string + 1) == 'd') {
  1937. string += 2;
  1938. strcat(helpstr, dcc_prefix);
  1939. } else if (*(string + 1) == '%') {
  1940. string += 2;
  1941. strcat(helpstr, "%");
  1942. } else {
  1943. if (ok) {
  1944. sprintf(tmp, "%c", *string);
  1945. strcat(helpstr, tmp);
  1946. }
  1947. string++;
  1948. }
  1949. } else {
  1950. if (ok) {
  1951. sprintf(tmp, "%c", *string);
  1952. strcat(helpstr, tmp);
  1953. }
  1954. string++;
  1955. }
  1956. }
  1957. if (strchr(helpstr, '\0'))
  1958. *(char*)(strchr(helpstr, '\0')) = 0;
  1959. if (helpstr[0]) dumplots(idx, "", helpstr);
  1960. }
  1961. /* Arrange the N elements of ARRAY in random order. */
  1962. static void shuffleArray(char *array[], int n)
  1963. {
  1964. int i;
  1965. for (i = 0; i < n; i++) {
  1966. int j = i + random() / (RAND_MAX / (n - i) + 1);
  1967. char *t = array[j];
  1968. array[j] = array[i];
  1969. array[i] = t;
  1970. }
  1971. }
  1972. void shuffle(char *string, char *delim)
  1973. {
  1974. char *array[501], *str, *work;
  1975. int len = 0, i = 0;
  1976. work = nmalloc(strlen(string) + 1);
  1977. strcpy(work, string);
  1978. str = strtok(work, delim);
  1979. while(str && *str)
  1980. {
  1981. array[len] = str;
  1982. len++;
  1983. str = strtok((char*) NULL, delim);
  1984. }
  1985. shuffleArray(array, len);
  1986. string[0] = 0;
  1987. for (i = 0; i < len; i++) {
  1988. strcat(string, array[i]);
  1989. if (i != len - 1)
  1990. strcat(string, delim);
  1991. }
  1992. nfree(work);
  1993. string[strlen(string)] = 0;
  1994. }
  1995. char *color(int idx, int type, int color)
  1996. {
  1997. int ansi = 0;
  1998. /* if user is connected over TELNET or !backgrd, show ANSI
  1999. * if they are relaying, they are most likely on an IRC client and should have mIRC codes
  2000. */
  2001. if ((idx && ((dcc[idx].type != &DCC_RELAYING) && (dcc[idx].status & STAT_TELNET))) || !backgrd) ansi++;
  2002. if (type == BOLD_OPEN) {
  2003. return ansi ? "\033[1m" : "\002";
  2004. } else if (type == BOLD_CLOSE) {
  2005. return ansi ? "\033[22m" : "\002";
  2006. } else if (type == UNDERLINE_OPEN) {
  2007. return ansi ? "\033[4m" : "\037";
  2008. } else if (type == UNDERLINE_CLOSE) {
  2009. return ansi ? "\033[24m" : "\037";
  2010. } else if (type == FLASH_OPEN) {
  2011. return ansi ? "\033[5m" : "\002\037";
  2012. } else if (type == FLASH_CLOSE) {
  2013. return ansi ? "\033[0m" : "\037\002";
  2014. } else if (type == COLOR_OPEN) {
  2015. switch (color) {
  2016. case C_BLACK: return ansi ? "\033[30m" : "\00301";
  2017. case C_RED: return ansi ? "\033[31m" : "\00304";
  2018. case C_GREEN: return ansi ? "\033[32m" : "\00303";
  2019. case C_YELLOW: return ansi ? "\033[33m" : "\00308";
  2020. case C_BLUE: return ansi ? "\033[34m" : "\00302";
  2021. case C_PURPLE: return ansi ? "\033[35m" : "\00306";
  2022. case C_CYAN: return ansi ? "\033[36m" : "\00309";
  2023. case C_WHITE: return ansi ? "\033[37m" : "\00300";
  2024. default: break;
  2025. }
  2026. } else if (type == COLOR_CLOSE) {
  2027. return ansi ? "\033[0m" : "\003";
  2028. }
  2029. /* This should never be reached.. */
  2030. return "";
  2031. }