/[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.61 - (show annotations) (download) (as text)
Sat Oct 20 21:57:15 2001 UTC (18 years, 1 month ago) by stdarg
Branch: MAIN
Changes since 1.60: +6 -2 lines
File MIME type: text/x-chdr
* Added Oskar Liljeblad's patch to convert H_chat, H_act, and H_bcst.
* Experimented with changing around the chat bind so it's called before text is sent, and is breakable.

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23