/[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.4 - (show annotations) (download) (as text)
Tue Oct 19 12:13:33 2010 UTC (8 years, 8 months ago) by pseudo
Branch: MAIN
Changes since 1.3: +133 -19 lines
File MIME type: text/x-chdr
Added full SSL support including Tcl commands.
Added support for certificate authentication.
Added support for botnet and partyline encryption using ssl.
Documented the new features and commands.
Fixed add_server() problems with IPv6 addresses in the server list.

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23