/[cvs]/eggdrop1.8/src/dcc.c
ViewVC logotype

Contents of /eggdrop1.8/src/dcc.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.1.1.1 - (show annotations) (download) (as text) (vendor branch)
Mon Jul 26 21:11:06 2010 UTC (8 years, 9 months ago) by simple
Branch: eggheads
CVS Tags: v1
Changes since 1.1: +0 -0 lines
File MIME type: text/x-chdr
Imported Eggdrop 1.6.20

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23