dccutil.c 26 KB

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