/[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.68 - (show annotations) (download) (as text)
Wed Jan 16 22:09:43 2002 UTC (17 years, 10 months ago) by ite
Branch: MAIN
Changes since 1.67: +2 -2 lines
File MIME type: text/x-chdr
Removed our malloc_strcpy macro sincw it had the same functionality of strdup (provided the respective fallback function)

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23