/[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.21 - (show annotations) (download) (as text)
Wed Dec 22 20:30:03 1999 UTC (19 years, 11 months ago) by guppy
Branch: MAIN
Changes since 1.20: +6 -11 lines
File MIME type: text/x-chdr
patches .. and more patches

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23