dccutil.c 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039
  1. /*
  2. * dccutil.c -- handles:
  3. * lots of little functions to send formatted text to
  4. * varying types of connections
  5. * '.who', '.whom', and '.dccstat' code
  6. * memory management for dcc structures
  7. * timeout checking for dcc connections
  8. *
  9. */
  10. #include <sys/stat.h>
  11. #include "common.h"
  12. #include "color.h"
  13. #include "userrec.h"
  14. #include "dcc.h"
  15. #include "auth.h"
  16. #include "botnet.h"
  17. #include "adns.h"
  18. #include "net.h"
  19. #include "main.h"
  20. #include "dccutil.h"
  21. #include "misc.h"
  22. #include "botcmd.h"
  23. #include <errno.h>
  24. #include "chan.h"
  25. #include "tandem.h"
  26. #include "core_binds.h"
  27. #include "egg_timer.h"
  28. #include "src/mod/server.mod/server.h"
  29. #include "src/mod/notes.mod/notes.h"
  30. #include <stdarg.h>
  31. static struct portmap *root = NULL;
  32. time_t connect_timeout = 40; /* How long to wait before a telnet connection times out */
  33. int max_dcc = 200;
  34. static int dcc_flood_thr = 3;
  35. void
  36. init_dcc()
  37. {
  38. if (!conf.bot->hub)
  39. protect_telnet = 0;
  40. if (max_dcc < 1)
  41. max_dcc = 1;
  42. if (dcc)
  43. dcc = (struct dcc_t *) my_realloc(dcc, sizeof(struct dcc_t) * max_dcc);
  44. else
  45. dcc = (struct dcc_t *) my_calloc(1, sizeof(struct dcc_t) * max_dcc);
  46. }
  47. /* Replace \n with \r\n */
  48. char *
  49. add_cr(char *buf)
  50. {
  51. static char WBUF[1024] = "";
  52. char *p = NULL, *q = NULL;
  53. for (p = buf, q = WBUF; *p; p++, q++) {
  54. if (*p == '\n')
  55. *q++ = '\r';
  56. *q = *p;
  57. }
  58. *q = *p;
  59. return WBUF;
  60. }
  61. static void
  62. colorbuf(char *buf, size_t len, int idx)
  63. {
  64. // char *buf = *bufp;
  65. int cidx = coloridx(idx);
  66. static int cflags;
  67. int schar = 0;
  68. char buf3[1024] = "", buf2[1024] = "", c = 0;
  69. for (size_t i = 0; i < len; i++) {
  70. c = buf[i];
  71. buf2[0] = 0;
  72. if (cidx) {
  73. if (schar) { /* These are for $X replacements */
  74. schar--; /* Unset identifier int */
  75. switch (c) {
  76. case 'b':
  77. if (cflags & CFLGS_BOLD) {
  78. simple_sprintf(buf2, "%s", BOLD_END(idx));
  79. cflags &= ~CFLGS_BOLD;
  80. } else {
  81. cflags |= CFLGS_BOLD;
  82. simple_sprintf(buf2, "%s", BOLD(idx));
  83. }
  84. break;
  85. case 'u':
  86. if (cflags & CFLGS_UNDERLINE) {
  87. simple_sprintf(buf2, "%s", UNDERLINE_END(idx));
  88. cflags &= ~CFLGS_UNDERLINE;
  89. } else {
  90. simple_sprintf(buf2, "%s", UNDERLINE(idx));
  91. cflags |= CFLGS_UNDERLINE;
  92. }
  93. break;
  94. case 'f':
  95. if (cflags & CFLGS_FLASH) {
  96. simple_sprintf(buf2, "%s", FLASH_END(idx));
  97. cflags &= ~CFLGS_FLASH;
  98. } else {
  99. simple_sprintf(buf2, "%s", FLASH(idx));
  100. cflags |= CFLGS_FLASH;
  101. }
  102. break;
  103. default:
  104. simple_sprintf(buf2, "$%c", c); /* No identifier, put the '$' back in */
  105. break;
  106. }
  107. } else { /* These are character replacements */
  108. switch (c) {
  109. case '$':
  110. schar++;
  111. break;
  112. case ':':
  113. simple_sprintf(buf2, "%s%c%s", LIGHTGREY(idx), c, COLOR_END(idx));
  114. break;
  115. case '@':
  116. simple_sprintf(buf2, "%s%c%s", BOLD(idx), c, BOLD_END(idx));
  117. break;
  118. case '>':
  119. case ')':
  120. case '<':
  121. case '(':
  122. simple_sprintf(buf2, "%s%c%s", GREEN(idx), c, COLOR_END(idx));
  123. break;
  124. default:
  125. simple_sprintf(buf2, "%c", c);
  126. break;
  127. }
  128. }
  129. } else {
  130. if (schar) {
  131. schar--;
  132. switch (c) {
  133. case 'b':
  134. case 'u':
  135. case 'f':
  136. break;
  137. default:
  138. simple_sprintf(buf2, "$%c", c); /* No identifier, put the '$' back in */
  139. }
  140. } else {
  141. switch (c) {
  142. case '$':
  143. schar++;
  144. break;
  145. default:
  146. simple_sprintf(buf2, "%c", c);
  147. break;
  148. }
  149. }
  150. }
  151. simple_sprintf(buf3, "%s%s", (buf3 && buf3[0]) ? buf3 : "", (buf2 && buf2[0]) ? buf2 : "");
  152. }
  153. buf3[strlen(buf3)] = 0;
  154. strcpy(buf, buf3);
  155. }
  156. /* Dump a potentially super-long string of text.
  157. */
  158. void dumplots(int idx, const char *prefix, char *data)
  159. {
  160. if (!*data) {
  161. dprintf(idx, "%s\n", prefix);
  162. return;
  163. }
  164. char *p = data, *q = NULL, *n = NULL, c = 0;
  165. const size_t max_data_len = 120 - strlen(prefix);
  166. while ((strlen(p) - ansi_len(p)) > max_data_len) {
  167. q = p + max_data_len;
  168. /* Search for embedded linefeed first */
  169. n = strchr(p, '\n');
  170. if (n && n < q) {
  171. /* Great! dump that first line then start over */
  172. *n = 0;
  173. dprintf(idx, "%s%s\n", prefix, p);
  174. *n = '\n';
  175. p = n + 1;
  176. } else {
  177. /* Search backwards for the last space */
  178. while (*q != ' ' && q != p)
  179. q--;
  180. if (q == p)
  181. q = p + max_data_len;
  182. c = *q;
  183. *q = 0;
  184. dprintf(idx, "%s%s\n", prefix, p);
  185. *q = c;
  186. p = q;
  187. if (c == ' ')
  188. p++;
  189. }
  190. }
  191. /* Last trailing bit: split by linefeeds if possible */
  192. n = strchr(p, '\n');
  193. while (n) {
  194. *n = 0;
  195. dprintf(idx, "%s%s\n", prefix, p);
  196. *n = '\n';
  197. p = n + 1;
  198. n = strchr(p, '\n');
  199. }
  200. if (*p)
  201. dprintf(idx, "%s%s\n", prefix, p); /* Last trailing bit */
  202. }
  203. void
  204. dprintf(int idx, const char *format, ...)
  205. {
  206. char buf[1024] = "";
  207. size_t len;
  208. va_list va;
  209. va_start(va, format);
  210. egg_vsnprintf(buf, sizeof(buf), format, va);
  211. va_end(va);
  212. /* We can not use the return value vsnprintf() to determine where
  213. * to null terminate. The C99 standard specifies that vsnprintf()
  214. * shall return the number of bytes that would be written if the
  215. * buffer had been large enough, rather then -1.
  216. */
  217. /* We actually can, since if it's < 0 or >= sizeof(buf), we know it wrote
  218. * sizeof(buf) bytes. But we're not doing that anyway.
  219. */
  220. len = strlen(buf);
  221. /* this is for color on dcc :P */
  222. if (idx < 0) {
  223. tputs(-idx, buf, len);
  224. } else if (idx > 0x7FF0) {
  225. if (idx == DP_STDOUT || idx == DP_STDOUT) {
  226. colorbuf(buf, len, -1);
  227. buf[sizeof(buf) - 1] = 0;
  228. len = strlen(buf);
  229. }
  230. switch (idx) {
  231. case DP_STDOUT:
  232. tputs(STDOUT, buf, len);
  233. break;
  234. case DP_STDERR:
  235. tputs(STDERR, buf, len);
  236. break;
  237. case DP_SERVER:
  238. case DP_HELP:
  239. case DP_MODE:
  240. case DP_MODE_NEXT:
  241. case DP_SERVER_NEXT:
  242. case DP_HELP_NEXT:
  243. case DP_DUMP:
  244. if (conf.bot->hub)
  245. break;
  246. len -= remove_crlf_r(buf);
  247. if ((idx == DP_DUMP || floodless)) {
  248. if (serv != -1) {
  249. if (debug_output)
  250. putlog(LOG_SRVOUT, "@", "[d->] %s", buf);
  251. write_to_server(buf, len);
  252. }
  253. } else
  254. queue_server(idx, buf, len);
  255. break;
  256. }
  257. return;
  258. } else { /* normal chat text */
  259. colorbuf(buf, len, idx);
  260. buf[sizeof(buf) - 1] = 0;
  261. len = strlen(buf);
  262. if (len > 1000) { /* Truncate to fit */
  263. buf[1000] = 0;
  264. strcat(buf, "\n");
  265. len = 1001;
  266. }
  267. if (dcc[idx].simul >= 0 && !dcc[idx].irc) {
  268. bounce_simul(idx, buf);
  269. } else if (dcc[idx].irc) {
  270. // size_t size = strlen(dcc[idx].simulbot) + strlen(buf) + 20;
  271. // char *ircbuf = (char *) my_calloc(1, size);
  272. // egg_snprintf(ircbuf, size, "PRIVMSG %s :%s", dcc[idx].simulbot, buf);
  273. // tputs(dcc[idx].sock, ircbuf, strlen(ircbuf));
  274. dprintf(DP_HELP, "PRIVMSG %s :%s\n", dcc[idx].simulbot, buf);
  275. // free(ircbuf);
  276. } else {
  277. if (dcc[idx].type && ((long) (dcc[idx].type->output) == 1)) {
  278. char *p = add_cr(buf);
  279. tputs(dcc[idx].sock, p, strlen(p));
  280. } else if (dcc[idx].type && dcc[idx].type->output) {
  281. dcc[idx].type->output(idx, buf, dcc[idx].u.other);
  282. } else {
  283. tputs(dcc[idx].sock, buf, len);
  284. }
  285. }
  286. }
  287. }
  288. void
  289. chatout(const char *format, ...)
  290. {
  291. char s[1024] = "", *p = NULL;
  292. va_list va;
  293. va_start(va, format);
  294. egg_vsnprintf(s, sizeof(s), format, va);
  295. va_end(va);
  296. if ((p = strrchr(s, '\n')))
  297. *p++ = 0;
  298. for (int i = 0; i < dcc_total; i++)
  299. if (dcc[i].type && (dcc[i].type == &DCC_CHAT) && (dcc[i].simul == -1))
  300. if (dcc[i].u.chat->channel >= 0)
  301. dprintf(i, "%s\n", s);
  302. }
  303. /* Print to all on this channel but one.
  304. */
  305. void
  306. chanout_but(int x, int chan, const char *format, ...)
  307. {
  308. char s[1024] = "", *p = NULL;
  309. va_list va;
  310. va_start(va, format);
  311. egg_vsnprintf(s, sizeof(s), format, va);
  312. va_end(va);
  313. if ((p = strrchr(s, '\n')))
  314. *p = 0;
  315. for (int i = 0; i < dcc_total; i++)
  316. if (dcc[i].type && (dcc[i].type == &DCC_CHAT) && (i != x) && (dcc[i].simul == -1))
  317. if (dcc[i].u.chat->channel == chan)
  318. dprintf(i, "%s\n", s);
  319. }
  320. void
  321. dcc_chatter(int idx)
  322. {
  323. int i;
  324. int j;
  325. struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0 };
  326. strcpy(dcc[idx].u.chat->con_chan, "***");
  327. check_bind_chon(dcc[idx].nick, idx);
  328. dprintf(idx, "Connected to %s, running %s\n", conf.bot->nick, version);
  329. show_banner(idx); /* check STAT_BANNER inside function */
  330. get_user_flagrec(dcc[idx].user, &fr, NULL);
  331. if ((dcc[idx].status & STAT_BOTS) && glob_master(fr)) {
  332. if ((tands + 1) > 1)
  333. dprintf(idx, "There are %s-%d- bots%s currently linked.\n", BOLD(idx), tands + 1, BOLD_END(idx));
  334. else
  335. dprintf(idx, "There is %s-%d- bot%s currently linked.\n", BOLD(idx), tands + 1, BOLD_END(idx));
  336. dprintf(idx, " \n");
  337. }
  338. if (dcc[idx].status & STAT_WHOM) {
  339. answer_local_whom(idx, -1);
  340. dprintf(idx, " \n");
  341. }
  342. if (dcc[idx].status & STAT_CHANNELS) {
  343. show_channels(idx, NULL);
  344. dprintf(idx, " \n");
  345. }
  346. show_motd(idx);
  347. notes_chon(idx);
  348. if (glob_party(fr)) {
  349. i = dcc[idx].u.chat->channel;
  350. } else {
  351. dprintf(idx, "You don't have partyline chat access; commands only.\n\n");
  352. i = -1;
  353. }
  354. j = dcc[idx].sock;
  355. dcc[idx].u.chat->channel = 234567;
  356. /* Still there? */
  357. if ((idx >= dcc_total) || (dcc[idx].sock != j))
  358. return; /* Nope */
  359. if (dcc[idx].type == &DCC_CHAT) {
  360. if (!strcmp(dcc[idx].u.chat->con_chan, "***"))
  361. strcpy(dcc[idx].u.chat->con_chan, "*");
  362. if (dcc[idx].u.chat->channel == 234567) {
  363. /* If the chat channel has already been altered it's *highly*
  364. * probably join/part messages have been broadcast everywhere,
  365. * so dont bother sending them
  366. */
  367. if (i == -2)
  368. i = 0;
  369. dcc[idx].u.chat->channel = i;
  370. if (dcc[idx].u.chat->channel >= 0) {
  371. if (dcc[idx].u.chat->channel < GLOBAL_CHANS) {
  372. botnet_send_join_idx(idx);
  373. }
  374. }
  375. }
  376. /* But *do* bother with sending it locally */
  377. if (!dcc[idx].u.chat->channel) {
  378. chanout_but(-1, 0, "*** %s joined the party line.\n", dcc[idx].nick);
  379. } else if (dcc[idx].u.chat->channel > 0) {
  380. chanout_but(-1, dcc[idx].u.chat->channel, "*** %s joined the channel.\n", dcc[idx].nick);
  381. }
  382. }
  383. }
  384. void trim_dcclist(int top_index)
  385. {
  386. dcc_total = top_index + 1;
  387. }
  388. int
  389. dcc_read(FILE *f)
  390. {
  391. char inbuf[1024] = "", *type = NULL, *buf = NULL;
  392. int idx = -1;
  393. bool isserv = 0;
  394. while (fgets(inbuf, sizeof(inbuf), f) != NULL) {
  395. remove_crlf(inbuf);
  396. buf = inbuf;
  397. if (!strcmp(buf, "+dcc"))
  398. return idx;
  399. type = newsplit(&buf);
  400. if (!strcmp(type, "type")) {
  401. struct dcc_table *dcc_type = NULL;
  402. size_t dcc_size = 0;
  403. // if (!strcmp(buf, "CHAT"))
  404. // dcc_type = &DCC_CHAT;
  405. if (!strcmp(buf, "SERVER")) {
  406. dcc_type = &SERVER_SOCKET;
  407. isserv = 1;
  408. }
  409. // if (!strcmp(buf, "BOT"))
  410. // dcc_type = &DCC_BOT;
  411. if (dcc_type) {
  412. idx = new_dcc(dcc_type, dcc_size);
  413. if (isserv)
  414. servidx = idx;
  415. }
  416. }
  417. if (idx >= 0) {
  418. if (!strcmp(type, "addr"))
  419. dcc[idx].addr = my_atoul(buf);
  420. if (!strcmp(type, "sock")) {
  421. dcc[idx].sock = atoi(buf);
  422. if (isserv)
  423. serv = dcc[idx].sock;
  424. }
  425. if (!strcmp(type, "port"))
  426. dcc[idx].port = atoi(buf);
  427. if (!strcmp(type, "nick"))
  428. strlcpy(dcc[idx].nick, buf, NICKLEN);
  429. if (!strcmp(type, "host")) {
  430. strlcpy(dcc[idx].host, buf, UHOSTLEN);
  431. }
  432. }
  433. }
  434. return -1;
  435. }
  436. void
  437. dcc_write(FILE *f, int idx)
  438. {
  439. if (dcc[idx].sock > 0) {
  440. fprintf(f, "-dcc\n");
  441. if (dcc[idx].type)
  442. fprintf(f, "type %s\n", dcc[idx].type->name);
  443. // if (user)
  444. // fprintf(f, "user %s\n", dcc[idx].user->handle);
  445. if (dcc[idx].addr)
  446. fprintf(f, "addr %u\n", dcc[idx].addr);
  447. if (dcc[idx].status)
  448. fprintf(f, "status %lu\n", dcc[idx].status);
  449. fprintf(f, "sock %d\n", dcc[idx].sock);
  450. // fprintf(f, "simul %d\n", dcc[idx].simul);
  451. if (dcc[idx].port)
  452. fprintf(f, "port %d\n", dcc[idx].port);
  453. if (dcc[idx].nick[0])
  454. fprintf(f, "nick %s\n", dcc[idx].nick);
  455. if (dcc[idx].host[0])
  456. fprintf(f, "host %s\n", dcc[idx].host);
  457. fprintf(f, "+dcc\n");
  458. }
  459. }
  460. /* Mark an entry as lost and deconstruct it's contents. It will be securely
  461. * removed from the dcc list in the main loop.
  462. */
  463. void
  464. lostdcc(int n)
  465. {
  466. sdprintf("lostdcc(%d)", n);
  467. /* Make sure it's a valid dcc index. */
  468. if (n < 0 || n >= max_dcc)
  469. return;
  470. if (dcc[n].type && dcc[n].type->kill)
  471. dcc[n].type->kill(n, dcc[n].u.other);
  472. else if (dcc[n].u.other)
  473. free(dcc[n].u.other);
  474. dcc[n].u.other = NULL;
  475. // This is also done when we new_dcc(), so don't bother for now, we set sock/type to NULL, so it won't even be
  476. // parsed by anything.
  477. // egg_bzero(&dcc[n], sizeof(struct dcc_t));
  478. dcc[n].sock = -1;
  479. dcc[n].type = NULL;
  480. dccn--;
  481. /* last entry! make table smaller :) */
  482. if (n == (dcc_total - 1))
  483. dcc_total--;
  484. }
  485. /* Show list of current dcc's to a dcc-chatter
  486. * positive value: idx given -- negative value: sock given
  487. */
  488. void
  489. tell_dcc(int idx)
  490. {
  491. int i;
  492. size_t j, nicklen = 0;
  493. char other[160] = "", format[81] = "";
  494. /* calculate max nicklen */
  495. for (i = 0; i < dcc_total; i++) {
  496. if (dcc[i].type && strlen(dcc[i].nick) > (unsigned) nicklen)
  497. nicklen = strlen(dcc[i].nick);
  498. }
  499. if (nicklen < 9)
  500. nicklen = 9;
  501. egg_snprintf(format, sizeof format, "%%-4s %%-4s %%-8s %%-5s %%-%us %%-40s %%s\n", nicklen);
  502. dprintf(idx, format, "SOCK", "IDX", "ADDR", "PORT", "NICK", "HOST", "TYPE");
  503. dprintf(idx, format, "----", "---", "--------", "-----", "---------",
  504. "----------------------------------------", "----");
  505. egg_snprintf(format, sizeof format, "%%-4d %%-4d %%08X %%5u %%-%us %%-40s %%s\n", nicklen);
  506. dprintf(idx, "dccn: %d, dcc_total: %d\n", dccn, dcc_total);
  507. dprintf(idx, "dns_idx: %d, servidx: %d\n", dns_idx, servidx);
  508. for (i = 0; i < dcc_total; i++) {
  509. if (dcc[i].type) {
  510. j = strlen(dcc[i].host);
  511. if (j > 40)
  512. j -= 40;
  513. else
  514. j = 0;
  515. if (dcc[i].type && dcc[i].type->display)
  516. dcc[i].type->display(i, other);
  517. else {
  518. sprintf(other, "?:%lX !! ERROR !!", (long) dcc[i].type);
  519. break;
  520. }
  521. dprintf(idx, format, dcc[i].sock, i, dcc[i].addr, dcc[i].port, dcc[i].nick, dcc[i].host + j, other);
  522. }
  523. }
  524. }
  525. /* Mark someone on dcc chat as no longer away
  526. */
  527. void
  528. not_away(int idx)
  529. {
  530. if (dcc[idx].u.chat->away == NULL) {
  531. dprintf(idx, "You weren't away!\n");
  532. return;
  533. }
  534. if (dcc[idx].u.chat->channel >= 0) {
  535. chanout_but(-1, dcc[idx].u.chat->channel, "*** %s is no longer away.\n", dcc[idx].nick);
  536. if (dcc[idx].u.chat->channel < GLOBAL_CHANS) {
  537. botnet_send_away(-1, conf.bot->nick, dcc[idx].sock, NULL, idx);
  538. }
  539. }
  540. dprintf(idx, "You're not away any more.\n");
  541. free(dcc[idx].u.chat->away);
  542. dcc[idx].u.chat->away = NULL;
  543. check_bind_away(conf.bot->nick, idx, NULL);
  544. }
  545. void
  546. set_away(int idx, char *s)
  547. {
  548. if (s == NULL) {
  549. not_away(idx);
  550. return;
  551. }
  552. if (!s[0]) {
  553. not_away(idx);
  554. return;
  555. }
  556. if (dcc[idx].u.chat->away != NULL)
  557. free(dcc[idx].u.chat->away);
  558. dcc[idx].u.chat->away = strdup(s);
  559. if (dcc[idx].u.chat->channel >= 0) {
  560. chanout_but(-1, dcc[idx].u.chat->channel, "*** %s is now away: %s\n", dcc[idx].nick, s);
  561. if (dcc[idx].u.chat->channel < GLOBAL_CHANS) {
  562. botnet_send_away(-1, conf.bot->nick, dcc[idx].sock, s, idx);
  563. }
  564. }
  565. dprintf(idx, "You are now away. (%s)\n", s);
  566. check_bind_away(conf.bot->nick, idx, s);
  567. }
  568. /* Make a password, 10-14 random letters and digits
  569. */
  570. void
  571. makepass(char *s)
  572. {
  573. make_rand_str(s, 10 + randint(5));
  574. }
  575. void
  576. flush_lines(int idx, struct chat_info *ci)
  577. {
  578. int c = ci->line_count;
  579. struct msgq *p = ci->buffer, *o;
  580. while (p && c < (ci->max_line)) {
  581. ci->current_lines--;
  582. tputs(dcc[idx].sock, p->msg, p->len);
  583. free(p->msg);
  584. o = p->next;
  585. free(p);
  586. p = o;
  587. c++;
  588. }
  589. if (p != NULL) {
  590. if (dcc[idx].status & STAT_TELNET)
  591. tputs(dcc[idx].sock, "[More]: ", 8);
  592. else
  593. tputs(dcc[idx].sock, "[More]\n", 7);
  594. }
  595. ci->buffer = p;
  596. ci->line_count = 0;
  597. }
  598. int
  599. new_dcc(struct dcc_table *type, int xtra_size)
  600. {
  601. if (!type)
  602. return -1;
  603. if (dcc_total == max_dcc)
  604. return -1;
  605. int i = 0;
  606. /* Find the first gap */
  607. for (i = 0; i <= dcc_total; i++)
  608. if (!dcc[i].type)
  609. break;
  610. /* we managed to get to the end of the list! */
  611. if (i == dcc_total) {
  612. i = dcc_total;
  613. dcc_total++;
  614. }
  615. dccn++;
  616. /* empty out the memory for the entry */
  617. egg_bzero((char *) &dcc[i], sizeof(struct dcc_t));
  618. dcc[i].type = type;
  619. if (xtra_size)
  620. dcc[i].u.other = (char *) my_calloc(1, xtra_size);
  621. else
  622. dcc[i].u.other = NULL;
  623. dcc[i].simul = -1;
  624. dcc[i].sock = -1;
  625. sdprintf("new_dcc (%s): %d (dccn/dcc_total: %d/%d)", type->name, i, dccn, dcc_total);
  626. return i;
  627. }
  628. /* Changes the given dcc entry to another type.
  629. */
  630. void
  631. changeover_dcc(int i, struct dcc_table *type, int xtra_size)
  632. {
  633. /* Free old structure. */
  634. if (dcc[i].type && dcc[i].type->kill)
  635. dcc[i].type->kill(i, dcc[i].u.other);
  636. else if (dcc[i].u.other) {
  637. free(dcc[i].u.other);
  638. dcc[i].u.other = NULL;
  639. }
  640. dcc[i].type = type;
  641. if (xtra_size)
  642. dcc[i].u.other = (char *) my_calloc(1, xtra_size);
  643. }
  644. int
  645. detect_dcc_flood(time_t * timer, struct chat_info *chat, int idx)
  646. {
  647. if (!dcc_flood_thr)
  648. return 0;
  649. time_t t = now;
  650. if (*timer != t) {
  651. *timer = t;
  652. chat->msgs_per_sec = 0;
  653. } else {
  654. chat->msgs_per_sec++;
  655. if (chat->msgs_per_sec > dcc_flood_thr) {
  656. /* FLOOD */
  657. dprintf(idx, "*** FLOOD: Goodbye.\n");
  658. /* Evil assumption here that flags&DCT_CHAT implies chat type */
  659. if ((dcc[idx].type->flags & DCT_CHAT) && chat && (chat->channel >= 0)) {
  660. char x[1024];
  661. egg_snprintf(x, sizeof x, DCC_FLOODBOOT, dcc[idx].nick);
  662. chanout_but(idx, chat->channel, "*** %s", x);
  663. if (chat->channel < GLOBAL_CHANS)
  664. botnet_send_part_idx(idx, x);
  665. }
  666. check_bind_chof(dcc[idx].nick, idx);
  667. if ((dcc[idx].sock != STDOUT) || backgrd) {
  668. killsock(dcc[idx].sock);
  669. lostdcc(idx);
  670. } else {
  671. dprintf(DP_STDOUT, "\n### SIMULATION RESET ###\n\n");
  672. dcc_chatter(idx);
  673. }
  674. return 1; /* <- flood */
  675. }
  676. }
  677. return 0;
  678. }
  679. /* Handle someone being booted from dcc chat.
  680. */
  681. void
  682. do_boot(int idx, char *by, char *reason)
  683. {
  684. int files = (dcc[idx].type != &DCC_CHAT);
  685. dprintf(idx, DCC_BOOTED1);
  686. dprintf(idx, DCC_BOOTED2, files ? "file section" : "bot", by, reason[0] ? ": " : ".", reason);
  687. /* If it's a partyliner (chatterer :) */
  688. /* Horrible assumption that DCT_CHAT using structure uses same format
  689. * as DCC_CHAT */
  690. if ((dcc[idx].type->flags & DCT_CHAT) && (dcc[idx].u.chat->channel >= 0)) {
  691. char x[1024] = "";
  692. egg_snprintf(x, sizeof x, DCC_BOOTED3, by, dcc[idx].nick, reason[0] ? ": " : "", reason);
  693. chanout_but(idx, dcc[idx].u.chat->channel, "*** %s.\n", x);
  694. if (dcc[idx].u.chat->channel < GLOBAL_CHANS)
  695. botnet_send_part_idx(idx, x);
  696. }
  697. check_bind_chof(dcc[idx].nick, idx);
  698. if ((dcc[idx].sock != STDOUT) || backgrd) {
  699. killsock(dcc[idx].sock);
  700. lostdcc(idx);
  701. /* Entry must remain in the table so it can be logged by the caller */
  702. } else {
  703. dprintf(DP_STDOUT, "\n### SIMULATION RESET\n\n");
  704. dcc_chatter(idx);
  705. }
  706. return;
  707. }
  708. port_t
  709. listen_all(port_t lport, bool off)
  710. {
  711. int idx = (-1);
  712. port_t port, realport;
  713. #ifdef USE_IPV6
  714. int i6 = 0;
  715. #endif /* USE_IPV6 */
  716. int i;
  717. struct portmap *pmap = NULL, *pold = NULL;
  718. port = realport = lport;
  719. for (pmap = root; pmap; pold = pmap, pmap = pmap->next)
  720. if (pmap->realport == port) {
  721. port = pmap->mappedto;
  722. break;
  723. }
  724. for (int ii = 0; ii < dcc_total; ii++) {
  725. if (dcc[ii].type && (dcc[ii].type == &DCC_TELNET) && (dcc[ii].port == port)) {
  726. idx = ii;
  727. if (off) {
  728. if (pmap) {
  729. if (pold)
  730. pold->next = pmap->next;
  731. else
  732. root = pmap->next;
  733. free(pmap);
  734. }
  735. #ifdef USE_IPV6
  736. if (sockprotocol(dcc[idx].sock) == AF_INET6)
  737. putlog(LOG_DEBUG, "*", "Closing IPv6 listening port %d", dcc[idx].port);
  738. else
  739. #endif /* USE_IPV6 */
  740. putlog(LOG_DEBUG, "*", "Closing IPv4 listening port %d", dcc[idx].port);
  741. killsock(dcc[idx].sock);
  742. lostdcc(idx);
  743. return idx;
  744. }
  745. }
  746. }
  747. if (idx < 0) {
  748. if (off) {
  749. putlog(LOG_ERRORS, "*", "No such listening port open - %d", lport);
  750. return idx;
  751. }
  752. /* make new one */
  753. if (dcc_total >= max_dcc) {
  754. putlog(LOG_ERRORS, "*", "Can't open listening port - no more DCC Slots");
  755. } else {
  756. #ifdef USE_IPV6
  757. i6 = open_listen_by_af(&port, AF_INET6);
  758. if (i6 < 0) {
  759. putlog(LOG_ERRORS, "*", "Can't open IPv6 listening port %d - %s", port,
  760. i6 == -1 ? "it's taken." : "couldn't assign ip.");
  761. } else {
  762. idx = new_dcc(&DCC_TELNET, 0);
  763. dcc[idx].addr = 0L;
  764. strcpy(dcc[idx].host6, myipstr(6));
  765. dcc[idx].port = port;
  766. dcc[idx].sock = i6;
  767. dcc[idx].timeval = now;
  768. strcpy(dcc[idx].nick, "(telnet6)");
  769. strcpy(dcc[idx].host, "*");
  770. putlog(LOG_DEBUG, "*", "Listening on IPv6 at telnet port %d", port);
  771. }
  772. i = open_listen_by_af(&port, AF_INET);
  773. #else
  774. i = open_listen(&port);
  775. #endif /* USE_IPV6 */
  776. if (i < 0) {
  777. putlog(LOG_ERRORS, "*", "Can't open IPv4 listening port %d - %s", port,
  778. i == -1 ? "it's taken." : "couldn't assign ip.");
  779. } else {
  780. idx = (-1); /* now setup ipv4 listening port */
  781. idx = new_dcc(&DCC_TELNET, 0);
  782. dcc[idx].addr = iptolong(getmyip());
  783. dcc[idx].port = port;
  784. dcc[idx].sock = i;
  785. dcc[idx].timeval = now;
  786. strcpy(dcc[idx].nick, "(telnet)");
  787. strcpy(dcc[idx].host, "*");
  788. putlog(LOG_DEBUG, "*", "Listening on IPv4 at telnet port %d", port);
  789. }
  790. #ifdef USE_IPV6
  791. if (i > 0 || i6 > 0) {
  792. #else
  793. if (i > 0) {
  794. #endif /* USE_IPV6 */
  795. if (!pmap) {
  796. pmap = (struct portmap *) my_calloc(1, sizeof(struct portmap));
  797. pmap->next = root;
  798. root = pmap;
  799. }
  800. pmap->realport = realport;
  801. pmap->mappedto = port;
  802. }
  803. }
  804. }
  805. /* if one of the protocols failed, the one which worked will be returned
  806. * if both were successful, it wont matter which idx is returned, because the
  807. * code reading listen_all will only be reading dcc[idx].port, which would be
  808. * open on both protocols.
  809. * -bryan (10/29/03)
  810. */
  811. return idx;
  812. }
  813. void
  814. identd_open()
  815. {
  816. int idx;
  817. int i = -1;
  818. port_t port = 113;
  819. for (idx = 0; idx < dcc_total; idx++)
  820. if (dcc[idx].type == &DCC_IDENTD_CONNECT)
  821. return; /* it's already open :) */
  822. idx = -1;
  823. identd_hack = 1;
  824. #ifdef USE_IPV6
  825. i = open_listen_by_af(&port, AF_INET6);
  826. #else
  827. i = open_listen(&port);
  828. #endif /* USE_IPV6 */
  829. identd_hack = 0;
  830. if (i >= 0) {
  831. idx = new_dcc(&DCC_IDENTD_CONNECT, 0);
  832. if (idx >= 0) {
  833. egg_timeval_t howlong;
  834. dcc[idx].addr = iptolong(getmyip());
  835. dcc[idx].port = port;
  836. dcc[idx].sock = i;
  837. dcc[idx].timeval = now;
  838. strcpy(dcc[idx].nick, "(identd)");
  839. strcpy(dcc[idx].host, "*");
  840. putlog(LOG_DEBUG, "*", "Identd daemon started.");
  841. howlong.sec = 15;
  842. howlong.usec = 0;
  843. timer_create(&howlong, "identd_close()", (Function) identd_close);
  844. } else
  845. killsock(i);
  846. }
  847. }
  848. void
  849. identd_close()
  850. {
  851. for (int idx = 0; idx < dcc_total; idx++) {
  852. if (dcc[idx].type == &DCC_IDENTD_CONNECT) {
  853. killsock(dcc[idx].sock);
  854. lostdcc(idx);
  855. putlog(LOG_DEBUG, "*", "Identd daemon stopped.");
  856. break;
  857. }
  858. }
  859. }
  860. bool
  861. valid_idx(int idx)
  862. {
  863. if ((idx == -1) || (idx >= dcc_total) || (!dcc[idx].type))
  864. return 0;
  865. return 1;
  866. }
  867. int check_cmd_pass(const char *cmd, char *pass)
  868. {
  869. if (check_master_hash(NULL, pass))
  870. return 1;
  871. struct cmd_pass *cp = NULL;
  872. for (cp = cmdpass; cp; cp = cp->next)
  873. if (!egg_strcasecmp(cmd, cp->name)) {
  874. char tmp[32] = "";
  875. encrypt_cmd_pass(pass, tmp);
  876. if (!strcmp(tmp, cp->pass))
  877. return 1;
  878. return 0;
  879. }
  880. return 0;
  881. }
  882. int has_cmd_pass(const char *cmd)
  883. {
  884. struct cmd_pass *cp = NULL;
  885. for (cp = cmdpass; cp; cp = cp->next)
  886. if (!egg_strcasecmp(cmd, cp->name))
  887. return 1;
  888. return 0;
  889. }
  890. void set_cmd_pass(char *ln, int shareit)
  891. {
  892. struct cmd_pass *cp = NULL;
  893. char *cmd = NULL;
  894. cmd = newsplit(&ln);
  895. for (cp = cmdpass; cp; cp = cp->next)
  896. if (!strcmp(cmd, cp->name))
  897. break;
  898. if (cp)
  899. if (ln[0]) {
  900. /* change */
  901. strcpy(cp->pass, ln);
  902. if (shareit)
  903. botnet_send_cmdpass(-1, cp->name, cp->pass);
  904. } else {
  905. if (cp == cmdpass)
  906. cmdpass = cp->next;
  907. else {
  908. struct cmd_pass *cp2;
  909. cp2 = cmdpass;
  910. while (cp2->next != cp)
  911. cp2 = cp2->next;
  912. cp2->next = cp->next;
  913. }
  914. if (shareit)
  915. botnet_send_cmdpass(-1, cp->name, "");
  916. free(cp->name);
  917. free(cp);
  918. } else if (ln[0]) {
  919. /* create */
  920. cp = (struct cmd_pass *) my_calloc(1, sizeof(struct cmd_pass));
  921. cp->next = cmdpass;
  922. cmdpass = cp;
  923. cp->name = strdup(cmd);
  924. strcpy(cp->pass, ln);
  925. if (shareit)
  926. botnet_send_cmdpass(-1, cp->name, cp->pass);
  927. }
  928. }