/[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.8 - (show annotations) (download) (as text)
Fri Nov 26 13:20:29 2010 UTC (9 years, 7 months ago) by pseudo
Branch: MAIN
Changes since 1.7: +30 -27 lines
File MIME type: text/x-chdr
Added a little hack to send starttls before password exchange during the initial handshake.

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