/[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.46 - (show annotations) (download) (as text)
Fri Jun 29 05:09:58 2001 UTC (18 years, 4 months ago) by guppy
Branch: MAIN
Changes since 1.45: +2 -2 lines
File MIME type: text/x-chdr
One small patch coming up ... I even created this problem I believe .. silly guppy, mistakes are for lusers

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23