misc.c 54 KB

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