/[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.1.1.1 - (show annotations) (download) (as text) (vendor branch)
Wed Jun 23 19:51:28 1999 UTC (20 years, 5 months ago) by segfault
Branch: eggdev
CVS Tags: start
Changes since 1.1: +0 -0 lines
File MIME type: text/x-chdr
Eggdrop 1.3.28 CVS Code

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23