misc.c 51 KB

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