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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23