/[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.7 - (show annotations) (download) (as text)
Tue Nov 23 16:36:23 2010 UTC (10 years, 11 months ago) by pseudo
Branch: MAIN
Changes since 1.6: +52 -19 lines
File MIME type: text/x-chdr
Fixed a problem with sharing causing starttls to fail.
Moved STARTTLS early in the bot link process and synchronized the handshake.
Made it possible for ssl handshakes to complete even without data to be sent on the channel.
Fixed an ancient bug resulting in sending uninitialized strings when sharing bot addresses.
Enabled userfile sending over ssl.

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23