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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23