/[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.6.2.6 - (show annotations) (download) (as text)
Fri Jun 22 21:42:00 2012 UTC (7 years, 3 months ago) by thommey
Branch: gettext
Changes since 1.6.2.5: +7 -1 lines
File MIME type: text/x-chdr
new stripcode flag "o" for mirc ctrl+o and * for everything

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