/[cvs]/eggdrop1.4/src/dcc.c
ViewVC logotype

Contents of /eggdrop1.4/src/dcc.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.6 - (show annotations) (download) (as text)
Wed Aug 4 15:51:58 1999 UTC (20 years, 1 month ago) by guppy
Branch: MAIN
Changes since 1.5: +6 -4 lines
File MIME type: text/x-chdr
*** empty log message ***

1 /*
2 * dcc.c -- handles:
3 * activity on a dcc socket
4 * disconnect on a dcc socket
5 * ...and that's it! (but it's a LOT)
6 * dprintf'ized, 27oct1995
7 */
8 /*
9 * This file is part of the eggdrop source code
10 * copyright (c) 1997 Robey Pointer
11 * and is distributed according to the GNU general public license.
12 * For full details, read the top of 'main.c' or the file called
13 * COPYING that was distributed with this code.
14 */
15
16 #include "main.h"
17 #include <ctype.h>
18 #include <errno.h>
19 #include "modules.h"
20 #include "tandem.h"
21
22 extern struct userrec *userlist;
23 extern struct chanset_t *chanset;
24 extern Tcl_Interp *interp;
25 extern time_t now;
26 extern int egg_numver, connect_timeout, conmask, backgrd, max_dcc;
27 extern int make_userfile, default_flags, debug_output, ignore_time;
28 extern char botnetnick[], ver[], origbotname[], notify_new[];
29
30 struct dcc_t *dcc = 0; /* dcc list */
31 int dcc_total = 0; /* total dcc's */
32 char tempdir[121] = ""; /* temporary directory (default: current dir) */
33 int require_p = 0; /* require 'p' access to get on the party line? */
34 int allow_new_telnets = 0; /* allow people to introduce themselves via telnet */
35 int stealth_telnets = 0; /* be paranoid? <cybah> */
36 int use_telnet_banner = 0; /* display telnet banner? [seC] */
37 char network[41] = "unknown-net"; /* name of the IRC network you're on */
38 int password_timeout = 180; /* time to wait for a password from a user */
39 int bot_timeout = 60; /* bot timeout value */
40 int identtimeout = 5; /* timeout value for ident lookups */
41 int protect_telnet = 1; /* even bother with ident lookups :) */
42 int flood_telnet_thr = 5; /* number of telnet connections to be considered a flood */
43 int flood_telnet_time = 60; /* in how many seconds? */
44 extern int min_dcc_port, max_dcc_port; /* valid portrange for telnets */
45 extern int par_telnet_flood; /* trigger telnet flood for +f ppl? */
46 char bannerfile[121] = "telnet-banner"; /* file displayed on telnet login */
47
48 static void strip_telnet(int sock, char *buf, int *len)
49 {
50 unsigned char *p = (unsigned char *) buf, *o = (unsigned char *) buf;
51 int mark;
52
53 while (*p != 0) {
54 while ((*p != 255) && (*p != 0))
55 *o++ = *p++;
56 if (*p == 255) {
57 p++;
58 mark = 2;
59 if (!*p)
60 mark = 1; /* bogus */
61 if ((*p >= 251) && (*p <= 254)) {
62 mark = 3;
63 if (!*(p + 1))
64 mark = 2; /* bogus */
65 }
66 if (*p == 251) {
67 /* WILL X -> response: DONT X */
68 /* except WILL ECHO which we just smile and ignore */
69 if (!(*(p + 1) == 1)) {
70 write(sock, "\377\376", 2);
71 write(sock, p + 1, 1);
72 }
73 }
74 if (*p == 253) {
75 /* DO X -> response: WONT X */
76 /* except DO ECHO which we just smile and ignore */
77 if (!(*(p + 1) == 1)) {
78 write(sock, "\377\374", 2);
79 write(sock, p + 1, 1);
80 }
81 }
82 if (*p == 246) {
83 /* "are you there?" */
84 /* response is: "hell yes!" */
85 write(sock, "\r\nHell, yes!\r\n", 14);
86 }
87 /* anything else can probably be ignored */
88 p += mark - 1;
89 *len = *len - mark;
90 }
91 }
92 *o = *p;
93 }
94
95 static void greet_new_bot(int idx)
96 {
97 int bfl = bot_flags(dcc[idx].user);
98 int i;
99
100 dcc[idx].timeval = now;
101 dcc[idx].u.bot->version[0] = 0;
102 dcc[idx].u.bot->numver = 0;
103 if (bfl & BOT_REJECT) {
104 putlog(LOG_BOTS, "*", DCC_REJECT, dcc[idx].nick);
105 dprintf(idx, "error You are being rejected.\n");
106 dprintf(idx, "bye\n");
107 killsock(dcc[idx].sock);
108 lostdcc(idx);
109 return;
110 }
111 if (bfl & BOT_LEAF)
112 dcc[idx].status |= STAT_LEAF;
113 dcc[idx].status |= STAT_LINKING;
114 #ifndef NO_OLD_BOTNET
115 dprintf(idx, "version %d %d %s <%s>\n", egg_numver, HANDLEN, ver, network);
116 #else
117 dprintf(idx, "v %d %d %s <%s>\n", egg_numver, HANDLEN, ver, network);
118 #endif
119 for (i = 0; i < dcc_total; i++)
120 if (dcc[i].type == &DCC_FORK_BOT) {
121 killsock(dcc[i].sock);
122 lostdcc(i);
123 i--;
124 }
125 }
126
127 static void bot_version(int idx, char *par)
128 {
129 char x[1024];
130 int l;
131
132 context;
133 dcc[idx].timeval = now;
134 if ((par[0] >= '0') && (par[0] <= '9')) {
135 char *work;
136
137 work = newsplit(&par);
138 dcc[idx].u.bot->numver = atoi(work);
139 } else
140 dcc[idx].u.bot->numver = 0;
141
142 #ifndef NO_OLD_BOTNET
143 if (b_numver(idx) < NEAT_BOTNET) {
144 #if HANDLEN != 9
145 dprintf(idx, "error Non-matching handle length: mine %d, yours 9\n",
146 HANDLEN);
147 dprintf(idx, "bye\n");
148 killsock(dcc[idx].sock);
149 lostdcc(idx);
150 return;
151 #else
152 dprintf(idx, "thisbot %s\n", botnetnick);
153 #endif
154 } else {
155 #endif
156 dprintf(idx, "tb %s\n", botnetnick);
157 l = atoi(newsplit(&par));
158 if (l != HANDLEN) {
159 dprintf(idx, "error Non-matching handle length: mine %d, yours %d\n",
160 HANDLEN, l);
161 dprintf(idx, "bye\n");
162 killsock(dcc[idx].sock);
163 lostdcc(idx);
164 return;
165 }
166 #ifndef NO_OLD_BOTNET
167 }
168 #endif
169 strncpy(dcc[idx].u.bot->version, par, 120);
170 dcc[idx].u.bot->version[120] = 0;
171 putlog(LOG_BOTS, "*", DCC_LINKED, dcc[idx].nick);
172 chatout("*** Linked to %s\n", dcc[idx].nick);
173 botnet_send_nlinked(idx, dcc[idx].nick, botnetnick, '!',
174 dcc[idx].u.bot->numver);
175 dump_links(idx);
176 dcc[idx].type = &DCC_BOT;
177 addbot(dcc[idx].nick, dcc[idx].nick, botnetnick, '-',
178 dcc[idx].u.bot->numver);
179 check_tcl_link(dcc[idx].nick, botnetnick);
180 simple_sprintf(x, "v %d", dcc[idx].u.bot->numver);
181 bot_share(idx, x);
182 dprintf(idx, "el\n");
183 }
184
185 void failed_link(int idx)
186 {
187 char s[81], s1[512];
188
189 if (dcc[idx].port >= dcc[idx].u.bot->port + 3) {
190 if (dcc[idx].u.bot->linker[0]) {
191 sprintf(s, "Couldn't link to %s.", dcc[idx].nick);
192 strcpy(s1, dcc[idx].u.bot->linker);
193 add_note(s1, botnetnick, s, -2, 0);
194 }
195 if (dcc[idx].u.bot->numver >= (-1))
196 putlog(LOG_BOTS, "*", DCC_LINKFAIL, dcc[idx].nick);
197 killsock(dcc[idx].sock);
198 strcpy(s, dcc[idx].nick);
199 lostdcc(idx);
200 autolink_cycle(s); /* check for more auto-connections */
201 return;
202 }
203 /* try next port */
204 killsock(dcc[idx].sock);
205 dcc[idx].sock = getsock(SOCK_STRONGCONN);
206 dcc[idx].port++;
207 dcc[idx].timeval = now;
208 if (open_telnet_raw(dcc[idx].sock, dcc[idx].host, dcc[idx].port) < 0) {
209 failed_link(idx);
210 }
211 }
212
213 static void cont_link(int idx, char *buf, int i)
214 {
215 char *s, x[1024];
216 struct userrec *u = get_user_by_handle(userlist, dcc[idx].nick);
217 int atr = bot_flags(dcc[idx].user);
218
219 context;
220 if (atr & BOT_HUB) {
221 /* disconnect all +a bots because we just got a hub */
222 for (i = 0; i < dcc_total; i++) {
223 if ((i != idx) && (bot_flags(dcc[i].user) & BOT_ALT)) {
224 if (dcc[i].type == &DCC_FORK_BOT) {
225 killsock(dcc[i].sock);
226 lostdcc(i);
227 } else if (dcc[i].type == &DCC_BOT_NEW) {
228 killsock(dcc[i].sock);
229 lostdcc(i);
230 }
231 }
232 }
233 /* just those currently in the process of linking */
234 if (in_chain(dcc[idx].nick)) {
235 i = nextbot(dcc[idx].nick);
236 if (i > 0) {
237 simple_sprintf(x, "Unlinked %s (restructure)", dcc[i].nick);
238 chatout("*** %s\n", x);
239 botnet_send_unlinked(i, dcc[i].nick, x);
240 dprintf(i, "bye\n");
241 killsock(dcc[i].sock);
242 lostdcc(i);
243 }
244 }
245 }
246 dcc[idx].type = &DCC_BOT_NEW;
247 dcc[idx].u.bot->numver = 0;
248 s = get_user(&USERENTRY_PASS, u);
249 if (!s || !strcmp(s, "-"))
250 dprintf(idx, "%s\n", botnetnick);
251 else
252 dprintf(idx, "%s\n%s\n", botnetnick, s);
253 return;
254 }
255
256 static void dcc_bot_new(int idx, char *buf, int x)
257 {
258 struct userrec *u = get_user_by_handle(userlist, dcc[idx].nick);
259 char *code;
260
261 strip_telnet(dcc[idx].sock, buf, &x);
262 code = newsplit(&buf);
263 if (!strcasecmp(code, "*hello!")) {
264 greet_new_bot(idx);
265 } else if (!strcasecmp(code, "version") || !strcasecmp(code, "v")) {
266 bot_version(idx, buf);
267 } else if (!strcasecmp(code, "badpass")) {
268 /* we entered the wrong password */
269 putlog(LOG_BOTS, "*", DCC_BADPASS, dcc[idx].nick);
270 } else if (!strcasecmp(code, "passreq")) {
271 if (u_pass_match(u, "-")) {
272 putlog(LOG_BOTS, "*", DCC_PASSREQ, dcc[idx].nick);
273 dprintf(idx, "-\n");
274 }
275 } else if (!strcasecmp(code, "error")) {
276 putlog(LOG_BOTS, "*", DCC_LINKERROR, dcc[idx].nick, buf);
277 }
278 /* ignore otherwise */
279 }
280
281 static void eof_dcc_bot_new(int idx)
282 {
283 context;
284 putlog(LOG_BOTS, "*", DCC_LOSTBOT, dcc[idx].nick, dcc[idx].port);
285 killsock(dcc[idx].sock);
286 lostdcc(idx);
287 }
288
289 static void timeout_dcc_bot_new(int idx)
290 {
291 putlog(LOG_BOTS, "*", DCC_TIMEOUT, dcc[idx].nick,
292 dcc[idx].host, dcc[idx].port);
293 killsock(dcc[idx].sock);
294 lostdcc(idx);
295 }
296
297 static void display_dcc_bot_new(int idx, char *buf)
298 {
299 sprintf(buf, "bot* waited %lus", now - dcc[idx].timeval);
300 }
301
302 static int expmem_dcc_bot_(void *x)
303 {
304 return sizeof(struct bot_info);
305 }
306
307 static void free_dcc_bot_(int n, void *x)
308 {
309 if (dcc[n].type == &DCC_BOT) {
310 unvia(n, findbot(dcc[n].nick));
311 rembot(dcc[n].nick);
312 }
313 nfree(x);
314 }
315
316 struct dcc_table DCC_BOT_NEW =
317 {
318 "BOT_NEW",
319 0,
320 eof_dcc_bot_new,
321 dcc_bot_new,
322 &bot_timeout,
323 timeout_dcc_bot_new,
324 display_dcc_bot_new,
325 expmem_dcc_bot_,
326 free_dcc_bot_,
327 0
328 };
329
330 /* hash function for tandem bot commands */
331 extern botcmd_t C_bot[];
332
333 static void dcc_bot(int idx, char *code, int i)
334 {
335 char *msg;
336 int f;
337
338 context;
339 strip_telnet(dcc[idx].sock, code, &i);
340 if (debug_output) {
341 if (code[0] == 's')
342 putlog(LOG_BOTSHARE, "*", "{%s} %s", dcc[idx].nick, code + 2);
343 else
344 putlog(LOG_BOTNET, "*", "[%s] %s", dcc[idx].nick, code);
345 }
346 msg = strchr(code, ' ');
347 if (msg) {
348 *msg = 0;
349 msg++;
350 } else
351 msg = "";
352 f = 0;
353 i = 0;
354 while ((C_bot[i].name != NULL) && (!f)) {
355 int y = strcasecmp(code, C_bot[i].name);
356
357 if (y == 0) {
358 /* found a match */
359 (C_bot[i].func) (idx, msg);
360 f = 1;
361 } else if (y < 0)
362 return;
363 i++;
364 }
365 }
366
367 static void eof_dcc_bot(int idx)
368 {
369 char x[1024];
370
371 simple_sprintf(x, "Lost bot: %s", dcc[idx].nick);
372 putlog(LOG_BOTS, "*", "%s.", x);
373 chatout("*** %s\n", x);
374 botnet_send_unlinked(idx, dcc[idx].nick, x);
375 killsock(dcc[idx].sock);
376 lostdcc(idx);
377 }
378
379 static void display_dcc_bot(int idx, char *buf)
380 {
381 int i = simple_sprintf(buf, "bot flags: ");
382
383 buf[i++] = b_status(idx) & STAT_PINGED ? 'P' : 'p';
384 buf[i++] = b_status(idx) & STAT_SHARE ? 'U' : 'u';
385 buf[i++] = b_status(idx) & STAT_CALLED ? 'C' : 'c';
386 buf[i++] = b_status(idx) & STAT_OFFERED ? 'O' : 'o';
387 buf[i++] = b_status(idx) & STAT_SENDING ? 'S' : 's';
388 buf[i++] = b_status(idx) & STAT_GETTING ? 'G' : 'g';
389 buf[i++] = b_status(idx) & STAT_WARNED ? 'W' : 'w';
390 buf[i++] = b_status(idx) & STAT_LEAF ? 'L' : 'l';
391 buf[i++] = b_status(idx) & STAT_LINKING ? 'I' : 'i';
392 buf[i++] = b_status(idx) & STAT_AGGRESSIVE ? 'a' : 'A';
393 buf[i++] = 0;
394 }
395
396 static void display_dcc_fork_bot(int idx, char *buf)
397 {
398 sprintf(buf, "conn bot");
399 }
400
401 struct dcc_table DCC_BOT =
402 {
403 "BOT",
404 DCT_BOT,
405 eof_dcc_bot,
406 dcc_bot,
407 0,
408 0,
409 display_dcc_bot,
410 expmem_dcc_bot_,
411 free_dcc_bot_,
412 0
413 };
414
415 struct dcc_table DCC_FORK_BOT =
416 {
417 "FORK_BOT",
418 0,
419 failed_link,
420 cont_link,
421 &connect_timeout,
422 failed_link,
423 display_dcc_fork_bot,
424 expmem_dcc_bot_,
425 free_dcc_bot_,
426 0
427 };
428
429 static void dcc_chat_pass(int idx, char *buf, int atr)
430 {
431 if (!atr)
432 return;
433 strip_telnet(dcc[idx].sock, buf, &atr);
434 atr = dcc[idx].user ? dcc[idx].user->flags : 0;
435 if (u_pass_match(dcc[idx].user, buf)) {
436 if (atr & USER_BOT) {
437 nfree(dcc[idx].u.chat);
438 dcc[idx].type = &DCC_BOT_NEW;
439 dcc[idx].u.bot = get_data_ptr(sizeof(struct bot_info));
440
441 dcc[idx].status = STAT_CALLED;
442 dprintf(idx, "*hello!\n");
443 greet_new_bot(idx);
444 } else {
445 /* log entry for successful login -slennox 3/28/1999 */
446 putlog(LOG_MISC, "*", DCC_LOGGEDIN, dcc[idx].nick,
447 dcc[idx].host, dcc[idx].port);
448 if (dcc[idx].u.chat->away) {
449 nfree(dcc[idx].u.chat->away);
450 dcc[idx].u.chat->away = NULL;
451 }
452 dcc[idx].type = &DCC_CHAT;
453 dcc[idx].status &= ~STAT_CHAT;
454 dcc[idx].u.chat->con_flags = (atr & USER_MASTER) ? conmask : 0;
455 dcc[idx].u.chat->channel = -2;
456 if (dcc[idx].status & STAT_TELNET)
457 dprintf(idx, "\377\374\001\n"); /* turn echo back on */
458 dcc_chatter(idx);
459 }
460 } else {
461 if (atr & USER_BOT)
462 dprintf(idx, "badpass\n");
463 else
464 dprintf(idx, DCC_HOUSTON);
465 putlog(LOG_MISC, "*", DCC_BADLOGIN, dcc[idx].nick,
466 dcc[idx].host, dcc[idx].port);
467 if (dcc[idx].u.chat->away) { /* su from a dumb user */
468 if (dcc[idx].status & STAT_TELNET)
469 dprintf(idx, "\377\374\001\n"); /* turn echo back on */
470 dcc[idx].user = get_user_by_handle(userlist, dcc[idx].u.chat->away);
471 strcpy(dcc[idx].nick, dcc[idx].u.chat->away);
472 nfree(dcc[idx].u.chat->away);
473 nfree(dcc[idx].u.chat->su_nick);
474 dcc[idx].u.chat->away = NULL;
475 dcc[idx].u.chat->su_nick = NULL;
476 dcc[idx].type = &DCC_CHAT;
477 if (dcc[idx].u.chat->channel < 100000)
478 botnet_send_join_idx(idx, -1);
479 chanout_but(-1, dcc[idx].u.chat->channel, DCC_JOIN, dcc[idx].nick);
480 } else {
481 killsock(dcc[idx].sock);
482 lostdcc(idx);
483 }
484 }
485 }
486
487 static void eof_dcc_general(int idx)
488 {
489 putlog(LOG_MISC, "*",DCC_LOSTDCC, dcc[idx].nick,
490 dcc[idx].host, dcc[idx].port);
491 killsock(dcc[idx].sock);
492 lostdcc(idx);
493 }
494
495 static void tout_dcc_chat_pass(int idx)
496 {
497 dprintf(idx, "Timeout.\n");
498 putlog(LOG_MISC, "*",DCC_PWDTIMEOUT, dcc[idx].nick,
499 dcc[idx].host);
500 killsock(dcc[idx].sock);
501 lostdcc(idx);
502 }
503
504 static void display_dcc_chat_pass(int idx, char *buf)
505 {
506 sprintf(buf, "pass waited %lus", now - dcc[idx].timeval);
507 }
508
509 static int expmem_dcc_general(void *x)
510 {
511 register struct chat_info *p = (struct chat_info *) x;
512 int tot = sizeof(struct chat_info);
513
514 if (p->away)
515 tot += strlen(p->away) + 1;
516 if (p->buffer) {
517 struct msgq *q = p->buffer;
518
519 while (q) {
520 tot += sizeof(struct list_type);
521
522 tot += q->len + 1;
523 q = q->next;
524 }
525 }
526 return tot;
527 }
528
529 static void kill_dcc_general(int idx, void *x)
530 {
531 register struct chat_info *p = (struct chat_info *) x;
532
533 if (p) {
534 if (p->buffer) {
535 struct msgq *r = dcc[idx].u.chat->buffer, *q;
536
537 while (r) {
538 q = r->next;
539 nfree(r->msg);
540 nfree(r);
541 r = q;
542 }
543 }
544 if (p->away) {
545 nfree(p->away);
546 }
547 nfree(p);
548 }
549 }
550
551 /* Remove the color control codes that mIRC,pIRCh etc use to make
552 * their client seem so fecking cool! (Sorry, Khaled, you are a nice
553 * guy, but when you added this feature you forced people to either
554 * use your *SHAREWARE* client or face screenfulls of crap!) */
555 static void strip_mirc_codes(int flags, char *text)
556 {
557 char *dd = text;
558
559 while (*text) {
560 switch (*text) {
561 case 2: /* Bold text */
562 if (flags & STRIP_BOLD) {
563 text++;
564 continue;
565 }
566 break;
567 case 3: /* mIRC colors? */
568 if (flags & STRIP_COLOR) {
569 if (isdigit(text[1])) { /* Is the first char a number? */
570 text += 2; /* Skip over the ^C and the first digit */
571 if (isdigit(*text))
572 text++; /* Is this a double digit number? */
573 if (*text == ',') { /* Do we have a background color next? */
574 if (isdigit(text[1]))
575 text += 2; /* Skip over the first background digit */
576 if (isdigit(*text))
577 text++; /* Is it a double digit? */
578 }
579 } else
580 text++;
581 continue;
582 }
583 break;
584 case 7:
585 if (flags & STRIP_BELLS) {
586 text++;
587 continue;
588 }
589 break;
590 case 0x16: /* Reverse video */
591 if (flags & STRIP_REV) {
592 text++;
593 continue;
594 }
595 break;
596 case 0x1f: /* Underlined text */
597 if (flags & STRIP_UNDER) {
598 text++;
599 continue;
600 }
601 break;
602 case 033:
603 if (flags & STRIP_ANSI) {
604 text++;
605 if (*text == '[') {
606 text++;
607 while ((*text == ';') || isdigit(*text))
608 text++;
609 if (*text)
610 text++; /* also kill the following char */
611 }
612 continue;
613 }
614 break;
615 }
616 *dd++ = *text++; /* Move on to the next char */
617 }
618 *dd = 0;
619 }
620
621 static void append_line(int idx, char *line)
622 {
623 int l = strlen(line);
624 struct msgq *p, *q;
625 struct chat_info *c = (dcc[idx].type == &DCC_CHAT) ? dcc[idx].u.chat :
626 dcc[idx].u.file->chat;
627
628 if (c->current_lines > 1000) {
629 p = c->buffer;
630 /* they're probably trying to fill up the bot nuke the sods :) */
631 while (p) { /* flush their queue */
632 q = p->next;
633 nfree(p->msg);
634 nfree(p);
635 p = q;
636 }
637 c->buffer = 0;
638 dcc[idx].status &= ~STAT_PAGE;
639 do_boot(idx, botnetnick, "too many pages - senq full");
640 return;
641 }
642 if ((c->line_count < c->max_line) && (c->buffer == NULL)) {
643 c->line_count++;
644 tputs(dcc[idx].sock, line, l);
645 } else {
646 c->current_lines++;
647 if (c->buffer == NULL)
648 q = NULL;
649 else {
650 q = c->buffer;
651 while (q->next != NULL)
652 q = q->next;
653 }
654 p = get_data_ptr(sizeof(struct msgq));
655
656 p->len = l;
657 p->msg = get_data_ptr(l + 1);
658 p->next = NULL;
659 strcpy(p->msg, line);
660 if (q == NULL)
661 c->buffer = p;
662 else
663 q->next = p;
664 }
665 }
666
667 static void out_dcc_general(int idx, char *buf, void *x)
668 {
669 register struct chat_info *p = (struct chat_info *) x;
670 char *y = buf;
671
672 strip_mirc_codes(p->strip_flags, buf);
673 if (dcc[idx].status & STAT_TELNET)
674 y = add_cr(buf);
675 if (dcc[idx].status & STAT_PAGE)
676 append_line(idx, y);
677 else
678 tputs(dcc[idx].sock, y, strlen(y));
679 }
680
681 struct dcc_table DCC_CHAT_PASS =
682 {
683 "CHAT_PASS",
684 0,
685 eof_dcc_general,
686 dcc_chat_pass,
687 &password_timeout,
688 tout_dcc_chat_pass,
689 display_dcc_chat_pass,
690 expmem_dcc_general,
691 kill_dcc_general,
692 out_dcc_general
693 };
694
695 /* make sure ansi code is just for color-changing */
696 static int check_ansi(char *v)
697 {
698 int count = 2;
699
700 if (*v++ != '\033')
701 return 1;
702 if (*v++ != '[')
703 return 1;
704 while (*v) {
705 if (*v == 'm')
706 return 0;
707 if ((*v != ';') && ((*v < '0') || (*v > '9')))
708 return count;
709 v++;
710 count++;
711 }
712 return count;
713 }
714
715 static void eof_dcc_chat(int idx)
716 {
717 context;
718 putlog(LOG_MISC, "*", DCC_LOSTDCC, dcc[idx].nick,
719 dcc[idx].host, dcc[idx].port);
720 context;
721 if (dcc[idx].u.chat->channel >= 0) {
722 chanout_but(idx, dcc[idx].u.chat->channel, "*** %s lost dcc link.\n",
723 dcc[idx].nick);
724 context;
725 if (dcc[idx].u.chat->channel < 100000)
726 botnet_send_part_idx(idx, "lost dcc link");
727 check_tcl_chpt(botnetnick, dcc[idx].nick, dcc[idx].sock,
728 dcc[idx].u.chat->channel);
729 }
730 context;
731 check_tcl_chof(dcc[idx].nick, dcc[idx].sock);
732 context;
733 killsock(dcc[idx].sock);
734 context;
735 lostdcc(idx);
736 context;
737 }
738
739 static void dcc_chat(int idx, char *buf, int i)
740 {
741 int nathan = 0, doron = 0, fixed = 0;
742 char *v, *d;
743
744 context;
745 strip_telnet(dcc[idx].sock, buf, &i);
746 if (buf[0] && (buf[0] != '.') &&
747 detect_dcc_flood(&dcc[idx].timeval, dcc[idx].u.chat, idx))
748 return;
749 dcc[idx].timeval = now;
750 if (buf[0])
751 strcpy(buf, check_tcl_filt(idx, buf));
752 if (buf[0]) {
753 /* check for beeps and cancel annoying ones */
754 v = buf;
755 d = buf;
756 while (*v)
757 switch (*v) {
758 case 7: /* beep - no more than 3 */
759 nathan++;
760 if (nathan > 3)
761 v++;
762 else
763 *d++ = *v++;
764 break;
765 case 8: /* backspace - for lame telnet's :) */
766 if (d > buf) {
767 d--;
768 }
769 v++;
770 break;
771 case 27: /* ESC - ansi code? */
772 doron = check_ansi(v);
773 /* if it's valid, append a return-to-normal code at the end */
774 if (!doron) {
775 *d++ = *v++;
776 fixed = 1;
777 } else
778 v += doron;
779 break;
780 case '\r': /* weird pseudo-linefeed */
781 v++;
782 break;
783 default:
784 *d++ = *v++;
785 }
786 if (fixed)
787 strcpy(d, "\033[0m");
788 else
789 *d = 0;
790 if (buf[0]) { /* nothing to say - maybe paging... */
791 if ((buf[0] == '.') || (dcc[idx].u.chat->channel < 0)) {
792 if (buf[0] == '.')
793 buf++;
794 v = newsplit(&buf);
795 if (check_tcl_dcc(v, idx, buf)) {
796 check_tcl_chpt(botnetnick, dcc[idx].nick, dcc[idx].sock,
797 dcc[idx].u.chat->channel);
798 check_tcl_chof(dcc[idx].nick, dcc[idx].sock);
799 dprintf(idx, "*** Ja mata!\n");
800 flush_lines(idx, dcc[idx].u.chat);
801 putlog(LOG_MISC, "*", DCC_CLOSED, dcc[idx].nick,
802 dcc[idx].host);
803 if (dcc[idx].u.chat->channel >= 0) {
804 chanout_but(-1, dcc[idx].u.chat->channel,
805 "*** %s left the party line%s%s\n",
806 dcc[idx].nick, buf[0] ? ": " : ".", buf);
807 if (dcc[idx].u.chat->channel < 100000)
808 botnet_send_part_idx(idx, buf);
809 }
810 if (dcc[idx].u.chat->su_nick) {
811 dcc[idx].user = get_user_by_handle(userlist, dcc[idx].u.chat->su_nick);
812 strcpy(dcc[idx].nick, dcc[idx].u.chat->su_nick);
813 dcc[idx].type = &DCC_CHAT;
814 if (dcc[idx].u.chat->channel < 100000)
815 botnet_send_join_idx(idx, -1);
816 dprintf(idx, "Returning to real nick %s!\r\n", dcc[idx].u.chat->su_nick);
817 nfree(dcc[idx].u.chat->su_nick);
818 dcc[idx].u.chat->su_nick = NULL;
819 /* chanout_but(-1, dcc[idx].u.chat->channel, "*** %s has rejoined the party line.\n", dcc[idx].nick); */
820 dcc_chatter(idx);
821 return;
822 } else if ((dcc[idx].sock != STDOUT) || backgrd) {
823 killsock(dcc[idx].sock);
824 lostdcc(idx);
825 return;
826 } else {
827 dprintf(DP_STDOUT, "\n### SIMULATION RESET\n\n");
828 dcc_chatter(idx);
829 return;
830 }
831 }
832 } else if (buf[0] == ',') {
833 int me = 0;
834
835 if ((buf[1] == 'm') && (buf[2] == 'e') && buf[3] == ' ')
836 me = 1;
837 for (i = 0; i < dcc_total; i++) {
838 int ok = 0;
839
840 if (dcc[i].type->flags & DCT_MASTER) {
841 if ((dcc[i].type != &DCC_CHAT) ||
842 (dcc[i].u.chat->channel >= 0))
843 if ((i != idx) || (dcc[idx].status & STAT_ECHO))
844 ok = 1;
845 }
846 if (ok) {
847 struct userrec *u = get_user_by_handle(userlist, dcc[i].nick);
848
849 if (u && (u->flags & USER_MASTER)) {
850 if (me)
851 dprintf(i, "-> %s%s\n", dcc[idx].nick, buf + 3);
852 else
853 dprintf(i, "-%s-> %s\n", dcc[idx].nick, buf + 1);
854 }
855 }
856 }
857 } else if (buf[0] == '\'') {
858 int me = 0;
859
860 if ((buf[1] == 'm') && (buf[2] == 'e') &&
861 ((buf[3] == ' ') || (buf[3] == '\'') || (buf[3] == ',')))
862 me = 1;
863 for (i = 0; i < dcc_total; i++) {
864 if (dcc[i].type->flags & DCT_CHAT) {
865 if (me)
866 dprintf(i, "=> %s%s\n", dcc[idx].nick, buf + 3);
867 else
868 dprintf(i, "=%s=> %s\n", dcc[idx].nick, buf + 1);
869 }
870 }
871 } else {
872 if (dcc[idx].u.chat->away != NULL)
873 not_away(idx);
874 if (dcc[idx].status & STAT_ECHO)
875 chanout_but(-1, dcc[idx].u.chat->channel,
876 "<%s> %s\n", dcc[idx].nick, buf);
877 else
878 chanout_but(idx, dcc[idx].u.chat->channel, "<%s> %s\n",
879 dcc[idx].nick, buf);
880 botnet_send_chan(-1, botnetnick, dcc[idx].nick,
881 dcc[idx].u.chat->channel, buf);
882 check_tcl_chat(dcc[idx].nick, dcc[idx].u.chat->channel, buf);
883 }
884 }
885 }
886 if (dcc[idx].type == &DCC_CHAT) /* could have change to files */
887 if (dcc[idx].status & STAT_PAGE)
888 flush_lines(idx, dcc[idx].u.chat);
889 }
890
891 static void display_dcc_chat(int idx, char *buf)
892 {
893 int i = simple_sprintf(buf, "chat flags: ");
894
895 buf[i++] = dcc[idx].status & STAT_CHAT ? 'C' : 'c';
896 buf[i++] = dcc[idx].status & STAT_PARTY ? 'P' : 'p';
897 buf[i++] = dcc[idx].status & STAT_TELNET ? 'T' : 't';
898 buf[i++] = dcc[idx].status & STAT_ECHO ? 'E' : 'e';
899 buf[i++] = dcc[idx].status & STAT_PAGE ? 'P' : 'p';
900 simple_sprintf(buf + i, "/%d", dcc[idx].u.chat->channel);
901 }
902
903 struct dcc_table DCC_CHAT =
904 {
905 "CHAT",
906 DCT_CHAT | DCT_MASTER | DCT_SHOWWHO | DCT_VALIDIDX | DCT_SIMUL |
907 DCT_CANBOOT | DCT_REMOTEWHO,
908 eof_dcc_chat,
909 dcc_chat,
910 0,
911 0,
912 display_dcc_chat,
913 expmem_dcc_general,
914 kill_dcc_general,
915 out_dcc_general
916 };
917
918 static int lasttelnets;
919 static char lasttelnethost[81];
920 static time_t lasttelnettime;
921
922 /* a modified detect_flood for incoming telnet flood protection */
923 static int detect_telnet_flood(char *floodhost)
924 {
925 struct flag_record fr =
926 {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0};
927 context;
928 get_user_flagrec(get_user_by_host(floodhost), &fr, NULL);
929 context;
930 if (flood_telnet_thr == 0 || (glob_friend(fr) && !par_telnet_flood))
931 return 0; /* no flood protection */
932 if (strcasecmp(lasttelnethost, floodhost) != 0) { /* new */
933 strcpy(lasttelnethost, floodhost);
934 lasttelnettime = now;
935 lasttelnets = 0;
936 return 0;
937 }
938 if (lasttelnettime < now - flood_telnet_time) {
939 /* flood timer expired, reset it */
940 lasttelnettime = now;
941 lasttelnets = 0;
942 return 0;
943 }
944 lasttelnets++;
945 if (lasttelnets >= flood_telnet_thr) { /* FLOOD */
946 /* reset counters */
947 lasttelnets = 0;
948 lasttelnettime = 0;
949 lasttelnethost[0] = 0;
950 putlog(LOG_MISC, "*", IRC_TELNETFLOOD, floodhost);
951 addignore(floodhost, origbotname, "Telnet connection flood",
952 now + (60 * ignore_time));
953 return 1;
954 }
955 return 0;
956 }
957
958 static void dcc_telnet_got_ident(int, char *);
959
960 static void dcc_telnet(int idx, char *buf, int i)
961 {
962 unsigned long ip;
963 unsigned short port;
964 int j = 0, sock;
965 char s[UHOSTLEN + 1], s2[UHOSTLEN + 20];
966
967 context;
968 if (dcc_total + 1 > max_dcc) {
969 j = answer(dcc[idx].sock, s, &ip, &port, 0);
970 if (j != -1) {
971 dprintf(-j, "Sorry, too many connections already.\r\n");
972 killsock(j);
973 }
974 return;
975 }
976 context;
977 sock = answer(dcc[idx].sock, s, &ip, &port, 0);
978 while ((sock == -1) && (errno == EAGAIN))
979 sock = answer(sock, s, &ip, &port, 0);
980 if (sock < 0) {
981 neterror(s);
982 putlog(LOG_MISC, "*", DCC_FAILED, s);
983 killsock(sock);
984 return;
985 }
986 /* <bindle> [09:37] Telnet connection: 168.246.255.191/0
987 * <bindle> [09:37] Lost connection while identing [168.246.255.191/0]
988 */
989 context;
990 /* use dcc-portrange x:x on incoming telnets to ,dw */
991 if ((port < min_dcc_port) || (port > max_dcc_port)) {
992 putlog(LOG_BOTS, "*", DCC_BADSRC, s, port);
993 killsock(sock);
994 return;
995 }
996 context;
997 /* deny ips that ends with 0 or 255, dw */
998 if ((ip & 0xff) == 0 || (ip & 0xff) == 0xff) {
999 putlog(LOG_BOTS, "*", DCC_BADIP, s, port);
1000 killsock(sock);
1001 return;
1002 }
1003 if (dcc[idx].host[0] == '@') {
1004 /* restrict by hostname */
1005 if (!wild_match(dcc[idx].host + 1, s)) {
1006 putlog(LOG_BOTS, "*", DCC_BADHOST, s);
1007 killsock(sock);
1008 return;
1009 }
1010 }
1011 context;
1012 sprintf(s2, "telnet!telnet@%s", s);
1013 if (match_ignore(s2) || detect_telnet_flood(s2)) {
1014 killsock(sock);
1015 return;
1016 }
1017 context;
1018 i = new_dcc(&DCC_IDENTWAIT, 0);
1019 dcc[i].sock = sock;
1020 dcc[i].addr = ip;
1021 dcc[i].port = port;
1022 dcc[i].timeval = now;
1023 dcc[i].u.ident_sock = dcc[idx].sock;
1024 strncpy(dcc[i].host, s, UHOSTLEN - 1);
1025 dcc[i].host[UHOSTLEN - 1] = 0;
1026 strcpy(dcc[i].nick, "*");
1027 sock = open_telnet(s, 113);
1028 putlog(LOG_MISC, "*", DCC_TELCONN, s, port);
1029 s[0] = 0;
1030 context;
1031 if (sock < 0) {
1032 if (sock == -2)
1033 strcpy(s, "DNS lookup failed for ident");
1034 else
1035 neterror(s);
1036 } else {
1037 j = new_dcc(&DCC_IDENT, 0);
1038 if (j < 0) {
1039 killsock(sock);
1040 strcpy(s, "No Free DCC's");
1041 }
1042 }
1043 context;
1044 if (s[0]) {
1045 putlog(LOG_MISC, "*", DCC_IDENTFAIL, dcc[i].host, s);
1046 sprintf(s, "telnet@%s", dcc[i].host);
1047 dcc_telnet_got_ident(i, s);
1048 return;
1049 }
1050 context;
1051 dcc[j].sock = sock;
1052 dcc[j].port = 113;
1053 dcc[j].addr = ip;
1054 strcpy(dcc[j].host, dcc[i].host);
1055 strcpy(dcc[j].nick, "*");
1056 dcc[j].u.ident_sock = dcc[i].sock;
1057 dcc[j].timeval = now;
1058 dprintf(j, "%d, %d\n", dcc[i].port, dcc[idx].port);
1059 }
1060
1061 static void eof_dcc_telnet(int idx)
1062 {
1063 putlog(LOG_MISC, "*", DCC_PORTDIE,
1064 dcc[idx].port);
1065 killsock(dcc[idx].sock);
1066 lostdcc(idx);
1067 }
1068
1069 static void display_telnet(int idx, char *buf)
1070 {
1071 strcpy(buf, "lstn");
1072 }
1073
1074 struct dcc_table DCC_TELNET =
1075 {
1076 "TELNET",
1077 DCT_LISTEN,
1078 eof_dcc_telnet,
1079 dcc_telnet,
1080 0,
1081 0,
1082 display_telnet,
1083 0,
1084 0,
1085 0
1086 };
1087
1088 static void dcc_telnet_id(int idx, char *buf, int atr)
1089 {
1090 int ok = 0;
1091 struct flag_record fr =
1092 {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0};
1093
1094 context;
1095 strip_telnet(dcc[idx].sock, buf, &atr);
1096 buf[HANDLEN] = 0;
1097 /* toss out bad nicknames */
1098 if ((dcc[idx].nick[0] != '@') && (!wild_match(dcc[idx].nick, buf))) {
1099 dprintf(idx, "Sorry, that nickname format is invalid.\r\n");
1100
1101 putlog(LOG_BOTS, "*", DCC_BADNICK, dcc[idx].host);
1102 killsock(dcc[idx].sock);
1103 lostdcc(idx);
1104 return;
1105 }
1106 dcc[idx].user = get_user_by_handle(userlist, buf);
1107 get_user_flagrec(dcc[idx].user, &fr, NULL);
1108 /* make sure users-only/bots-only connects are honored */
1109 if ((dcc[idx].status & STAT_BOTONLY) && !glob_bot(fr)) {
1110 dprintf(idx, "This telnet port is for bots only.\r\n");
1111 putlog(LOG_BOTS, "*", DCC_NONBOT, dcc[idx].host);
1112 killsock(dcc[idx].sock);
1113 lostdcc(idx);
1114 return;
1115 }
1116 if ((dcc[idx].status & STAT_USRONLY) && glob_bot(fr)) {
1117 dprintf(idx, "error Only users may connect at this port.\n");
1118 putlog(LOG_BOTS, "*", DCC_NONUSER, dcc[idx].host);
1119 killsock(dcc[idx].sock);
1120 lostdcc(idx);
1121 return;
1122 }
1123 dcc[idx].status &= ~(STAT_BOTONLY | STAT_USRONLY);
1124 if ((!strcasecmp(buf, "NEW")) &&
1125 ((allow_new_telnets) || (make_userfile))) {
1126 dcc[idx].type = &DCC_TELNET_NEW;
1127 dcc[idx].timeval = now;
1128 dprintf(idx, "\r\n");
1129 dprintf(idx, IRC_TELNET, IRC_TELNET_ARGS);
1130 dprintf(idx, IRC_TELNET1);
1131 dprintf(idx, "\r\nEnter the nickname you would like to use.\r\n");
1132 return;
1133 }
1134 if (chan_op(fr)) {
1135 if (!require_p)
1136 ok = 1;
1137 }
1138 if (glob_party(fr) || glob_bot(fr))
1139 ok = 1;
1140 if (glob_xfer(fr)) {
1141 module_entry *me = module_find("filesys", 0, 0);
1142
1143 if (me && me->funcs[FILESYS_ISVALID] && (me->funcs[FILESYS_ISVALID]) ())
1144 ok = 1;
1145 }
1146 if (!ok) {
1147 dprintf(idx, "You don't have access.\r\n");
1148 putlog(LOG_BOTS, "*", DCC_INVHANDLE,
1149 dcc[idx].host, buf);
1150 killsock(dcc[idx].sock);
1151 lostdcc(idx);
1152 return;
1153 }
1154 if (glob_bot(fr)) {
1155 if (in_chain(buf)) {
1156 dprintf(idx, "error Already connected.\n");
1157 putlog(LOG_BOTS, "*", DCC_DUPLICATE,
1158 dcc[idx].host);
1159 killsock(dcc[idx].sock);
1160 lostdcc(idx);
1161 return;
1162 }
1163 }
1164 /* no password set? */
1165 if (u_pass_match(dcc[idx].user, "-")) {
1166 if (glob_bot(fr)) {
1167 char ps[20];
1168
1169 makepass(ps);
1170 set_user(&USERENTRY_PASS, dcc[idx].user, ps);
1171 correct_handle(buf);
1172 strcpy(dcc[idx].nick, buf);
1173 nfree(dcc[idx].u.chat);
1174 dcc[idx].u.bot = get_data_ptr(sizeof(struct bot_info));
1175
1176 dcc[idx].type = &DCC_BOT_NEW;
1177 dcc[idx].status = STAT_CALLED;
1178 dprintf(idx, "*hello!\n");
1179 greet_new_bot(idx);
1180 #ifdef NO_OLD_BOTNET
1181 dprintf(idx, "h %s\n", ps);
1182 #else
1183 dprintf(idx, "handshake %s\n", ps);
1184 #endif
1185 return;
1186 }
1187 dprintf(idx, "Can't telnet until you have a password set.\r\n");
1188 putlog(LOG_MISC, "*", DCC_NOPASS, buf, dcc[idx].host);
1189 killsock(dcc[idx].sock);
1190 lostdcc(idx);
1191 return;
1192 }
1193 ok = 0;
1194 dcc[idx].type = &DCC_CHAT_PASS;
1195 dcc[idx].timeval = now;
1196 if (glob_botmast(fr))
1197 ok = 1;
1198 else if (chan_op(fr)) {
1199 if (!require_p)
1200 ok = 1;
1201 else if (glob_party(fr))
1202 ok = 1;
1203 } else if (glob_party(fr)) {
1204 ok = 1;
1205 dcc[idx].status |= STAT_PARTY;
1206 }
1207 if (glob_bot(fr))
1208 ok = 1;
1209 if (!ok) {
1210 struct chat_info *ci;
1211
1212 ci = dcc[idx].u.chat;
1213 dcc[idx].u.file = get_data_ptr(sizeof(struct file_info));
1214
1215 dcc[idx].u.file->chat = ci;
1216 }
1217 correct_handle(buf);
1218 strcpy(dcc[idx].nick, buf);
1219 if (glob_bot(fr))
1220 dprintf(idx, "passreq\n");
1221 else {
1222 dprintf(idx, "\nEnter your password.\377\373\001\n");
1223 /* turn off remote telnet echo: IAC WILL ECHO */
1224 }
1225 }
1226
1227 static void eof_dcc_telnet_id(int idx)
1228 {
1229 putlog(LOG_MISC, "*", DCC_LOSTCON, dcc[idx].host,
1230 dcc[idx].port);
1231 killsock(dcc[idx].sock);
1232 lostdcc(idx);
1233 }
1234
1235 static void timeout_dcc_telnet_id(int idx)
1236 {
1237 dprintf(idx, "Timeout.\n");
1238 putlog(LOG_MISC, "*", DCC_TTIMEOUT, dcc[idx].host);
1239 killsock(dcc[idx].sock);
1240 lostdcc(idx);
1241 }
1242
1243 static void display_dcc_telnet_id(int idx, char *buf)
1244 {
1245 sprintf(buf, "t-in waited %lus", now - dcc[idx].timeval);
1246 }
1247
1248 struct dcc_table DCC_TELNET_ID =
1249 {
1250 "TELNET_ID",
1251 0,
1252 eof_dcc_telnet_id,
1253 dcc_telnet_id,
1254 &password_timeout,
1255 timeout_dcc_telnet_id,
1256 display_dcc_telnet_id,
1257 expmem_dcc_general,
1258 kill_dcc_general,
1259 out_dcc_general
1260 };
1261
1262 static void dcc_telnet_new(int idx, char *buf, int x)
1263 {
1264 int ok = 1;
1265 char work[1024], *p, *q, *r;
1266
1267 buf[HANDLEN] = 0;
1268 strip_telnet(dcc[idx].sock, buf, &x);
1269 strcpy(dcc[idx].nick, buf);
1270 dcc[idx].timeval = now;
1271 for (x = 0; x < strlen(buf); x++)
1272 if ((buf[x] <= 32) || (buf[x] >= 127))
1273 ok = 0;
1274 if (!ok) {
1275 dprintf(idx, "\nYou can't use weird symbols in your nick.\n");
1276 dprintf(idx, "Try another one please:\n");
1277 } else if (strchr("-,+*=:!.@#;$", buf[0]) != NULL) {
1278 dprintf(idx, "\nYou can't start your nick with the character '%c'\n", buf[0]);
1279 dprintf(idx, "Try another one please:\n");
1280 } else if (get_user_by_handle(userlist, buf)) {
1281 dprintf(idx, "\nSorry, that nickname is taken already.\n");
1282 dprintf(idx, "Try another one please:\n");
1283 return;
1284 } else if (!strcasecmp(buf, origbotname) || !strcasecmp(buf, botnetnick)) {
1285 dprintf(idx, "Sorry, can't use my name for a nick.\n");
1286 } else {
1287 if (make_userfile)
1288 userlist = adduser(userlist, buf, "telnet!*@*", "-",
1289 sanity_check(default_flags | USER_PARTY |
1290 USER_MASTER | USER_OWNER));
1291 else {
1292 p = strchr(dcc[idx].host, '@');
1293 if (p) {
1294 q = p;
1295 *q = 0;
1296 p++;
1297 r = strchr(p, '.');
1298 if (!r)
1299 simple_sprintf(work, "telnet!%s@%s", dcc[idx].host, p);
1300 else
1301 simple_sprintf(work, "telnet!%s@*%s", dcc[idx].host, r);
1302 *q = '@';
1303 } else
1304 simple_sprintf(work, "telnet!*@*%s", dcc[idx].host);
1305 userlist = adduser(userlist, buf, work, "-",
1306 sanity_check(USER_PARTY | default_flags));
1307 }
1308 reaffirm_owners();
1309 dcc[idx].status = STAT_ECHO | STAT_TELNET;
1310 dcc[idx].type = &DCC_CHAT; /* just so next line will work */
1311 dcc[idx].user = get_user_by_handle(userlist, buf);
1312 check_dcc_attrs(dcc[idx].user, USER_PARTY | default_flags);
1313 dcc[idx].type = &DCC_TELNET_PW;
1314 if (make_userfile) {
1315 dprintf(idx, "\nYOU ARE THE MASTER/OWNER ON THIS BOT NOW\n");
1316 dprintf(idx, IRC_LIMBO);
1317 putlog(LOG_MISC, "*", DCC_INSTCOMPL,
1318 buf);
1319 make_userfile = 0;
1320 write_userfile(-1);
1321 add_note(buf, botnetnick, "Welcome to eggdrop! :)", -1, 0);
1322 }
1323 dprintf(idx, "\nOkay, now choose and enter a password:\n");
1324 dprintf(idx, "(Only the first 15 letters are significant.)\n");
1325 }
1326 }
1327
1328 static void dcc_telnet_pw(int idx, char *buf, int x)
1329 {
1330 char *newpass;
1331 int ok;
1332
1333 strip_telnet(dcc[idx].sock, buf, &x);
1334 buf[16] = 0;
1335 ok = 1;
1336 if (strlen(buf) < 4) {
1337 dprintf(idx, "\nTry to use at least 4 characters in your password.\n");
1338 dprintf(idx, "Choose and enter a password:\n");
1339 return;
1340 }
1341 for (x = 0; x < strlen(buf); x++)
1342 if ((buf[x] <= 32) || (buf[x] == 127))
1343 ok = 0;
1344 if (!ok) {
1345 dprintf(idx, "\nYou can't use weird symbols in your password.\n");
1346 dprintf(idx, "Try another one please:\n");
1347 return;
1348 }
1349 putlog(LOG_MISC, "*", DCC_NEWUSER, dcc[idx].nick,
1350 dcc[idx].host, dcc[idx].port);
1351 if (notify_new[0]) {
1352 char s[121], s1[121], s2[121];
1353
1354 sprintf(s, "Introduced to %s, %s", dcc[idx].nick, dcc[idx].host);
1355 strcpy(s1, notify_new);
1356 splitc(s2, s1, ',');
1357 while (s2[0]) {
1358 rmspace(s2);
1359 add_note(s2, botnetnick, s, -1, 0);
1360 splitc(s2, s1, ',');
1361 }
1362 rmspace(s1);
1363 add_note(s1, botnetnick, s, -1, 0);
1364 }
1365 newpass = newsplit(&buf);
1366 set_user(&USERENTRY_PASS, dcc[idx].user, newpass);
1367 dprintf(idx, "\nRemember that! You'll need it next time you log in.\n");
1368 dprintf(idx, "You now have an account on %s...\n\n\n", botnetnick);
1369 dcc[idx].type = &DCC_CHAT;
1370 dcc[idx].u.chat->channel = -2;
1371 dcc_chatter(idx);
1372 }
1373
1374 static void eof_dcc_telnet_new(int idx)
1375 {
1376 putlog(LOG_MISC, "*", DCC_LOSTNEWUSER, dcc[idx].host,
1377 dcc[idx].port);
1378 killsock(dcc[idx].sock);
1379 lostdcc(idx);
1380 }
1381
1382 static void eof_dcc_telnet_pw(int idx)
1383 {
1384 putlog(LOG_MISC, "*", DCC_LOSTNEWUSR2, dcc[idx].nick,
1385 dcc[idx].host, dcc[idx].port);
1386 deluser(dcc[idx].nick);
1387 killsock(dcc[idx].sock);
1388 lostdcc(idx);
1389 }
1390
1391 static void tout_dcc_telnet_new(int idx)
1392 {
1393 dprintf(idx, "Guess you're not there. Bye.\n");
1394 putlog(LOG_MISC, "*", DCC_TIMEOUTUSER, dcc[idx].host,
1395 dcc[idx].port);
1396 killsock(dcc[idx].sock);
1397 lostdcc(idx);
1398 }
1399
1400 static void tout_dcc_telnet_pw(int idx)
1401 {
1402 dprintf(idx, "Guess you're not there. Bye.\n");
1403 putlog(LOG_MISC, "*", DCC_TIMEOUTUSR2,
1404 dcc[idx].nick, dcc[idx].host, dcc[idx].port);
1405 killsock(dcc[idx].sock);
1406 lostdcc(idx);
1407 }
1408
1409 static void display_dcc_telnet_new(int idx, char *buf)
1410 {
1411 sprintf(buf, "new waited %lus", now - dcc[idx].timeval);
1412 }
1413
1414 static void display_dcc_telnet_pw(int idx, char *buf)
1415 {
1416 sprintf(buf, "newp waited %lus", now - dcc[idx].timeval);
1417 }
1418
1419 struct dcc_table DCC_TELNET_NEW =
1420 {
1421 "TELNET_NEW",
1422 0,
1423 eof_dcc_telnet_new,
1424 dcc_telnet_new,
1425 &password_timeout,
1426 tout_dcc_telnet_new,
1427 display_dcc_telnet_new,
1428 expmem_dcc_general,
1429 kill_dcc_general,
1430 out_dcc_general
1431 };
1432
1433 struct dcc_table DCC_TELNET_PW =
1434 {
1435 "TELNET_PW",
1436 0,
1437 eof_dcc_telnet_pw,
1438 dcc_telnet_pw,
1439 &password_timeout,
1440 tout_dcc_telnet_pw,
1441 display_dcc_telnet_pw,
1442 expmem_dcc_general,
1443 kill_dcc_general,
1444 out_dcc_general
1445 };
1446
1447 static int call_tcl_func(char *name, int idx, char *args)
1448 {
1449 char s[11];
1450
1451 set_tcl_vars();
1452 sprintf(s, "%d", idx);
1453 Tcl_SetVar(interp, "_n", s, 0);
1454 Tcl_SetVar(interp, "_a", args, 0);
1455 if (Tcl_VarEval(interp, name, " $_n $_a", NULL) == TCL_ERROR) {
1456 putlog(LOG_MISC, "*", DCC_TCLERROR, name, interp->result);
1457 return -1;
1458 }
1459 return (atoi(interp->result));
1460 }
1461
1462 static void dcc_script(int idx, char *buf, int len)
1463 {
1464 void *old = NULL;
1465 long oldsock = dcc[idx].sock;
1466
1467 strip_telnet(dcc[idx].sock, buf, &len);
1468 if (!len)
1469 return;
1470 dcc[idx].timeval = now;
1471 set_tcl_vars();
1472 if (call_tcl_func(dcc[idx].u.script->command, dcc[idx].sock, buf)) {
1473 context;
1474 if ((dcc[idx].sock != oldsock) || (idx>max_dcc))
1475 return; /* drummer: this happen after killdcc */
1476 old = dcc[idx].u.script->u.other;
1477 dcc[idx].type = dcc[idx].u.script->type;
1478 nfree(dcc[idx].u.script);
1479 dcc[idx].u.other = old;
1480 if (dcc[idx].type == &DCC_SOCKET) {
1481 /* kill the whole thing off */
1482 killsock(dcc[idx].sock);
1483 lostdcc(idx);
1484 return;
1485 }
1486 if (dcc[idx].type == &DCC_CHAT) {
1487 if (dcc[idx].u.chat->channel >= 0) {
1488 chanout_but(-1, dcc[idx].u.chat->channel,DCC_JOIN, dcc[idx].nick);
1489 context;
1490 if (dcc[idx].u.chat->channel < 10000)
1491 botnet_send_join_idx(idx, -1);
1492 check_tcl_chjn(botnetnick, dcc[idx].nick, dcc[idx].u.chat->channel,
1493 geticon(idx), dcc[idx].sock, dcc[idx].host);
1494 }
1495 check_tcl_chon(dcc[idx].nick, dcc[idx].sock);
1496 }
1497 }
1498 }
1499
1500 static void eof_dcc_script(int idx)
1501 {
1502 void *old;
1503 int oldflags;
1504
1505 context;
1506 /* This will stop a killdcc from working, incase the script tries
1507 * to kill it's controlling socket while handling an EOF <cybah> */
1508 oldflags = dcc[idx].type->flags;
1509 dcc[idx].type->flags &= ~(DCT_VALIDIDX);
1510 /* tell the script they're gone: */
1511 call_tcl_func(dcc[idx].u.script->command, dcc[idx].sock, "");
1512 /* restore the flags */
1513 dcc[idx].type->flags = oldflags;
1514 context;
1515 old = dcc[idx].u.script->u.other;
1516 dcc[idx].type = dcc[idx].u.script->type;
1517 nfree(dcc[idx].u.script);
1518 dcc[idx].u.other = old;
1519 /* then let it fall thru to the real one */
1520 if (dcc[idx].type && dcc[idx].type->eof)
1521 dcc[idx].type->eof(idx);
1522 else {
1523 putlog(LOG_MISC, "*",
1524 DCC_DEADSOCKET,
1525 dcc[idx].sock, dcc[idx].type->name);
1526 killsock(dcc[idx].sock);
1527 lostdcc(idx);
1528 }
1529 }
1530
1531 static void display_dcc_script(int idx, char *buf)
1532 {
1533 sprintf(buf, "scri %s", dcc[idx].u.script->command);
1534 }
1535
1536 static int expmem_dcc_script(void *x)
1537 {
1538 register struct script_info *p = (struct script_info *) x;
1539 int tot = sizeof(struct script_info);
1540
1541 if (p->type && p->u.other)
1542 tot += p->type->expmem(p->u.other);
1543 return tot;
1544 }
1545
1546 static void kill_dcc_script(int idx, void *x)
1547 {
1548 register struct script_info *p = (struct script_info *) x;
1549
1550 if (p->type && p->u.other)
1551 p->type->kill(idx, p->u.other);
1552 nfree(p);
1553 }
1554
1555 static void out_dcc_script(int idx, char *buf, void *x)
1556 {
1557 register struct script_info *p = (struct script_info *) x;
1558
1559 if (p && p->type && p->u.other)
1560 p->type->output(idx, buf, p->u.other);
1561 else
1562 tputs(dcc[idx].sock, buf, strlen(buf));
1563 }
1564
1565 struct dcc_table DCC_SCRIPT =
1566 {
1567 "SCRIPT",
1568 DCT_VALIDIDX,
1569 eof_dcc_script,
1570 dcc_script,
1571 0,
1572 0,
1573 display_dcc_script,
1574 expmem_dcc_script,
1575 kill_dcc_script,
1576 out_dcc_script
1577 };
1578
1579 static void dcc_socket(int idx, char *buf, int len)
1580 {
1581 }
1582
1583 static void eof_dcc_socket(int idx)
1584 {
1585 killsock(dcc[idx].sock);
1586 lostdcc(idx);
1587 }
1588
1589 static void display_dcc_socket(int idx, char *buf)
1590 {
1591 strcpy(buf, "sock (stranded)");
1592 }
1593
1594 struct dcc_table DCC_SOCKET =
1595 {
1596 "SOCKET",
1597 DCT_VALIDIDX,
1598 eof_dcc_socket,
1599 dcc_socket,
1600 0,
1601 0,
1602 display_dcc_socket,
1603 0,
1604 0,
1605 0
1606 };
1607
1608 static void display_dcc_lost(int idx, char *buf)
1609 {
1610 strcpy(buf, "lost");
1611 }
1612
1613 struct dcc_table DCC_LOST =
1614 {
1615 "LOST",
1616 0,
1617 0,
1618 dcc_socket,
1619 0,
1620 0,
1621 display_dcc_lost,
1622 0,
1623 0,
1624 0
1625 };
1626
1627 void dcc_identwait(int idx, char *buf, int len)
1628 {
1629 /* ignore anything now */
1630 context;
1631 }
1632
1633 void eof_dcc_identwait(int idx)
1634 {
1635 int i;
1636
1637 putlog(LOG_MISC, "*", DCC_LOSTCONN,
1638 dcc[idx].host, dcc[idx].port);
1639 for (i = 0; i < dcc_total; i++)
1640 if ((dcc[i].type == &DCC_IDENT) &&
1641 (dcc[i].u.ident_sock == dcc[idx].sock)) {
1642 dcc[i].u.other = 0;
1643 killsock(dcc[i].sock); /* cleanup ident socket */
1644 }
1645 killsock(dcc[idx].sock); /* cleanup waiting socket */
1646 dcc[idx].u.other = 0;
1647 lostdcc(idx);
1648 }
1649
1650 static void display_dcc_identwait(int idx, char *buf)
1651 {
1652 sprintf(buf, "idtw waited %lus", now - dcc[idx].timeval);
1653 }
1654
1655 struct dcc_table DCC_IDENTWAIT =
1656 {
1657 "IDENTWAIT",
1658 0,
1659 eof_dcc_identwait,
1660 dcc_identwait,
1661 0,
1662 0,
1663 display_dcc_identwait,
1664 0,
1665 0,
1666 0
1667 };
1668
1669 void dcc_ident(int idx, char *buf, int len)
1670 {
1671 char response[512], uid[512], buf1[UHOSTLEN];
1672 int i, sock = dcc[idx].sock;
1673
1674 context;
1675 sscanf(buf, "%*[^:]:%[^:]:%*[^:]:%[^\n]\n", response, uid);
1676 rmspace(response);
1677 if (response[0] != 'U') {
1678 dcc[idx].timeval = now;
1679 return;
1680 }
1681 rmspace(uid);
1682 uid[20] = 0; /* 20 character ident max */
1683 for (i = 0; i < dcc_total; i++)
1684 if ((dcc[i].type == &DCC_IDENTWAIT) &&
1685 (dcc[i].sock == dcc[idx].u.ident_sock)) {
1686 simple_sprintf(buf1, "%s@%s", uid, dcc[idx].host);
1687 dcc_telnet_got_ident(i, buf1);
1688 }
1689 idx = findanyidx(sock);
1690 dcc[idx].u.other = 0;
1691 killsock(dcc[idx].sock);
1692 lostdcc(idx);
1693 }
1694
1695 void eof_dcc_ident(int idx)
1696 {
1697 char buf[UHOSTLEN];
1698 int i, sock = dcc[idx].sock;
1699
1700 for (i = 0; i < dcc_total; i++)
1701 if ((dcc[i].type == &DCC_IDENTWAIT) &&
1702 (dcc[i].sock == dcc[idx].u.ident_sock)) {
1703 putlog(LOG_MISC, "*", DCC_EOFIDENT);
1704 simple_sprintf(buf, "telnet@%s", dcc[idx].host);
1705 dcc_telnet_got_ident(i, buf);
1706 }
1707 idx = findanyidx(sock); /* sanity */
1708 killsock(dcc[idx].sock);
1709 dcc[idx].u.other = 0;
1710 lostdcc(idx);
1711 }
1712
1713 static void display_dcc_ident(int idx, char *buf)
1714 {
1715 sprintf(buf, "idnt (sock %d)", dcc[idx].u.ident_sock);
1716 }
1717
1718 struct dcc_table DCC_IDENT =
1719 {
1720 "IDENT",
1721 0,
1722 eof_dcc_ident,
1723 dcc_ident,
1724 &identtimeout,
1725 eof_dcc_ident,
1726 display_dcc_ident,
1727 0,
1728 0,
1729 0
1730 };
1731
1732 void dcc_telnet_got_ident(int i, char *host)
1733 {
1734 int idx;
1735 char x[1024];
1736
1737 for (idx = 0; idx < dcc_total; idx++)
1738 if ((dcc[idx].type == &DCC_TELNET) &&
1739 (dcc[idx].sock == dcc[i].u.ident_sock))
1740 break;
1741 dcc[i].u.other = 0;
1742 if (dcc_total == idx)
1743 putlog(LOG_MISC, "*", DCC_LOSTIDENT);
1744 strncpy(dcc[i].host, host, UHOSTLEN);
1745 dcc[i].host[UHOSTLEN] = 0;
1746 simple_sprintf(x, "telnet!%s", dcc[i].host);
1747 if (protect_telnet && !make_userfile) {
1748 struct userrec *u;
1749 int ok = 1;
1750
1751 context;
1752 u = get_user_by_host(x);
1753 /* not a user or +p & require p OR +o */
1754 if (!u)
1755 ok = 0;
1756 else if (require_p && !(u->flags & USER_PARTY))
1757 ok = 0;
1758 else if (!require_p && !(u->flags & USER_OP))
1759 ok = 0;
1760 if (!ok && u && (u->flags & USER_BOT))
1761 ok = 1;
1762 if (!ok) {
1763 putlog(LOG_MISC, "*", DCC_NOACCESS, dcc[i].host);
1764 killsock(dcc[i].sock);
1765 lostdcc(i);
1766 return;
1767 }
1768 }
1769 context;
1770 if (match_ignore(x)) {
1771 killsock(dcc[i].sock);
1772 lostdcc(i);
1773 return;
1774 }
1775 /* script? */
1776 if (!strcmp(dcc[idx].nick, "(script)")) {
1777 dcc[i].type = &DCC_SOCKET;
1778 dcc[i].u.other = NULL;
1779 strcpy(dcc[i].nick, "*");
1780 check_tcl_listen(dcc[idx].host, dcc[i].sock);
1781 return;
1782 }
1783 dcc[i].type = &DCC_TELNET_ID;
1784 dcc[i].u.chat = get_data_ptr(sizeof(struct chat_info));
1785 bzero(dcc[i].u.chat, sizeof(struct chat_info));
1786
1787 /* copy acceptable-nick/host mask */
1788 dcc[i].status = STAT_TELNET | STAT_ECHO;
1789 if (!strcmp(dcc[idx].nick, "(bots)"))
1790 dcc[i].status |= STAT_BOTONLY;
1791 if (!strcmp(dcc[idx].nick, "(users)"))
1792 dcc[i].status |= STAT_USRONLY;
1793 /* copy acceptable-nick/host mask */
1794 strncpy(dcc[i].nick, dcc[idx].host, HANDLEN);
1795 dcc[i].nick[HANDLEN] = 0;
1796 dcc[i].timeval = now;
1797 strcpy(dcc[i].u.chat->con_chan, chanset ? chanset->name : "*");
1798 /* Displays a customizable banner. [seC] */
1799 if (use_telnet_banner)
1800 show_banner(i);
1801 /* This is so we dont tell someone doing a portscan anything
1802 * about ourselves. <cybah> */
1803 if (stealth_telnets)
1804 sub_lang(i, MISC_BANNER_STEALTH);
1805 else {
1806 dprintf(i, "\r\n\r\n");
1807 sub_lang(i, MISC_BANNER);
1808 }
1809 if (allow_new_telnets)
1810 dprintf(i, "(If you are new, enter 'NEW' here.)\r\n");
1811 }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23