/[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.100 - (show annotations) (download) (as text)
Tue Feb 25 10:28:22 2003 UTC (16 years, 9 months ago) by stdarg
Branch: MAIN
CVS Tags: HEAD
Changes since 1.99: +1 -1 lines
File MIME type: text/x-chdr
FILE REMOVED
* Cleanups

1 /*
2 * dcc.c --
3 *
4 * activity on a dcc socket
5 * disconnect on a dcc socket
6 * ...and that's it! (but it's a LOT)
7 */
8 /*
9 * Copyright (C) 1997 Robey Pointer
10 * Copyright (C) 1999, 2000, 2001, 2002, 2003 Eggheads Development Team
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 */
26
27 #ifndef lint
28 static const char rcsid[] = "$Id: dcc.c,v 1.99 2003/02/25 06:52:19 stdarg Exp $";
29 #endif
30
31 #include "main.h"
32 #include <ctype.h>
33 #include <errno.h>
34 #include "modules.h"
35 #include "logfile.h"
36 #include "dns.h"
37 #include "misc.h"
38 #include "cmdt.h" /* cmd_t */
39 #include "users.h" /* match_ignore, addignore, get_user_by_host */
40 //#include "chanprog.h" /* reaffirm_owners */
41 //#include "cmds.h" /* check_dcc_attrs */
42 #include "dccutil.h" /* dprintf_eggdrop, lostdcc, chatout,
43 dcc_chatter, chanout_but, add_cr, not_away
44 not_away, flush_lines, new_dcc,
45 changeover_dcc, makepass */
46 #include "net.h" /* killsock, getsock, open_telnet_raw, tputs,
47 answer, neterror, sockoptions, open_telnet */
48 #include "userrec.h" /* u_pass_match, correct_handle, write_userfile,
49 deluser */
50 #include "dcc.h" /* prototypes */
51
52 extern struct userrec *userlist;
53 extern struct chanset_t *chanset;
54 extern time_t now;
55 extern int egg_numver, connect_timeout, conmask, backgrd, make_userfile,
56 default_flags, raw_log, ignore_time;
57 extern char myname[], ver[], origbotname[], notify_new[];
58
59 #ifndef MAKING_MODS
60 extern struct dcc_table DCC_CHAT, DCC_BOT, DCC_PRE_RELAY, DCC_FORK_RELAY,
61 DCC_RELAYING, DCC_DNSWAIT, DCC_FORK_BOT, DCC_BOT_NEW,
62 DCC_RELAY, DCC_IDENTWAIT, DCC_IDENT, DCC_SOCKET,
63 DCC_TELNET, DCC_TELNET_NEW, DCC_TELNET_PW;
64 #endif /* MAKING_MODS */
65
66
67 struct dcc_t *dcc = NULL; /* DCC list */
68 int dcc_total = 0; /* Total dcc's */
69 int max_dcc = 0; /* Max number of dcc's */
70 char tempdir[121] = ""; /* Temporary directory
71 (default: current directory) */
72 int learn_users = 0; /* Allow people to introduce themselves */
73 char network[41] = "unknown-net"; /* Name of the IRC network you're on */
74 int password_timeout = 180; /* Time to wait for a password from a user */
75 int bot_timeout = 60; /* Bot timeout value */
76 int ident_timeout = 5; /* Timeout value for ident lookups */
77 int dupwait_timeout = 5; /* Timeout for rejecting duplicate entries */
78 extern int resolve_timeout;
79 int protect_telnet = 1; /* Even bother with ident lookups :) */
80 int dcc_flood_thr = 3;
81 int flood_telnet_thr = 5; /* Number of telnet connections to be
82 considered a flood */
83 int flood_telnet_time = 60; /* In how many seconds? */
84 char bannerfile[121] = "text/banner"; /* File displayed on telnet login */
85
86 /* This var specifies the chars to recognize as commands characters for dcc
87 commands. Default value is "./" */
88 static char *dcc_command_chars = NULL;
89
90 static void dcc_telnet_hostresolved(int);
91 static void dcc_telnet_got_ident(int, char *);
92 static void dcc_telnet_pass(int, int);
93
94 /* Callback functions for linked variables. */
95 static int dcc_write_max_dcc(script_linked_var_t *linked_var, script_var_t *newvalue);
96
97
98 extern void init_dcc_max(int newmax);
99
100 static script_var_callbacks_t max_dcc_callback = {
101 NULL,
102 dcc_write_max_dcc,
103 NULL
104 };
105
106 static script_linked_var_t dcc_script_vars[] = {
107 {"", "dcc_command_chars", &dcc_command_chars, SCRIPT_STRING, NULL},
108 {"", "max_dcc", &max_dcc, SCRIPT_INTEGER, &max_dcc_callback},
109 {"", "dcc_flood_thr", &dcc_flood_thr, SCRIPT_INTEGER, NULL},
110 {"", "protect_telnet", &protect_telnet, SCRIPT_INTEGER, NULL},
111 {"", "connect_timeout", &connect_timeout, SCRIPT_INTEGER, NULL},
112 {"", "dupwait_timeout", &dupwait_timeout, SCRIPT_INTEGER, NULL},
113 {"", "ident_timeout", &ident_timeout, SCRIPT_INTEGER, NULL},
114 {"", "resolve_timeout", &resolve_timeout, SCRIPT_INTEGER, NULL},
115 {0}
116 };
117
118 void dcc_init()
119 {
120 dcc_command_chars = strdup("./");
121 script_link_vars(dcc_script_vars);
122 init_dcc_max(50);
123 }
124
125 static void strip_telnet(int sock, char *buf, int *len)
126 {
127 unsigned char *p = (unsigned char *) buf, *o = (unsigned char *) buf;
128 int mark;
129
130 while (*p != 0) {
131 while ((*p != TLN_IAC) && (*p != 0))
132 *o++ = *p++;
133 if (*p == TLN_IAC) {
134 p++;
135 mark = 2;
136 if (!*p)
137 mark = 1; /* bogus */
138 if ((*p >= TLN_WILL) && (*p <= TLN_DONT)) {
139 mark = 3;
140 if (!*(p + 1))
141 mark = 2; /* bogus */
142 }
143 if (*p == TLN_WILL) {
144 /* WILL X -> response: DONT X */
145 /* except WILL ECHO which we just smile and ignore */
146 if (*(p + 1) != TLN_ECHO) {
147 write(sock, TLN_IAC_C TLN_DONT_C, 2);
148 write(sock, p + 1, 1);
149 }
150 }
151 if (*p == TLN_DO) {
152 /* DO X -> response: WONT X */
153 /* except DO ECHO which we just smile and ignore */
154 if (*(p + 1) != TLN_ECHO) {
155 write(sock, TLN_IAC_C TLN_WONT_C, 2);
156 write(sock, p + 1, 1);
157 }
158 }
159 if (*p == TLN_AYT) {
160 /* "are you there?" */
161 /* response is: "hell yes!" */
162 write(sock, "\r\nHell, yes!\r\n", 14);
163 }
164 /* Anything else can probably be ignored */
165 p += mark - 1;
166 *len = *len - mark;
167 }
168 }
169 *o = *p;
170 }
171
172 static void dcc_chat_pass(int idx, char *buf, int atr)
173 {
174 if (!atr)
175 return;
176 strip_telnet(dcc[idx].sock, buf, &atr);
177 atr = dcc[idx].user ? dcc[idx].user->flags : 0;
178
179 if (u_pass_match(dcc[idx].user, buf)) {
180 /* Log entry for successful login -slennox 3/28/1999 */
181 putlog(LOG_MISC, "*", _("Logged in: %s (%s/%d)"), dcc[idx].nick,
182 dcc[idx].host, dcc[idx].port);
183 if (dcc[idx].u.chat->away)
184 free_null(dcc[idx].u.chat->away);
185 dcc[idx].type = &DCC_CHAT;
186 dcc[idx].status &= ~STAT_CHAT;
187 dcc[idx].u.chat->con_flags = (atr & USER_MASTER) ? conmask : 0;
188 dcc[idx].u.chat->channel = -2;
189 /* Turn echo back on for telnet sessions (send IAC WON'T ECHO). */
190 if (dcc[idx].status & STAT_TELNET)
191 dprintf(idx, TLN_IAC_C TLN_WONT_C TLN_ECHO_C "\n");
192 dcc_chatter(idx);
193 } else {
194 dprintf(idx, _("Negative on that, Houston.\n"));
195 putlog(LOG_MISC, "*", _("Bad Password: [%s]%s/%d"), dcc[idx].nick,
196 dcc[idx].host, dcc[idx].port);
197 if (dcc[idx].u.chat->away) { /* su from a dumb user */
198 /* Turn echo back on for telnet sessions (send IAC WON'T ECHO). */
199 if (dcc[idx].status & STAT_TELNET)
200 dprintf(idx, TLN_IAC_C TLN_WONT_C TLN_ECHO_C "\n");
201 dcc[idx].user = get_user_by_handle(userlist, dcc[idx].u.chat->away);
202 strcpy(dcc[idx].nick, dcc[idx].u.chat->away);
203 free_null(dcc[idx].u.chat->away);
204 free_null(dcc[idx].u.chat->su_nick);
205 dcc[idx].type = &DCC_CHAT;
206 if (dcc[idx].u.chat->channel < 100000)
207 chanout_but(-1, dcc[idx].u.chat->channel, _("*** %s has joined the party line.\n"), dcc[idx].nick);
208 } else {
209 killsock(dcc[idx].sock);
210 lostdcc(idx);
211 }
212 }
213 }
214
215 static void eof_dcc_general(int idx)
216 {
217 putlog(LOG_MISC, "*", _("Lost dcc connection to %s (%s/%d)"), dcc[idx].nick,
218 dcc[idx].host, dcc[idx].port);
219 killsock(dcc[idx].sock);
220 lostdcc(idx);
221 }
222
223 static void tout_dcc_chat_pass(int idx)
224 {
225 dprintf(idx, "Timeout.\n");
226 putlog(LOG_MISC, "*", _("Password timeout on dcc chat: [%s]%s"), dcc[idx].nick,
227 dcc[idx].host);
228 killsock(dcc[idx].sock);
229 lostdcc(idx);
230 }
231
232 static void display_dcc_chat_pass(int idx, char *buf)
233 {
234 sprintf(buf, "pass waited %lus", now - dcc[idx].timeval);
235 }
236
237 static void kill_dcc_general(int idx, void *x)
238 {
239 register struct chat_info *p = (struct chat_info *) x;
240
241 if (p) {
242 if (p->buffer) {
243 struct msgq *r, *q;
244
245 for (r = dcc[idx].u.chat->buffer; r; r = q) {
246 q = r->next;
247 free(r->msg);
248 free(r);
249 }
250 }
251 if (p->away) {
252 free(p->away);
253 }
254 free(p);
255 }
256 }
257
258 static void append_line(int idx, char *line)
259 {
260 int l = strlen(line);
261 struct msgq *p, *q;
262 struct chat_info *c = (dcc[idx].type == &DCC_CHAT) ? dcc[idx].u.chat :
263 dcc[idx].u.file->chat;
264
265 if (c->current_lines > 1000) {
266 /* They're probably trying to fill up the bot nuke the sods :) */
267 for (p = c->buffer; p; p = q) {
268 q = p->next;
269 free(p->msg);
270 free(p);
271 }
272 c->buffer = 0;
273 dcc[idx].status &= ~STAT_PAGE;
274 do_boot(idx, myname, "too many pages - senq full");
275 return;
276 }
277 if ((c->line_count < c->max_line) && (c->buffer == NULL)) {
278 c->line_count++;
279 tputs(dcc[idx].sock, line, l);
280 } else {
281 c->current_lines++;
282 if (c->buffer == NULL)
283 q = NULL;
284 else
285 for (q = c->buffer; q->next; q = q->next);
286
287 p = calloc(1, sizeof(struct msgq));
288 p->len = l;
289 p->msg = calloc(1, l + 1);
290 p->next = NULL;
291 strcpy(p->msg, line);
292 if (q == NULL)
293 c->buffer = p;
294 else
295 q->next = p;
296 }
297 }
298
299 static void out_dcc_general(int idx, char *buf, void *x)
300 {
301 char *y = buf;
302
303 if (dcc[idx].status & STAT_TELNET)
304 y = add_cr(buf);
305 if (dcc[idx].status & STAT_PAGE)
306 append_line(idx, y);
307 else
308 tputs(dcc[idx].sock, y, strlen(y));
309 }
310
311 struct dcc_table DCC_CHAT_PASS =
312 {
313 "CHAT_PASS",
314 0,
315 eof_dcc_general,
316 dcc_chat_pass,
317 &password_timeout,
318 tout_dcc_chat_pass,
319 display_dcc_chat_pass,
320 kill_dcc_general,
321 out_dcc_general
322 };
323
324 /* Make sure ansi code is just for color-changing
325 */
326 static int check_ansi(char *v)
327 {
328 int count = 2;
329
330 if (*v++ != '\033')
331 return 1;
332 if (*v++ != '[')
333 return 1;
334 while (*v) {
335 if (*v == 'm')
336 return 0;
337 if ((*v != ';') && ((*v < '0') || (*v > '9')))
338 return count;
339 v++;
340 count++;
341 }
342 return count;
343 }
344
345 static void eof_dcc_chat(int idx)
346 {
347 putlog(LOG_MISC, "*", _("Lost dcc connection to %s (%s/%d)"), dcc[idx].nick,
348 dcc[idx].host, dcc[idx].port);
349 if (dcc[idx].u.chat->channel >= 0) {
350 chanout_but(idx, dcc[idx].u.chat->channel, "*** %s lost dcc link.\n",
351 dcc[idx].nick);
352 }
353 killsock(dcc[idx].sock);
354 lostdcc(idx);
355 }
356
357 static void dcc_chat(int idx, char *buf, int i)
358 {
359 int nathan = 0, doron = 0, fixed = 0;
360 int iscommand;
361 char *v, *d;
362
363 strip_telnet(dcc[idx].sock, buf, &i);
364 if (!buf[0]) return;
365 iscommand = (strchr(dcc_command_chars, buf[0]) != NULL);
366
367 /* If it's not a command, check for a flood, and abort if it is a flood. */
368 if (!iscommand && detect_dcc_flood(&dcc[idx].timeval, dcc[idx].u.chat, idx)) return;
369
370 dcc[idx].timeval = now;
371
372 /* Check for beeps and cancel annoying ones */
373 v = buf;
374 d = buf;
375 while (*v)
376 switch (*v) {
377 case 7: /* Beep - no more than 3 */
378 nathan++;
379 if (nathan > 3)
380 v++;
381 else
382 *d++ = *v++;
383 break;
384 case 8: /* Backspace - for lame telnet's :) */
385 if (d > buf) {
386 d--;
387 }
388 v++;
389 break;
390 case 27: /* ESC - ansi code? */
391 doron = check_ansi(v);
392 /* If it's valid, append a return-to-normal code at the end */
393 if (!doron) {
394 *d++ = *v++;
395 fixed = 1;
396 } else
397 v += doron;
398 break;
399 case '\r': /* Weird pseudo-linefeed */
400 v++;
401 break;
402 default:
403 *d++ = *v++;
404 }
405 if (fixed)
406 strcpy(d, "\033[0m");
407 else
408 *d = 0;
409
410 if (iscommand || (dcc[idx].u.chat->channel < 0)) {
411 if (iscommand) buf++;
412 v = newsplit(&buf);
413 rmspace(buf);
414 //check_bind_dcc(v, idx, buf);
415 }
416 else if (buf[0] == ',') {
417 int me = 0;
418
419 if ((buf[1] == 'm') && (buf[2] == 'e') && buf[3] == ' ')
420 me = 1;
421 for (i = 0; i < dcc_total; i++) {
422 struct userrec *u;
423
424 if (!dcc[i].type) continue;
425
426 if (!(dcc[i].type->flags & DCT_MASTER) ||
427 (dcc[i].type != &DCC_CHAT) ||
428 (dcc[i].u.chat->channel < 0) ||
429 (i == idx && dcc[idx].status != STAT_ECHO)) continue;
430
431 u = get_user_by_handle(userlist, dcc[i].nick);
432
433 if (u && (u->flags & USER_MASTER)) {
434 if (me) dprintf(i, "-> %s%s\n", dcc[idx].nick, buf + 3);
435 else dprintf(i, "-%s-> %s\n", dcc[idx].nick, buf + 1);
436 }
437 }
438 }
439 else if (buf[0] == '\'') {
440 int me = 0;
441
442 if ((buf[1] == 'm') && (buf[2] == 'e') &&
443 ((buf[3] == ' ') || (buf[3] == '\'') || (buf[3] == ',')))
444 me = 1;
445 for (i = 0; i < dcc_total; i++) {
446 if (dcc[i].type && dcc[i].type->flags & DCT_CHAT) {
447 if (me)
448 dprintf(i, "=> %s%s\n", dcc[idx].nick, buf + 3);
449 else
450 dprintf(i, "=%s=> %s\n", dcc[idx].nick, buf + 1);
451 }
452 }
453 } else {
454 int r = 0;
455
456 if (r & BIND_RET_BREAK) return;
457
458 if (dcc[idx].u.chat->away != NULL)
459 not_away(idx);
460 if (dcc[idx].status & STAT_ECHO)
461 chanout_but(-1, dcc[idx].u.chat->channel,
462 "<%s> %s\n", dcc[idx].nick, buf);
463 else
464 chanout_but(idx, dcc[idx].u.chat->channel, "<%s> %s\n",
465 dcc[idx].nick, buf);
466 }
467 if (dcc[idx].type == &DCC_CHAT) /* Could have change to files */
468 if (dcc[idx].status & STAT_PAGE)
469 flush_lines(idx, dcc[idx].u.chat);
470 }
471
472 static void display_dcc_chat(int idx, char *buf)
473 {
474 int i = simple_sprintf(buf, "chat flags: ");
475
476 buf[i++] = dcc[idx].status & STAT_CHAT ? 'C' : 'c';
477 buf[i++] = dcc[idx].status & STAT_PARTY ? 'P' : 'p';
478 buf[i++] = dcc[idx].status & STAT_TELNET ? 'T' : 't';
479 buf[i++] = dcc[idx].status & STAT_ECHO ? 'E' : 'e';
480 buf[i++] = dcc[idx].status & STAT_PAGE ? 'P' : 'p';
481 simple_sprintf(buf + i, "/%d", dcc[idx].u.chat->channel);
482 }
483
484 struct dcc_table DCC_CHAT =
485 {
486 "CHAT",
487 DCT_CHAT | DCT_MASTER | DCT_SHOWWHO | DCT_VALIDIDX | DCT_SIMUL |
488 DCT_CANBOOT | DCT_REMOTEWHO,
489 eof_dcc_chat,
490 dcc_chat,
491 NULL,
492 NULL,
493 display_dcc_chat,
494 kill_dcc_general,
495 out_dcc_general
496 };
497
498 static int lasttelnets;
499 static char lasttelnethost[81];
500 static time_t lasttelnettime;
501
502 /* A modified detect_flood for incoming telnet flood protection.
503 */
504 static int detect_telnet_flood(char *floodhost)
505 {
506 struct flag_record fr = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0};
507
508 get_user_flagrec(get_user_by_host(floodhost), &fr, NULL);
509 if (!flood_telnet_thr || glob_friend(fr))
510 return 0; /* No flood protection */
511 if (strcasecmp(lasttelnethost, floodhost)) { /* New... */
512 strcpy(lasttelnethost, floodhost);
513 lasttelnettime = now;
514 lasttelnets = 0;
515 return 0;
516 }
517 if (lasttelnettime < now - flood_telnet_time) {
518 /* Flood timer expired, reset it */
519 lasttelnettime = now;
520 lasttelnets = 0;
521 return 0;
522 }
523 lasttelnets++;
524 if (lasttelnets >= flood_telnet_thr) { /* FLOOD! */
525 /* Reset counters */
526 lasttelnets = 0;
527 lasttelnettime = 0;
528 lasttelnethost[0] = 0;
529 putlog(LOG_MISC, "*", _("Telnet connection flood from %s! Placing on ignore!"), floodhost);
530 addignore(floodhost, origbotname, "Telnet connection flood",
531 now + (60 * ignore_time));
532 return 1;
533 }
534 return 0;
535 }
536
537 static void dcc_telnet(int idx, char *buf, int i)
538 {
539 char ip[ADDRLEN];
540 unsigned short port;
541 int j, sock;
542 char s[UHOSTLEN + 1];
543
544 sock = answer(dcc[idx].sock, s, ip, &port, 0);
545 if (dcc_total + 1 > max_dcc) {
546 if (sock != -1) {
547 dprintf(-sock, "Sorry, too many connections already.\r\n");
548 killsock(sock);
549 }
550 return;
551 }
552 while ((sock == -1) && (errno == EAGAIN))
553 sock = answer(sock, s, ip, &port, 0);
554 if (sock < 0) {
555 neterror(s);
556 putlog(LOG_MISC, "*", _("Failed TELNET incoming (%s)"), s);
557 return;
558 }
559 /* Buffer data received on this socket. */
560 sockoptions(sock, EGG_OPTION_SET, SOCK_BUFFER);
561
562 if ((port < 1024) || (port > 65535)) {
563 putlog(LOG_BOTS, "*", _("Refused %s/%d (bad src port)"), s, port);
564 killsock(sock);
565 return;
566 }
567
568 j = strlen(ip);
569 i = new_dcc(&DCC_DNSWAIT, sizeof(struct dns_info));
570 dcc[i].sock = sock;
571 strcpy(dcc[i].addr, ip);
572 dcc[i].port = port;
573 dcc[i].timeval = now;
574 strcpy(dcc[i].nick, "*");
575 dcc[i].u.dns->host = calloc(1, j + 1);
576 strcpy(dcc[i].u.dns->host, dcc[i].addr);
577 debug3("|DCC| dcc_telnet: idx: %d addr: %s u.dns->host: %s", i, dcc[i].addr, dcc[i].u.dns->host);
578 dcc[i].u.dns->dns_success = dcc_telnet_hostresolved;
579 dcc[i].u.dns->dns_failure = dcc_telnet_hostresolved;
580 dcc[i].u.dns->dns_type = RES_HOSTBYIP;
581 dcc[i].u.dns->ibuf = dcc[idx].sock;
582 dcc[i].u.dns->type = &DCC_IDENTWAIT;
583 dcc_dnshostbyip(ip);
584 }
585
586 static void dcc_telnet_hostresolved(int i)
587 {
588 int idx;
589 int j = 0, sock;
590 char s[UHOSTLEN], s2[UHOSTLEN + 20];
591
592 strlcpy(dcc[i].host, dcc[i].u.dns->host, UHOSTLEN);
593 debug2("|DCC| dcc_telnet_hostresolved: idx: %d host: %s", i, dcc[i].host);
594
595 for (idx = 0; idx < dcc_total; idx++)
596 if ((dcc[idx].type == &DCC_TELNET) &&
597 (dcc[idx].sock == dcc[i].u.dns->ibuf)) {
598 break;
599 }
600 if (dcc_total == idx) {
601 putlog(LOG_BOTS, "*", _("Lost listening socket while resolving %s"),
602 dcc[i].host);
603 killsock(dcc[i].sock);
604 lostdcc(i);
605 return;
606 }
607 if (dcc[idx].host[0] == '@') {
608 /* Restrict by hostname */
609 if (!wild_match(dcc[idx].host + 1, dcc[i].host)) {
610 putlog(LOG_BOTS, "*", _("Refused %s (bad hostname)"), s);
611 killsock(dcc[i].sock);
612 lostdcc(i);
613 return;
614 }
615 }
616 sprintf(s2, "-telnet!telnet@%s", dcc[i].host);
617 if (match_ignore(s2) || detect_telnet_flood(s2)) {
618 killsock(dcc[i].sock);
619 lostdcc(i);
620 return;
621 }
622
623 changeover_dcc(i, &DCC_IDENTWAIT, 0);
624 dcc[i].timeval = now;
625 dcc[i].u.ident_sock = dcc[idx].sock;
626 sock = open_telnet(dcc[i].addr, 113);
627 putlog(LOG_MISC, "*", _("Telnet connection: %s/%d"), dcc[i].host, dcc[i].port);
628 s[0] = 0;
629 if (sock < 0) {
630 if (sock == -2)
631 strcpy(s, "DNS lookup failed for ident");
632 else
633 neterror(s);
634 } else {
635 j = new_dcc(&DCC_IDENT, 0);
636 if (j < 0) {
637 killsock(sock);
638 strcpy(s, "No Free DCC's");
639 }
640 }
641 if (s[0]) {
642 putlog(LOG_MISC, "*", _("Ident failed for %s: %s"), dcc[i].host, s);
643 sprintf(s, "telnet@%s", dcc[i].host);
644 dcc_telnet_got_ident(i, s);
645 return;
646 }
647 dcc[j].sock = sock;
648 dcc[j].port = 113;
649 strcpy(dcc[j].addr, dcc[i].addr);
650 strcpy(dcc[j].host, dcc[i].host);
651 strcpy(dcc[j].nick, "*");
652 dcc[j].u.ident_sock = dcc[i].sock;
653 dcc[j].timeval = now;
654 dprintf(j, "%d, %d\n", dcc[i].port, dcc[idx].port);
655 }
656
657 static void eof_dcc_telnet(int idx)
658 {
659 putlog(LOG_MISC, "*", _("(!) Listening port %d abruptly died."),
660 dcc[idx].port);
661 killsock(dcc[idx].sock);
662 lostdcc(idx);
663 }
664
665 static void display_telnet(int idx, char *buf)
666 {
667 sprintf(buf, "lstn %d%s", dcc[idx].port,
668 (dcc[idx].status & LSTN_PUBLIC) ? " pub" : "");
669 }
670
671 struct dcc_table DCC_TELNET =
672 {
673 "TELNET",
674 DCT_LISTEN,
675 eof_dcc_telnet,
676 dcc_telnet,
677 NULL,
678 NULL,
679 display_telnet,
680 NULL,
681 NULL
682 };
683
684 static void dcc_telnet_id(int idx, char *buf, int atr)
685 {
686 int ok = 0;
687 struct flag_record fr = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0};
688
689 strip_telnet(dcc[idx].sock, buf, &atr);
690 buf[HANDLEN] = 0;
691 /* Toss out bad nicknames */
692 if ((dcc[idx].nick[0] != '@') && (!wild_match(dcc[idx].nick, buf))) {
693 dprintf(idx, "Sorry, that nickname format is invalid.\n");
694 putlog(LOG_BOTS, "*", _("Refused %s (bad nick)"), dcc[idx].host);
695 killsock(dcc[idx].sock);
696 lostdcc(idx);
697 return;
698 }
699 dcc[idx].user = get_user_by_handle(userlist, buf);
700 get_user_flagrec(dcc[idx].user, &fr, NULL);
701 /* Make sure users-only/bots-only connects are honored */
702 if ((dcc[idx].status & STAT_BOTONLY) && !glob_bot(fr)) {
703 dprintf(idx, "This telnet port is for bots only.\n");
704 putlog(LOG_BOTS, "*", _("Refused %s (non-bot)"), dcc[idx].host);
705 killsock(dcc[idx].sock);
706 lostdcc(idx);
707 return;
708 }
709 if ((dcc[idx].status & STAT_USRONLY) && glob_bot(fr)) {
710 dprintf(idx, "error Only users may connect at this port.\n");
711 putlog(LOG_BOTS, "*", _("Refused %s (non-user)"), dcc[idx].host);
712 killsock(dcc[idx].sock);
713 lostdcc(idx);
714 return;
715 }
716 dcc[idx].status &= ~(STAT_BOTONLY | STAT_USRONLY);
717 if (!strcasecmp(buf, "NEW") && (learn_users || make_userfile)) {
718 dcc[idx].type = &DCC_TELNET_NEW;
719 dcc[idx].timeval = now;
720 dprintf(idx, "\n");
721 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"), myname);
722 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!"));
723 dprintf(idx, "\nEnter the nickname you would like to use.\n");
724 return;
725 }
726 if (!ok && (glob_party(fr) || glob_bot(fr)))
727 ok = 1;
728
729 if (!ok) {
730 dprintf(idx, "You don't have access.\n");
731 putlog(LOG_BOTS, "*", _("Refused %s (invalid handle: %s)"), dcc[idx].host, buf);
732 killsock(dcc[idx].sock);
733 lostdcc(idx);
734 return;
735 }
736 correct_handle(buf);
737 strcpy(dcc[idx].nick, buf);
738 dcc_telnet_pass(idx, atr);
739 }
740
741 static void dcc_telnet_pass(int idx, int atr)
742 {
743 int ok = 0;
744 struct flag_record fr = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0};
745
746 get_user_flagrec(dcc[idx].user, &fr, NULL);
747 /* No password set? */
748 if (u_pass_match(dcc[idx].user, "-")) {
749 dprintf(idx, "Can't telnet until you have a password set.\n");
750 putlog(LOG_MISC, "*", _("Refused [%s]%s (no password)"), dcc[idx].nick, dcc[idx].host);
751 killsock(dcc[idx].sock);
752 lostdcc(idx);
753 return;
754 }
755 ok = 0;
756 dcc[idx].type = &DCC_CHAT_PASS;
757 dcc[idx].timeval = now;
758 if (glob_botmast(fr))
759 ok = 1;
760 else if (glob_party(fr)) {
761 ok = 1;
762 dcc[idx].status |= STAT_PARTY;
763 }
764 if (glob_bot(fr))
765 ok = 1;
766 if (!ok) {
767 struct chat_info *ci;
768
769 ci = dcc[idx].u.chat;
770 dcc[idx].u.file = calloc(1, sizeof(struct file_info));
771 dcc[idx].u.file->chat = ci;
772 }
773
774 /* Turn off remote telnet echo (send IAC WILL ECHO). */
775 dprintf(idx, "\n%s" TLN_IAC_C TLN_WILL_C TLN_ECHO_C "\n", _("Enter your password."));
776 }
777
778 static void eof_dcc_telnet_id(int idx)
779 {
780 putlog(LOG_MISC, "*", _("Lost telnet connection to %s/%d"), dcc[idx].host,
781 dcc[idx].port);
782 killsock(dcc[idx].sock);
783 lostdcc(idx);
784 }
785
786 static void timeout_dcc_telnet_id(int idx)
787 {
788 dprintf(idx, "Timeout.\n");
789 putlog(LOG_MISC, "*", _("Ident timeout on telnet: %s"), dcc[idx].host);
790 killsock(dcc[idx].sock);
791 lostdcc(idx);
792 }
793
794 static void display_dcc_telnet_id(int idx, char *buf)
795 {
796 sprintf(buf, "t-in waited %lus", now - dcc[idx].timeval);
797 }
798
799 struct dcc_table DCC_TELNET_ID =
800 {
801 "TELNET_ID",
802 0,
803 eof_dcc_telnet_id,
804 dcc_telnet_id,
805 &password_timeout,
806 timeout_dcc_telnet_id,
807 display_dcc_telnet_id,
808 kill_dcc_general,
809 out_dcc_general
810 };
811
812 static void dcc_telnet_new(int idx, char *buf, int x)
813 {
814 int ok = 1;
815 char work[1024], *p, *q, *r;
816
817 buf[HANDLEN] = 0;
818 strip_telnet(dcc[idx].sock, buf, &x);
819 dcc[idx].timeval = now;
820 for (x = 0; x < strlen(buf); x++)
821 if ((buf[x] <= 32) || (buf[x] >= 127))
822 ok = 0;
823 if (!ok) {
824 dprintf(idx, "\nYou can't use weird symbols in your nick.\n");
825 dprintf(idx, "Try another one please:\n");
826 } else if (strchr("-,+*=:!.@#;$", buf[0]) != NULL) {
827 dprintf(idx, "\nYou can't start your nick with the character '%c'\n",
828 buf[0]);
829 dprintf(idx, "Try another one please:\n");
830 } else if (get_user_by_handle(userlist, buf)) {
831 dprintf(idx, "\nSorry, that nickname is taken already.\n");
832 dprintf(idx, "Try another one please:\n");
833 return;
834 } else if (!strcasecmp(buf, myname)) {
835 dprintf(idx, "Sorry, can't use my name for a nick.\n");
836 } else {
837 strcpy(dcc[idx].nick, buf);
838 if (make_userfile)
839 userlist = adduser(userlist, buf, "-telnet!*@*", "-",
840 sanity_check(default_flags | USER_PARTY |
841 USER_MASTER | USER_OWNER));
842 else {
843 p = strchr(dcc[idx].host, '@');
844 if (p) {
845 q = p;
846 *q = 0;
847 p++;
848 r = strchr(p, '.');
849 if (!r)
850 simple_sprintf(work, "-telnet!%s@%s", dcc[idx].host, p);
851 else
852 simple_sprintf(work, "-telnet!%s@*%s", dcc[idx].host, r);
853 *q = '@';
854 } else
855 simple_sprintf(work, "-telnet!*@*%s", dcc[idx].host);
856 userlist = adduser(userlist, buf, work, "-",
857 sanity_check(USER_PARTY | default_flags));
858 }
859 //reaffirm_owners();
860 dcc[idx].status = STAT_ECHO | STAT_TELNET;
861 dcc[idx].type = &DCC_CHAT; /* Just so next line will work */
862 dcc[idx].user = get_user_by_handle(userlist, buf);
863 //check_dcc_attrs(dcc[idx].user, USER_PARTY | default_flags);
864 dcc[idx].type = &DCC_TELNET_PW;
865 if (make_userfile) {
866 dprintf(idx, _("\nYOU ARE THE MASTER/OWNER ON THIS BOT NOW\n"));
867 dprintf(idx, _("From now on, you dont need to use the -m option to start the bot.\nEnjoy !!"));
868 putlog(LOG_MISC, "*", _("Bot installation complete, first master is %s"), buf);
869 make_userfile = 0;
870 write_userfile(-1);
871 add_note(buf, myname, _("Welcome to Eggdrop! :)"), -1, 0);
872 }
873 dprintf(idx, _("\nOkay, now choose and enter a password:\n"));
874 dprintf(idx, _("(Only the first 15 letters are significant.)\n"));
875 }
876 }
877
878 static void dcc_telnet_pw(int idx, char *buf, int x)
879 {
880 char *newpass;
881 int ok;
882
883 strip_telnet(dcc[idx].sock, buf, &x);
884 buf[16] = 0;
885 ok = 1;
886 if (strlen(buf) < 4) {
887 dprintf(idx, "\nTry to use at least 4 characters in your password.\n");
888 dprintf(idx, "Choose and enter a password:\n");
889 return;
890 }
891 for (x = 0; x < strlen(buf); x++)
892 if ((buf[x] <= 32) || (buf[x] == 127))
893 ok = 0;
894 if (!ok) {
895 dprintf(idx, "\nYou can't use weird symbols in your password.\n");
896 dprintf(idx, "Try another one please:\n");
897 return;
898 }
899 putlog(LOG_MISC, "*", _("New user via telnet: [%s]%s/%d"), dcc[idx].nick, dcc[idx].host,
900 dcc[idx].port);
901 if (notify_new[0]) {
902 char s[121], s1[121], s2[121];
903
904 sprintf(s, "Introduced to %s, %s", dcc[idx].nick, dcc[idx].host);
905 strcpy(s1, notify_new);
906 splitc(s2, s1, ',');
907 while (s2[0]) {
908 rmspace(s2);
909 add_note(s2, myname, s, -1, 0);
910 splitc(s2, s1, ',');
911 }
912 rmspace(s1);
913 add_note(s1, myname, s, -1, 0);
914 }
915 newpass = newsplit(&buf);
916 set_user(&USERENTRY_PASS, dcc[idx].user, newpass);
917 dprintf(idx, "\nRemember that! You'll need it next time you log in.\n");
918 dprintf(idx, "You now have an account on %s...\n\n\n", myname);
919 dcc[idx].type = &DCC_CHAT;
920 dcc[idx].u.chat->channel = -2;
921 dcc_chatter(idx);
922 }
923
924 static void eof_dcc_telnet_new(int idx)
925 {
926 putlog(LOG_MISC, "*", _("Lost new telnet user (%s/%d)"), dcc[idx].host, dcc[idx].port);
927 killsock(dcc[idx].sock);
928 lostdcc(idx);
929 }
930
931 static void eof_dcc_telnet_pw(int idx)
932 {
933 putlog(LOG_MISC, "*", _("Lost new telnet user %s (%s/%d)"), dcc[idx].nick, dcc[idx].host,
934 dcc[idx].port);
935 deluser(dcc[idx].nick);
936 killsock(dcc[idx].sock);
937 lostdcc(idx);
938 }
939
940 static void tout_dcc_telnet_new(int idx)
941 {
942 dprintf(idx, "Guess you're not there. Bye.\n");
943 putlog(LOG_MISC, "*", _("Timeout on new telnet user: %s/%d"), dcc[idx].host,
944 dcc[idx].port);
945 killsock(dcc[idx].sock);
946 lostdcc(idx);
947 }
948
949 static void tout_dcc_telnet_pw(int idx)
950 {
951 dprintf(idx, "Guess you're not there. Bye.\n");
952 putlog(LOG_MISC, "*", _("Timeout on new telnet user: [%s]%s/%d"), dcc[idx].nick,
953 dcc[idx].host, dcc[idx].port);
954 killsock(dcc[idx].sock);
955 lostdcc(idx);
956 }
957
958 static void display_dcc_telnet_new(int idx, char *buf)
959 {
960 sprintf(buf, "new waited %lus", now - dcc[idx].timeval);
961 }
962
963 static void display_dcc_telnet_pw(int idx, char *buf)
964 {
965 sprintf(buf, "newp waited %lus", now - dcc[idx].timeval);
966 }
967
968 struct dcc_table DCC_TELNET_NEW =
969 {
970 "TELNET_NEW",
971 0,
972 eof_dcc_telnet_new,
973 dcc_telnet_new,
974 &password_timeout,
975 tout_dcc_telnet_new,
976 display_dcc_telnet_new,
977 kill_dcc_general,
978 out_dcc_general
979 };
980
981 struct dcc_table DCC_TELNET_PW =
982 {
983 "TELNET_PW",
984 0,
985 eof_dcc_telnet_pw,
986 dcc_telnet_pw,
987 &password_timeout,
988 tout_dcc_telnet_pw,
989 display_dcc_telnet_pw,
990 kill_dcc_general,
991 out_dcc_general
992 };
993
994 static void dcc_script(int idx, char *buf, int len)
995 {
996 long oldsock;
997 script_callback_t *callback;
998
999 strip_telnet(dcc[idx].sock, buf, &len);
1000 if (!len)
1001 return;
1002
1003 callback = dcc[idx].u.script->callback;
1004 dcc[idx].timeval = now;
1005 oldsock = dcc[idx].sock; /* Remember the socket number. */
1006
1007 /* Execute the script callback. */
1008 if (callback->callback(callback, idx, buf)) {
1009 void *old_other = NULL;
1010
1011 /* Check whether the socket and dcc entry are still valid. They
1012 might have been killed by `killdcc'. */
1013 if (idx > max_dcc || dcc[idx].sock != oldsock)
1014 return;
1015
1016 old_other = dcc[idx].u.script->u.other;
1017 dcc[idx].type = dcc[idx].u.script->type;
1018 free(dcc[idx].u.script);
1019 dcc[idx].u.other = old_other;
1020 if (dcc[idx].type == &DCC_SOCKET) {
1021 /* Kill the whole thing off */
1022 killsock(dcc[idx].sock);
1023 lostdcc(idx);
1024 return;
1025 }
1026
1027 /* If we're not closing the idx, we have to delete the callback manually. */
1028 callback->del(callback);
1029
1030 if (dcc[idx].type == &DCC_CHAT) {
1031 if (dcc[idx].u.chat->channel >= 0) {
1032 chanout_but(-1, dcc[idx].u.chat->channel, _("*** %s has joined the party line.\n"), dcc[idx].nick);
1033 }
1034 }
1035 }
1036 }
1037
1038 static void eof_dcc_script(int idx)
1039 {
1040 void *old;
1041 int oldflags;
1042 script_callback_t *callback;
1043
1044 /* This will stop a killdcc from working, incase the script tries
1045 * to kill it's controlling socket while handling an EOF <cybah>
1046 */
1047 oldflags = dcc[idx].type->flags;
1048 dcc[idx].type->flags &= ~(DCT_VALIDIDX);
1049
1050 /* Tell the script they're gone: */
1051 callback = dcc[idx].u.script->callback;
1052 callback->callback(callback, idx, "");
1053 callback->del(callback);
1054
1055 /* Restore the flags */
1056 dcc[idx].type->flags = oldflags;
1057 old = dcc[idx].u.script->u.other;
1058 dcc[idx].type = dcc[idx].u.script->type;
1059 free(dcc[idx].u.script);
1060 dcc[idx].u.other = old;
1061 /* Then let it fall thru to the real one */
1062 if (dcc[idx].type && dcc[idx].type->eof)
1063 dcc[idx].type->eof(idx);
1064 else {
1065 putlog(LOG_MISC, "*", _("*** ATTENTION: DEAD SOCKET (%d) OF TYPE %s UNTRAPPED"), dcc[idx].sock,
1066 dcc[idx].type->name);
1067 killsock(dcc[idx].sock);
1068 lostdcc(idx);
1069 }
1070 }
1071
1072 static void display_dcc_script(int idx, char *buf)
1073 {
1074 sprintf(buf, "scri %s", dcc[idx].u.script->callback->name);
1075 }
1076
1077 static void kill_dcc_script(int idx, void *x)
1078 {
1079 script_callback_t *callback;
1080 struct script_info *p = (struct script_info *) x;
1081
1082 callback = p->callback;
1083 callback->del(callback);
1084 if (p->type && p->u.other)
1085 p->type->kill(idx, p->u.other);
1086 free(p);
1087 }
1088
1089 static void out_dcc_script(int idx, char *buf, void *x)
1090 {
1091 struct script_info *p = (struct script_info *) x;
1092
1093 if (p && p->type && p->u.other)
1094 p->type->output(idx, buf, p->u.other);
1095 else
1096 tputs(dcc[idx].sock, buf, strlen(buf));
1097 }
1098
1099 struct dcc_table DCC_SCRIPT =
1100 {
1101 "SCRIPT",
1102 DCT_VALIDIDX,
1103 eof_dcc_script,
1104 dcc_script,
1105 NULL,
1106 NULL,
1107 display_dcc_script,
1108 kill_dcc_script,
1109 out_dcc_script
1110 };
1111
1112 static void dcc_socket(int idx, char *buf, int len)
1113 {
1114 }
1115
1116 static void eof_dcc_socket(int idx)
1117 {
1118 killsock(dcc[idx].sock);
1119 lostdcc(idx);
1120 }
1121
1122 static void display_dcc_socket(int idx, char *buf)
1123 {
1124 strcpy(buf, "sock (stranded)");
1125 }
1126
1127 struct dcc_table DCC_SOCKET =
1128 {
1129 "SOCKET",
1130 DCT_VALIDIDX,
1131 eof_dcc_socket,
1132 dcc_socket,
1133 NULL,
1134 NULL,
1135 display_dcc_socket,
1136 NULL,
1137 NULL
1138 };
1139
1140 static void display_dcc_lost(int idx, char *buf)
1141 {
1142 strcpy(buf, "lost");
1143 }
1144
1145 struct dcc_table DCC_LOST =
1146 {
1147 "LOST",
1148 0,
1149 NULL,
1150 dcc_socket,
1151 NULL,
1152 NULL,
1153 display_dcc_lost,
1154 NULL,
1155 NULL
1156 };
1157
1158 void dcc_identwait(int idx, char *buf, int len)
1159 {
1160 /* Ignore anything now */
1161 }
1162
1163 void eof_dcc_identwait(int idx)
1164 {
1165 int i;
1166
1167 putlog(LOG_MISC, "*", _("Lost connection while identing [%s/%d]"), dcc[idx].host, dcc[idx].port);
1168 for (i = 0; i < dcc_total; i++)
1169 if ((dcc[i].type == &DCC_IDENT) &&
1170 (dcc[i].u.ident_sock == dcc[idx].sock)) {
1171 killsock(dcc[i].sock); /* Cleanup ident socket */
1172 dcc[i].u.other = 0;
1173 lostdcc(i);
1174 break;
1175 }
1176 killsock(dcc[idx].sock); /* Cleanup waiting socket */
1177 dcc[idx].u.other = 0;
1178 lostdcc(idx);
1179 }
1180
1181 static void display_dcc_identwait(int idx, char *buf)
1182 {
1183 sprintf(buf, "idtw waited %lus", now - dcc[idx].timeval);
1184 }
1185
1186 struct dcc_table DCC_IDENTWAIT =
1187 {
1188 "IDENTWAIT",
1189 0,
1190 eof_dcc_identwait,
1191 dcc_identwait,
1192 NULL,
1193 NULL,
1194 display_dcc_identwait,
1195 NULL,
1196 NULL
1197 };
1198
1199 void dcc_ident(int idx, char *buf, int len)
1200 {
1201 char response[512], uid[512], buf1[UHOSTLEN];
1202 int i;
1203
1204 sscanf(buf, "%*[^:]:%[^:]:%*[^:]:%[^\n]\n", response, uid);
1205 rmspace(response);
1206 if (response[0] != 'U') {
1207 dcc[idx].timeval = now;
1208 return;
1209 }
1210 rmspace(uid);
1211 uid[20] = 0; /* 20 character ident max */
1212 for (i = 0; i < dcc_total; i++)
1213 if ((dcc[i].type == &DCC_IDENTWAIT) &&
1214 (dcc[i].sock == dcc[idx].u.ident_sock)) {
1215 simple_sprintf(buf1, "%s@%s", uid, dcc[idx].host);
1216 dcc_telnet_got_ident(i, buf1);
1217 }
1218 dcc[idx].u.other = 0;
1219 killsock(dcc[idx].sock);
1220 lostdcc(idx);
1221 }
1222
1223 void eof_dcc_ident(int idx)
1224 {
1225 char buf[UHOSTLEN];
1226 int i;
1227
1228 for (i = 0; i < dcc_total; i++)
1229 if ((dcc[i].type == &DCC_IDENTWAIT) &&
1230 (dcc[i].sock == dcc[idx].u.ident_sock)) {
1231 putlog(LOG_MISC, "*", _("Timeout/EOF ident connection"));
1232 simple_sprintf(buf, "telnet@%s", dcc[idx].host);
1233 dcc_telnet_got_ident(i, buf);
1234 }
1235 killsock(dcc[idx].sock);
1236 dcc[idx].u.other = 0;
1237 lostdcc(idx);
1238 }
1239
1240 static void display_dcc_ident(int idx, char *buf)
1241 {
1242 sprintf(buf, "idnt (sock %d)", dcc[idx].u.ident_sock);
1243 }
1244
1245 struct dcc_table DCC_IDENT =
1246 {
1247 "IDENT",
1248 0,
1249 eof_dcc_ident,
1250 dcc_ident,
1251 &ident_timeout,
1252 eof_dcc_ident,
1253 display_dcc_ident,
1254 NULL,
1255 NULL
1256 };
1257
1258 void dcc_telnet_got_ident(int i, char *host)
1259 {
1260 int idx;
1261 char x[1024];
1262
1263 for (idx = 0; idx < dcc_total; idx++)
1264 if ((dcc[idx].type == &DCC_TELNET) &&
1265 (dcc[idx].sock == dcc[i].u.ident_sock))
1266 break;
1267 dcc[i].u.other = 0;
1268 if (dcc_total == idx) {
1269 putlog(LOG_MISC, "*", _("Lost ident wait telnet socket!!"));
1270 killsock(dcc[i].sock);
1271 lostdcc(i);
1272 return;
1273 }
1274 strlcpy(dcc[i].host, host, UHOSTLEN);
1275 snprintf(x, sizeof x, "-telnet!%s", dcc[i].host);
1276 if (protect_telnet && !make_userfile) {
1277 struct userrec *u;
1278 int ok = 1;
1279
1280 u = get_user_by_host(x);
1281 /* Not a user or +p & require p OR +o */
1282 if (!u)
1283 ok = 0;
1284 else if (!(u->flags & USER_PARTY))
1285 ok = 0;
1286 if (!ok && (dcc[idx].status & LSTN_PUBLIC))
1287 ok = 1;
1288 if (!ok) {
1289 putlog(LOG_MISC, "*", _("Denied telnet: %s, No Access"), dcc[i].host);
1290 killsock(dcc[i].sock);
1291 lostdcc(i);
1292 return;
1293 }
1294 }
1295 if (match_ignore(x)) {
1296 killsock(dcc[i].sock);
1297 lostdcc(i);
1298 return;
1299 }
1300 /* Script? */
1301 if (!strcmp(dcc[idx].nick, "(script)")) {
1302 dcc[i].type = &DCC_SOCKET;
1303 dcc[i].u.other = NULL;
1304 strcpy(dcc[i].nick, "*");
1305 //check_bind_listen(dcc[idx].host, dcc[i].sock);
1306 return;
1307 }
1308 /* Do not buffer data anymore. All received and stored data is passed
1309 over to the dcc functions from now on. */
1310 sockoptions(dcc[i].sock, EGG_OPTION_UNSET, SOCK_BUFFER);
1311
1312 dcc[i].type = &DCC_TELNET_ID;
1313 dcc[i].u.chat = calloc(1, sizeof(struct chat_info));
1314
1315 /* Copy acceptable-nick/host mask */
1316 dcc[i].status = STAT_TELNET | STAT_ECHO;
1317 if (!strcmp(dcc[idx].nick, "(bots)"))
1318 dcc[i].status |= STAT_BOTONLY;
1319 if (!strcmp(dcc[idx].nick, "(users)"))
1320 dcc[i].status |= STAT_USRONLY;
1321 /* Copy acceptable-nick/host mask */
1322 strlcpy(dcc[i].nick, dcc[idx].host, HANDLEN);
1323 dcc[i].timeval = now;
1324 strcpy(dcc[i].u.chat->con_chan, chanset ? chanset->name : "*");
1325
1326 /* Displays a telnet banner if the file exists. */
1327 show_telnet_banner(i);
1328
1329 dprintf(i, "\n\n");
1330 sub_lang(i, _("%B (%E)\n\nPlease enter your nickname.\n"));
1331
1332 if (learn_users)
1333 dprintf(i, "(If you are new, enter 'NEW' here.)\n");
1334 }
1335
1336 /* Trace callbacks for our script variables. */
1337 int dcc_write_max_dcc(script_linked_var_t *linked_var, script_var_t *newvalue)
1338 {
1339 int newval = (int) newvalue->value;
1340 int i;
1341
1342 /* If they're shrinking it, determine the most we can shrink. */
1343 if (newval < dcc_total) {
1344 for (i = dcc_total; i > 0; --i) {
1345 if (dcc[i].type) break;
1346 }
1347 if (newval < i+1) newval = i+1;
1348 dcc_total = newval;
1349 }
1350
1351 /* Use init_dcc_max to resize the array. */
1352 init_dcc_max(newval);
1353
1354 return(0);
1355 }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23