/[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.76 - (show annotations) (download) (as text)
Mon Apr 1 13:33:33 2002 UTC (17 years, 7 months ago) by ite
Branch: MAIN
Changes since 1.75: +5 -5 lines
File MIME type: text/x-chdr
* Got rid of strncpyz() in favour of BSD's strlcpy(). Fallback function provided.
* BSD's strlcat() provided as fallback function.
* Fallback functions weren't linked as expected when needed.

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23