/[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.5 - (show annotations) (download) (as text)
Wed Oct 20 13:07:13 2010 UTC (8 years, 9 months ago) by pseudo
Branch: MAIN
Changes since 1.4: +2 -6 lines
File MIME type: text/x-chdr
Clarified the OpenSSL version requirements.
Rewrote open_telnet() to make it more useful.
Replaced some calls to open_telnet_raw() with open_telnet().

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23