/[cvs]/eggdrop1.9/src/dcc.c
ViewVC logotype

Contents of /eggdrop1.9/src/dcc.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.35 - (show annotations) (download) (as text)
Mon Sep 18 20:04:57 2000 UTC (19 years, 2 months ago) by fabian
Branch: MAIN
Changes since 1.34: +2 -2 lines
File MIME type: text/x-chdr
fabian: applied guppy's lang_args patch

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23