/[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.12 - (show annotations) (download) (as text)
Thu Oct 7 23:12:02 1999 UTC (19 years, 11 months ago) by guppy
Branch: MAIN
Changes since 1.11: +15 -9 lines
File MIME type: text/x-chdr
more patches for today

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23