/[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.27 - (show annotations) (download) (as text)
Fri Jul 14 22:26:57 2000 UTC (19 years ago) by guppy
Branch: MAIN
CVS Tags: eggdrop10404, HEAD
Changes since 1.26: +9 -9 lines
File MIME type: text/x-chdr
almost ready for 1.4.4

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23