/[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.1 - (show annotations) (download) (as text)
Wed Nov 10 13:39:19 2010 UTC (8 years, 8 months ago) by pseudo
Branch: gettext
Changes since 1.6: +146 -119 lines
File MIME type: text/x-chdr
Converted remaining lang #defines in the core to english strings from core.english.lang. Gettextified most of the hardcoded strings.

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23