/[cvs]/eggdrop1.9/src/dcc.c
ViewVC logotype

Annotation of /eggdrop1.9/src/dcc.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.99 - (hide annotations) (download) (as text)
Tue Feb 25 06:52:19 2003 UTC (16 years, 8 months ago) by stdarg
Branch: MAIN
Changes since 1.98: +3 -4 lines
File MIME type: text/x-chdr
* Well, I think Tcl is finally removed from the core (except for detection/configuration).

1 guppy 1.44 /*
2 tothwolf 1.85 * dcc.c --
3 guppy 1.44 *
4 tothwolf 1.85 * activity on a dcc socket
5     * disconnect on a dcc socket
6     * ...and that's it! (but it's a LOT)
7 segfault 1.1 */
8 guppy 1.44 /*
9     * Copyright (C) 1997 Robey Pointer
10 wcc 1.95 * Copyright (C) 1999, 2000, 2001, 2002, 2003 Eggheads Development Team
11 guppy 1.44 *
12 fabian 1.14 * 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 guppy 1.44 *
17 fabian 1.14 * 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 guppy 1.44 *
22 fabian 1.14 * 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 segfault 1.1 */
26 tothwolf 1.85
27     #ifndef lint
28 stdarg 1.99 static const char rcsid[] = "$Id: dcc.c,v 1.98 2003/02/18 10:37:18 stdarg Exp $";
29 tothwolf 1.85 #endif
30 segfault 1.1
31     #include "main.h"
32     #include <ctype.h>
33     #include <errno.h>
34     #include "modules.h"
35 ite 1.70 #include "logfile.h"
36     #include "dns.h"
37     #include "misc.h"
38 wingman 1.84 #include "cmdt.h" /* cmd_t */
39     #include "users.h" /* match_ignore, addignore, get_user_by_host */
40 stdarg 1.93 //#include "chanprog.h" /* reaffirm_owners */
41     //#include "cmds.h" /* check_dcc_attrs */
42 wingman 1.84 #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 segfault 1.1
52 fabian 1.22 extern struct userrec *userlist;
53     extern struct chanset_t *chanset;
54 wcc 1.97 extern time_t now;
55     extern int egg_numver, connect_timeout, conmask, backgrd, make_userfile,
56 stdarg 1.99 default_flags, raw_log, ignore_time;
57 wcc 1.97 extern char myname[], ver[], origbotname[], notify_new[];
58 wingman 1.84
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 fabian 1.22
66    
67     struct dcc_t *dcc = NULL; /* DCC list */
68     int dcc_total = 0; /* Total dcc's */
69 stdarg 1.81 int max_dcc = 0; /* Max number of dcc's */
70 fabian 1.22 char tempdir[121] = ""; /* Temporary directory
71     (default: current directory) */
72 guppy 1.65 int learn_users = 0; /* Allow people to introduce themselves */
73 fabian 1.22 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 stdarg 1.83 int ident_timeout = 5; /* Timeout value for ident lookups */
77 fabian 1.22 int dupwait_timeout = 5; /* Timeout for rejecting duplicate entries */
78 stdarg 1.83 extern int resolve_timeout;
79 fabian 1.22 int protect_telnet = 1; /* Even bother with ident lookups :) */
80 stdarg 1.83 int dcc_flood_thr = 3;
81 fabian 1.22 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 segfault 1.1
86 stdarg 1.80 /* This var specifies the chars to recognize as commands characters for dcc
87     commands. Default value is "./" */
88 stdarg 1.62 static char *dcc_command_chars = NULL;
89    
90 fabian 1.10 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 stdarg 1.80 /* Callback functions for linked variables. */
95     static int dcc_write_max_dcc(script_linked_var_t *linked_var, script_var_t *newvalue);
96    
97 fabian 1.22
98 stdarg 1.81 extern void init_dcc_max(int newmax);
99 stdarg 1.62
100 stdarg 1.80 static script_var_callbacks_t max_dcc_callback = {
101     NULL,
102     dcc_write_max_dcc,
103     NULL
104     };
105    
106 stdarg 1.78 static script_linked_var_t dcc_script_vars[] = {
107     {"", "dcc_command_chars", &dcc_command_chars, SCRIPT_STRING, NULL},
108 stdarg 1.80 {"", "max_dcc", &max_dcc, SCRIPT_INTEGER, &max_dcc_callback},
109 stdarg 1.83 {"", "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 stdarg 1.63 {0}
116 stdarg 1.62 };
117    
118     void dcc_init()
119     {
120 ite 1.68 dcc_command_chars = strdup("./");
121 stdarg 1.87 script_link_vars(dcc_script_vars);
122 ite 1.82 init_dcc_max(50);
123 stdarg 1.62 }
124    
125 segfault 1.1 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 fabian 1.30 while ((*p != TLN_IAC) && (*p != 0))
132 segfault 1.1 *o++ = *p++;
133 fabian 1.30 if (*p == TLN_IAC) {
134 segfault 1.1 p++;
135     mark = 2;
136     if (!*p)
137     mark = 1; /* bogus */
138 fabian 1.30 if ((*p >= TLN_WILL) && (*p <= TLN_DONT)) {
139 segfault 1.1 mark = 3;
140     if (!*(p + 1))
141     mark = 2; /* bogus */
142     }
143 fabian 1.30 if (*p == TLN_WILL) {
144 segfault 1.1 /* WILL X -> response: DONT X */
145     /* except WILL ECHO which we just smile and ignore */
146 fabian 1.30 if (*(p + 1) != TLN_ECHO) {
147     write(sock, TLN_IAC_C TLN_DONT_C, 2);
148 segfault 1.1 write(sock, p + 1, 1);
149     }
150     }
151 fabian 1.30 if (*p == TLN_DO) {
152 segfault 1.1 /* DO X -> response: WONT X */
153     /* except DO ECHO which we just smile and ignore */
154 fabian 1.30 if (*(p + 1) != TLN_ECHO) {
155     write(sock, TLN_IAC_C TLN_WONT_C, 2);
156 segfault 1.1 write(sock, p + 1, 1);
157     }
158     }
159 fabian 1.30 if (*p == TLN_AYT) {
160 segfault 1.1 /* "are you there?" */
161     /* response is: "hell yes!" */
162     write(sock, "\r\nHell, yes!\r\n", 14);
163     }
164 fabian 1.22 /* Anything else can probably be ignored */
165 segfault 1.1 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 guppy 1.43 if (u_pass_match(dcc[idx].user, buf)) {
180 fabian 1.22 /* Log entry for successful login -slennox 3/28/1999 */
181 ite 1.49 putlog(LOG_MISC, "*", _("Logged in: %s (%s/%d)"), dcc[idx].nick,
182 segfault 1.1 dcc[idx].host, dcc[idx].port);
183 tothwolf 1.56 if (dcc[idx].u.chat->away)
184     free_null(dcc[idx].u.chat->away);
185 segfault 1.1 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 fabian 1.30 /* Turn echo back on for telnet sessions (send IAC WON'T ECHO). */
190 segfault 1.1 if (dcc[idx].status & STAT_TELNET)
191 fabian 1.30 dprintf(idx, TLN_IAC_C TLN_WONT_C TLN_ECHO_C "\n");
192 segfault 1.1 dcc_chatter(idx);
193     } else {
194 ite 1.49 dprintf(idx, _("Negative on that, Houston.\n"));
195     putlog(LOG_MISC, "*", _("Bad Password: [%s]%s/%d"), dcc[idx].nick,
196 segfault 1.1 dcc[idx].host, dcc[idx].port);
197     if (dcc[idx].u.chat->away) { /* su from a dumb user */
198 fabian 1.30 /* Turn echo back on for telnet sessions (send IAC WON'T ECHO). */
199 segfault 1.1 if (dcc[idx].status & STAT_TELNET)
200 fabian 1.30 dprintf(idx, TLN_IAC_C TLN_WONT_C TLN_ECHO_C "\n");
201 segfault 1.1 dcc[idx].user = get_user_by_handle(userlist, dcc[idx].u.chat->away);
202     strcpy(dcc[idx].nick, dcc[idx].u.chat->away);
203 tothwolf 1.56 free_null(dcc[idx].u.chat->away);
204     free_null(dcc[idx].u.chat->su_nick);
205 segfault 1.1 dcc[idx].type = &DCC_CHAT;
206     if (dcc[idx].u.chat->channel < 100000)
207 ite 1.49 chanout_but(-1, dcc[idx].u.chat->channel, _("*** %s has joined the party line.\n"), dcc[idx].nick);
208 segfault 1.1 } else {
209     killsock(dcc[idx].sock);
210     lostdcc(idx);
211     }
212     }
213     }
214    
215     static void eof_dcc_general(int idx)
216     {
217 ite 1.49 putlog(LOG_MISC, "*", _("Lost dcc connection to %s (%s/%d)"), dcc[idx].nick,
218 segfault 1.1 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 ite 1.49 putlog(LOG_MISC, "*", _("Password timeout on dcc chat: [%s]%s"), dcc[idx].nick,
227 segfault 1.1 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 guppy 1.47 struct msgq *r, *q;
244 segfault 1.1
245 guppy 1.47 for (r = dcc[idx].u.chat->buffer; r; r = q) {
246 segfault 1.1 q = r->next;
247 tothwolf 1.56 free(r->msg);
248     free(r);
249 segfault 1.1 }
250     }
251     if (p->away) {
252 tothwolf 1.56 free(p->away);
253 segfault 1.1 }
254 tothwolf 1.56 free(p);
255 segfault 1.1 }
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 fabian 1.22 /* They're probably trying to fill up the bot nuke the sods :) */
267 guppy 1.47 for (p = c->buffer; p; p = q) {
268 segfault 1.1 q = p->next;
269 tothwolf 1.56 free(p->msg);
270     free(p);
271 segfault 1.1 }
272     c->buffer = 0;
273     dcc[idx].status &= ~STAT_PAGE;
274 wcc 1.97 do_boot(idx, myname, "too many pages - senq full");
275 segfault 1.1 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 guppy 1.47 else
285     for (q = c->buffer; q->next; q = q->next);
286    
287 tothwolf 1.58 p = calloc(1, sizeof(struct msgq));
288 segfault 1.1 p->len = l;
289 tothwolf 1.58 p->msg = calloc(1, l + 1);
290 segfault 1.1 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 fabian 1.22 /* Make sure ansi code is just for color-changing
325     */
326 segfault 1.1 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 ite 1.49 putlog(LOG_MISC, "*", _("Lost dcc connection to %s (%s/%d)"), dcc[idx].nick,
348 segfault 1.1 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 stdarg 1.62 int iscommand;
361 segfault 1.1 char *v, *d;
362    
363     strip_telnet(dcc[idx].sock, buf, &i);
364 stdarg 1.62 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 segfault 1.1 dcc[idx].timeval = now;
371 stdarg 1.62
372 fabian 1.22 /* Check for beeps and cancel annoying ones */
373 segfault 1.1 v = buf;
374     d = buf;
375     while (*v)
376     switch (*v) {
377 fabian 1.22 case 7: /* Beep - no more than 3 */
378 segfault 1.1 nathan++;
379     if (nathan > 3)
380     v++;
381     else
382     *d++ = *v++;
383     break;
384 fabian 1.22 case 8: /* Backspace - for lame telnet's :) */
385 segfault 1.1 if (d > buf) {
386     d--;
387     }
388     v++;
389     break;
390     case 27: /* ESC - ansi code? */
391     doron = check_ansi(v);
392 fabian 1.22 /* If it's valid, append a return-to-normal code at the end */
393 segfault 1.1 if (!doron) {
394     *d++ = *v++;
395     fixed = 1;
396     } else
397     v += doron;
398     break;
399 fabian 1.22 case '\r': /* Weird pseudo-linefeed */
400 segfault 1.1 v++;
401     break;
402     default:
403     *d++ = *v++;
404     }
405     if (fixed)
406     strcpy(d, "\033[0m");
407     else
408     *d = 0;
409 stdarg 1.54
410 stdarg 1.62 if (iscommand || (dcc[idx].u.chat->channel < 0)) {
411     if (iscommand) buf++;
412 segfault 1.1 v = newsplit(&buf);
413     rmspace(buf);
414 stdarg 1.98 //check_bind_dcc(v, idx, buf);
415 stdarg 1.62 }
416     else if (buf[0] == ',') {
417 segfault 1.1 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 stdarg 1.62 struct userrec *u;
423 segfault 1.1
424 stdarg 1.79 if (!dcc[i].type) continue;
425    
426 stdarg 1.62 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 segfault 1.1 }
437     }
438 stdarg 1.62 }
439     else if (buf[0] == '\'') {
440 segfault 1.1 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 stdarg 1.79 if (dcc[i].type && dcc[i].type->flags & DCT_CHAT) {
447 segfault 1.1 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 stdarg 1.54 } else {
454 stdarg 1.94 int r = 0;
455 stdarg 1.61
456     if (r & BIND_RET_BREAK) return;
457    
458 segfault 1.1 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 stdarg 1.62 }
467 fabian 1.22 if (dcc[idx].type == &DCC_CHAT) /* Could have change to files */
468 segfault 1.1 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 fabian 1.22 NULL,
492     NULL,
493 segfault 1.1 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 fabian 1.22 /* A modified detect_flood for incoming telnet flood protection.
503     */
504 segfault 1.1 static int detect_telnet_flood(char *floodhost)
505     {
506 fabian 1.22 struct flag_record fr = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0};
507    
508 segfault 1.1 get_user_flagrec(get_user_by_host(floodhost), &fr, NULL);
509 stdarg 1.99 if (!flood_telnet_thr || glob_friend(fr))
510 fabian 1.22 return 0; /* No flood protection */
511 tothwolf 1.60 if (strcasecmp(lasttelnethost, floodhost)) { /* New... */
512 segfault 1.1 strcpy(lasttelnethost, floodhost);
513     lasttelnettime = now;
514     lasttelnets = 0;
515     return 0;
516     }
517     if (lasttelnettime < now - flood_telnet_time) {
518 fabian 1.22 /* Flood timer expired, reset it */
519 segfault 1.1 lasttelnettime = now;
520     lasttelnets = 0;
521     return 0;
522     }
523     lasttelnets++;
524 fabian 1.22 if (lasttelnets >= flood_telnet_thr) { /* FLOOD! */
525     /* Reset counters */
526 segfault 1.1 lasttelnets = 0;
527     lasttelnettime = 0;
528     lasttelnethost[0] = 0;
529 ite 1.49 putlog(LOG_MISC, "*", _("Telnet connection flood from %s! Placing on ignore!"), floodhost);
530 segfault 1.1 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 drummer 1.48 char ip[ADDRLEN];
540 segfault 1.1 unsigned short port;
541 drummer 1.48 int j, sock;
542 fabian 1.3 char s[UHOSTLEN + 1];
543 segfault 1.1
544 drummer 1.48 sock = answer(dcc[idx].sock, s, ip, &port, 0);
545 segfault 1.1 if (dcc_total + 1 > max_dcc) {
546 drummer 1.48 if (sock != -1) {
547     dprintf(-sock, "Sorry, too many connections already.\r\n");
548     killsock(sock);
549 segfault 1.1 }
550     return;
551     }
552     while ((sock == -1) && (errno == EAGAIN))
553 drummer 1.48 sock = answer(sock, s, ip, &port, 0);
554 segfault 1.1 if (sock < 0) {
555     neterror(s);
556 ite 1.49 putlog(LOG_MISC, "*", _("Failed TELNET incoming (%s)"), s);
557 segfault 1.1 return;
558     }
559 fabian 1.39 /* Buffer data received on this socket. */
560     sockoptions(sock, EGG_OPTION_SET, SOCK_BUFFER);
561    
562 guppy 1.50 if ((port < 1024) || (port > 65535)) {
563 ite 1.49 putlog(LOG_BOTS, "*", _("Refused %s/%d (bad src port)"), s, port);
564 segfault 1.1 killsock(sock);
565     return;
566     }
567 ite 1.69
568 drummer 1.48 j = strlen(ip);
569 fabian 1.3 i = new_dcc(&DCC_DNSWAIT, sizeof(struct dns_info));
570     dcc[i].sock = sock;
571 drummer 1.48 strcpy(dcc[i].addr, ip);
572 fabian 1.3 dcc[i].port = port;
573     dcc[i].timeval = now;
574     strcpy(dcc[i].nick, "*");
575 tothwolf 1.58 dcc[i].u.dns->host = calloc(1, j + 1);
576 drummer 1.48 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 fabian 1.32 dcc[i].u.dns->dns_success = dcc_telnet_hostresolved;
579     dcc[i].u.dns->dns_failure = dcc_telnet_hostresolved;
580 fabian 1.3 dcc[i].u.dns->dns_type = RES_HOSTBYIP;
581     dcc[i].u.dns->ibuf = dcc[idx].sock;
582 fabian 1.5 dcc[i].u.dns->type = &DCC_IDENTWAIT;
583 fabian 1.16 dcc_dnshostbyip(ip);
584 fabian 1.3 }
585    
586     static void dcc_telnet_hostresolved(int i)
587     {
588     int idx;
589     int j = 0, sock;
590 fabian 1.6 char s[UHOSTLEN], s2[UHOSTLEN + 20];
591 fabian 1.3
592 ite 1.76 strlcpy(dcc[i].host, dcc[i].u.dns->host, UHOSTLEN);
593 drummer 1.48 debug2("|DCC| dcc_telnet_hostresolved: idx: %d host: %s", i, dcc[i].host);
594 fabian 1.3
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 ite 1.64 putlog(LOG_BOTS, "*", _("Lost listening socket while resolving %s"),
602 fabian 1.3 dcc[i].host);
603     killsock(dcc[i].sock);
604     lostdcc(i);
605     return;
606     }
607 segfault 1.1 if (dcc[idx].host[0] == '@') {
608 fabian 1.22 /* Restrict by hostname */
609 fabian 1.3 if (!wild_match(dcc[idx].host + 1, dcc[i].host)) {
610 ite 1.49 putlog(LOG_BOTS, "*", _("Refused %s (bad hostname)"), s);
611 fabian 1.3 killsock(dcc[i].sock);
612     lostdcc(i);
613 segfault 1.1 return;
614     }
615     }
616 fabian 1.36 sprintf(s2, "-telnet!telnet@%s", dcc[i].host);
617 segfault 1.1 if (match_ignore(s2) || detect_telnet_flood(s2)) {
618 fabian 1.3 killsock(dcc[i].sock);
619     lostdcc(i);
620 segfault 1.1 return;
621     }
622 fabian 1.3
623     changeover_dcc(i, &DCC_IDENTWAIT, 0);
624 segfault 1.1 dcc[i].timeval = now;
625 fabian 1.9 dcc[i].u.ident_sock = dcc[idx].sock;
626 drummer 1.48 sock = open_telnet(dcc[i].addr, 113);
627 ite 1.49 putlog(LOG_MISC, "*", _("Telnet connection: %s/%d"), dcc[i].host, dcc[i].port);
628 segfault 1.1 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 ite 1.49 putlog(LOG_MISC, "*", _("Ident failed for %s: %s"), dcc[i].host, s);
643 segfault 1.1 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 drummer 1.48 strcpy(dcc[j].addr, dcc[i].addr);
650 segfault 1.1 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 ite 1.49 putlog(LOG_MISC, "*", _("(!) Listening port %d abruptly died."),
660 segfault 1.1 dcc[idx].port);
661     killsock(dcc[idx].sock);
662     lostdcc(idx);
663     }
664    
665     static void display_telnet(int idx, char *buf)
666     {
667 fabian 1.17 sprintf(buf, "lstn %d%s", dcc[idx].port,
668     (dcc[idx].status & LSTN_PUBLIC) ? " pub" : "");
669 segfault 1.1 }
670    
671     struct dcc_table DCC_TELNET =
672     {
673     "TELNET",
674     DCT_LISTEN,
675     eof_dcc_telnet,
676     dcc_telnet,
677 fabian 1.22 NULL,
678     NULL,
679 segfault 1.1 display_telnet,
680 fabian 1.22 NULL,
681     NULL
682 segfault 1.1 };
683    
684     static void dcc_telnet_id(int idx, char *buf, int atr)
685     {
686     int ok = 0;
687 fabian 1.9 struct flag_record fr = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0};
688 segfault 1.1
689     strip_telnet(dcc[idx].sock, buf, &atr);
690     buf[HANDLEN] = 0;
691 fabian 1.22 /* Toss out bad nicknames */
692 segfault 1.1 if ((dcc[idx].nick[0] != '@') && (!wild_match(dcc[idx].nick, buf))) {
693 fabian 1.31 dprintf(idx, "Sorry, that nickname format is invalid.\n");
694 ite 1.49 putlog(LOG_BOTS, "*", _("Refused %s (bad nick)"), dcc[idx].host);
695 segfault 1.1 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 fabian 1.22 /* Make sure users-only/bots-only connects are honored */
702 segfault 1.1 if ((dcc[idx].status & STAT_BOTONLY) && !glob_bot(fr)) {
703 fabian 1.31 dprintf(idx, "This telnet port is for bots only.\n");
704 ite 1.49 putlog(LOG_BOTS, "*", _("Refused %s (non-bot)"), dcc[idx].host);
705 segfault 1.1 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 ite 1.49 putlog(LOG_BOTS, "*", _("Refused %s (non-user)"), dcc[idx].host);
712 segfault 1.1 killsock(dcc[idx].sock);
713     lostdcc(idx);
714     return;
715     }
716     dcc[idx].status &= ~(STAT_BOTONLY | STAT_USRONLY);
717 guppy 1.65 if (!strcasecmp(buf, "NEW") && (learn_users || make_userfile)) {
718 segfault 1.1 dcc[idx].type = &DCC_TELNET_NEW;
719     dcc[idx].timeval = now;
720 fabian 1.31 dprintf(idx, "\n");
721 wcc 1.97 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 ite 1.49 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 fabian 1.31 dprintf(idx, "\nEnter the nickname you would like to use.\n");
724 segfault 1.1 return;
725     }
726 fabian 1.33 if (!ok && (glob_party(fr) || glob_bot(fr)))
727 segfault 1.1 ok = 1;
728    
729     if (!ok) {
730 fabian 1.31 dprintf(idx, "You don't have access.\n");
731 ite 1.49 putlog(LOG_BOTS, "*", _("Refused %s (invalid handle: %s)"), dcc[idx].host, buf);
732 segfault 1.1 killsock(dcc[idx].sock);
733     lostdcc(idx);
734     return;
735     }
736 fabian 1.10 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 fabian 1.22 /* No password set? */
748 segfault 1.1 if (u_pass_match(dcc[idx].user, "-")) {
749 fabian 1.31 dprintf(idx, "Can't telnet until you have a password set.\n");
750 ite 1.49 putlog(LOG_MISC, "*", _("Refused [%s]%s (no password)"), dcc[idx].nick, dcc[idx].host);
751 segfault 1.1 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 guppy 1.66 else if (glob_party(fr)) {
761 segfault 1.1 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 tothwolf 1.58 dcc[idx].u.file = calloc(1, sizeof(struct file_info));
771 segfault 1.1 dcc[idx].u.file->chat = ci;
772     }
773 fabian 1.23
774 fabian 1.30 /* Turn off remote telnet echo (send IAC WILL ECHO). */
775 ite 1.49 dprintf(idx, "\n%s" TLN_IAC_C TLN_WILL_C TLN_ECHO_C "\n", _("Enter your password."));
776 segfault 1.1 }
777    
778     static void eof_dcc_telnet_id(int idx)
779     {
780 ite 1.49 putlog(LOG_MISC, "*", _("Lost telnet connection to %s/%d"), dcc[idx].host,
781 segfault 1.1 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 ite 1.49 putlog(LOG_MISC, "*", _("Ident timeout on telnet: %s"), dcc[idx].host);
790 segfault 1.1 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 fabian 1.22 dprintf(idx, "\nYou can't start your nick with the character '%c'\n",
828     buf[0]);
829 segfault 1.1 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 wcc 1.97 } else if (!strcasecmp(buf, myname)) {
835 segfault 1.1 dprintf(idx, "Sorry, can't use my name for a nick.\n");
836     } else {
837 guppy 1.72 strcpy(dcc[idx].nick, buf);
838 segfault 1.1 if (make_userfile)
839 fabian 1.36 userlist = adduser(userlist, buf, "-telnet!*@*", "-",
840 segfault 1.1 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 fabian 1.36 simple_sprintf(work, "-telnet!%s@%s", dcc[idx].host, p);
851 segfault 1.1 else
852 fabian 1.36 simple_sprintf(work, "-telnet!%s@*%s", dcc[idx].host, r);
853 segfault 1.1 *q = '@';
854     } else
855 fabian 1.36 simple_sprintf(work, "-telnet!*@*%s", dcc[idx].host);
856 segfault 1.1 userlist = adduser(userlist, buf, work, "-",
857     sanity_check(USER_PARTY | default_flags));
858     }
859 stdarg 1.93 //reaffirm_owners();
860 segfault 1.1 dcc[idx].status = STAT_ECHO | STAT_TELNET;
861 fabian 1.22 dcc[idx].type = &DCC_CHAT; /* Just so next line will work */
862 segfault 1.1 dcc[idx].user = get_user_by_handle(userlist, buf);
863 stdarg 1.93 //check_dcc_attrs(dcc[idx].user, USER_PARTY | default_flags);
864 segfault 1.1 dcc[idx].type = &DCC_TELNET_PW;
865     if (make_userfile) {
866 ite 1.64 dprintf(idx, _("\nYOU ARE THE MASTER/OWNER ON THIS BOT NOW\n"));
867 ite 1.49 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 segfault 1.1 make_userfile = 0;
870     write_userfile(-1);
871 wcc 1.97 add_note(buf, myname, _("Welcome to Eggdrop! :)"), -1, 0);
872 segfault 1.1 }
873 ite 1.64 dprintf(idx, _("\nOkay, now choose and enter a password:\n"));
874     dprintf(idx, _("(Only the first 15 letters are significant.)\n"));
875 segfault 1.1 }
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 ite 1.49 putlog(LOG_MISC, "*", _("New user via telnet: [%s]%s/%d"), dcc[idx].nick, dcc[idx].host,
900 fabian 1.7 dcc[idx].port);
901 segfault 1.1 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 wcc 1.97 add_note(s2, myname, s, -1, 0);
910 segfault 1.1 splitc(s2, s1, ',');
911     }
912     rmspace(s1);
913 wcc 1.97 add_note(s1, myname, s, -1, 0);
914 segfault 1.1 }
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 wcc 1.97 dprintf(idx, "You now have an account on %s...\n\n\n", myname);
919 segfault 1.1 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 ite 1.49 putlog(LOG_MISC, "*", _("Lost new telnet user (%s/%d)"), dcc[idx].host, dcc[idx].port);
927 segfault 1.1 killsock(dcc[idx].sock);
928     lostdcc(idx);
929     }
930    
931     static void eof_dcc_telnet_pw(int idx)
932     {
933 ite 1.49 putlog(LOG_MISC, "*", _("Lost new telnet user %s (%s/%d)"), dcc[idx].nick, dcc[idx].host,
934 fabian 1.7 dcc[idx].port);
935 segfault 1.1 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 ite 1.49 putlog(LOG_MISC, "*", _("Timeout on new telnet user: %s/%d"), dcc[idx].host,
944 segfault 1.1 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 ite 1.49 putlog(LOG_MISC, "*", _("Timeout on new telnet user: [%s]%s/%d"), dcc[idx].nick,
953 fabian 1.7 dcc[idx].host, dcc[idx].port);
954 segfault 1.1 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 fabian 1.37 long oldsock;
997 stdarg 1.86 script_callback_t *callback;
998 segfault 1.1
999     strip_telnet(dcc[idx].sock, buf, &len);
1000 guppy 1.41 if (!len)
1001 segfault 1.1 return;
1002 fabian 1.37
1003 stdarg 1.86 callback = dcc[idx].u.script->callback;
1004 segfault 1.1 dcc[idx].timeval = now;
1005 fabian 1.37 oldsock = dcc[idx].sock; /* Remember the socket number. */
1006 stdarg 1.86
1007     /* Execute the script callback. */
1008     if (callback->callback(callback, idx, buf)) {
1009 fabian 1.37 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 stdarg 1.55 if (idx > max_dcc || dcc[idx].sock != oldsock)
1014 fabian 1.37 return;
1015    
1016     old_other = dcc[idx].u.script->u.other;
1017 segfault 1.1 dcc[idx].type = dcc[idx].u.script->type;
1018 tothwolf 1.56 free(dcc[idx].u.script);
1019 fabian 1.37 dcc[idx].u.other = old_other;
1020 segfault 1.1 if (dcc[idx].type == &DCC_SOCKET) {
1021 fabian 1.22 /* Kill the whole thing off */
1022 segfault 1.1 killsock(dcc[idx].sock);
1023     lostdcc(idx);
1024     return;
1025     }
1026 stdarg 1.86
1027     /* If we're not closing the idx, we have to delete the callback manually. */
1028     callback->del(callback);
1029    
1030 segfault 1.1 if (dcc[idx].type == &DCC_CHAT) {
1031     if (dcc[idx].u.chat->channel >= 0) {
1032 ite 1.49 chanout_but(-1, dcc[idx].u.chat->channel, _("*** %s has joined the party line.\n"), dcc[idx].nick);
1033 segfault 1.1 }
1034     }
1035     }
1036     }
1037    
1038     static void eof_dcc_script(int idx)
1039     {
1040     void *old;
1041     int oldflags;
1042 stdarg 1.86 script_callback_t *callback;
1043 segfault 1.1
1044     /* This will stop a killdcc from working, incase the script tries
1045 fabian 1.22 * to kill it's controlling socket while handling an EOF <cybah>
1046     */
1047 segfault 1.1 oldflags = dcc[idx].type->flags;
1048     dcc[idx].type->flags &= ~(DCT_VALIDIDX);
1049 stdarg 1.86
1050 fabian 1.22 /* Tell the script they're gone: */
1051 stdarg 1.86 callback = dcc[idx].u.script->callback;
1052     callback->callback(callback, idx, "");
1053     callback->del(callback);
1054    
1055 fabian 1.22 /* Restore the flags */
1056 segfault 1.1 dcc[idx].type->flags = oldflags;
1057     old = dcc[idx].u.script->u.other;
1058     dcc[idx].type = dcc[idx].u.script->type;
1059 tothwolf 1.56 free(dcc[idx].u.script);
1060 segfault 1.1 dcc[idx].u.other = old;
1061 fabian 1.22 /* Then let it fall thru to the real one */
1062 segfault 1.1 if (dcc[idx].type && dcc[idx].type->eof)
1063     dcc[idx].type->eof(idx);
1064     else {
1065 ite 1.49 putlog(LOG_MISC, "*", _("*** ATTENTION: DEAD SOCKET (%d) OF TYPE %s UNTRAPPED"), dcc[idx].sock,
1066 fabian 1.7 dcc[idx].type->name);
1067 segfault 1.1 killsock(dcc[idx].sock);
1068     lostdcc(idx);
1069     }
1070     }
1071    
1072     static void display_dcc_script(int idx, char *buf)
1073     {
1074 stdarg 1.86 sprintf(buf, "scri %s", dcc[idx].u.script->callback->name);
1075 segfault 1.1 }
1076    
1077     static void kill_dcc_script(int idx, void *x)
1078     {
1079 stdarg 1.86 script_callback_t *callback;
1080     struct script_info *p = (struct script_info *) x;
1081 segfault 1.1
1082 stdarg 1.86 callback = p->callback;
1083     callback->del(callback);
1084 segfault 1.1 if (p->type && p->u.other)
1085     p->type->kill(idx, p->u.other);
1086 tothwolf 1.56 free(p);
1087 segfault 1.1 }
1088    
1089     static void out_dcc_script(int idx, char *buf, void *x)
1090     {
1091 stdarg 1.86 struct script_info *p = (struct script_info *) x;
1092 segfault 1.1
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 fabian 1.22 NULL,
1106     NULL,
1107 segfault 1.1 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 fabian 1.22 NULL,
1134     NULL,
1135 segfault 1.1 display_dcc_socket,
1136 fabian 1.22 NULL,
1137     NULL
1138 segfault 1.1 };
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 fabian 1.22 NULL,
1150 segfault 1.1 dcc_socket,
1151 fabian 1.22 NULL,
1152     NULL,
1153 segfault 1.1 display_dcc_lost,
1154 fabian 1.22 NULL,
1155     NULL
1156 segfault 1.1 };
1157    
1158     void dcc_identwait(int idx, char *buf, int len)
1159     {
1160 fabian 1.22 /* Ignore anything now */
1161 segfault 1.1 }
1162    
1163     void eof_dcc_identwait(int idx)
1164     {
1165     int i;
1166    
1167 ite 1.49 putlog(LOG_MISC, "*", _("Lost connection while identing [%s/%d]"), dcc[idx].host, dcc[idx].port);
1168 segfault 1.1 for (i = 0; i < dcc_total; i++)
1169     if ((dcc[i].type == &DCC_IDENT) &&
1170     (dcc[i].u.ident_sock == dcc[idx].sock)) {
1171 fabian 1.22 killsock(dcc[i].sock); /* Cleanup ident socket */
1172 segfault 1.1 dcc[i].u.other = 0;
1173 fabian 1.2 lostdcc(i);
1174     break;
1175 segfault 1.1 }
1176 fabian 1.22 killsock(dcc[idx].sock); /* Cleanup waiting socket */
1177 segfault 1.1 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 fabian 1.22 NULL,
1193     NULL,
1194 segfault 1.1 display_dcc_identwait,
1195 fabian 1.22 NULL,
1196     NULL
1197 segfault 1.1 };
1198    
1199     void dcc_ident(int idx, char *buf, int len)
1200     {
1201     char response[512], uid[512], buf1[UHOSTLEN];
1202 fabian 1.15 int i;
1203 segfault 1.1
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 fabian 1.15 int i;
1227 segfault 1.1
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 ite 1.49 putlog(LOG_MISC, "*", _("Timeout/EOF ident connection"));
1232 segfault 1.1 simple_sprintf(buf, "telnet@%s", dcc[idx].host);
1233     dcc_telnet_got_ident(i, buf);
1234     }
1235 fabian 1.15 killsock(dcc[idx].sock);
1236     dcc[idx].u.other = 0;
1237     lostdcc(idx);
1238 segfault 1.1 }
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 stdarg 1.83 &ident_timeout,
1252 segfault 1.1 eof_dcc_ident,
1253     display_dcc_ident,
1254 fabian 1.22 NULL,
1255     NULL
1256 segfault 1.1 };
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 fabian 1.2 if (dcc_total == idx) {
1269 ite 1.49 putlog(LOG_MISC, "*", _("Lost ident wait telnet socket!!"));
1270 fabian 1.2 killsock(dcc[i].sock);
1271     lostdcc(i);
1272     return;
1273     }
1274 ite 1.76 strlcpy(dcc[i].host, host, UHOSTLEN);
1275 tothwolf 1.60 snprintf(x, sizeof x, "-telnet!%s", dcc[i].host);
1276 segfault 1.1 if (protect_telnet && !make_userfile) {
1277     struct userrec *u;
1278     int ok = 1;
1279    
1280     u = get_user_by_host(x);
1281 fabian 1.22 /* Not a user or +p & require p OR +o */
1282 segfault 1.1 if (!u)
1283     ok = 0;
1284 guppy 1.66 else if (!(u->flags & USER_PARTY))
1285 segfault 1.1 ok = 0;
1286 fabian 1.17 if (!ok && (dcc[idx].status & LSTN_PUBLIC))
1287 segfault 1.1 ok = 1;
1288     if (!ok) {
1289 ite 1.49 putlog(LOG_MISC, "*", _("Denied telnet: %s, No Access"), dcc[i].host);
1290 segfault 1.1 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 fabian 1.22 /* Script? */
1301 segfault 1.1 if (!strcmp(dcc[idx].nick, "(script)")) {
1302     dcc[i].type = &DCC_SOCKET;
1303     dcc[i].u.other = NULL;
1304     strcpy(dcc[i].nick, "*");
1305 stdarg 1.94 //check_bind_listen(dcc[idx].host, dcc[i].sock);
1306 segfault 1.1 return;
1307     }
1308 fabian 1.39 /* 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 segfault 1.1 dcc[i].type = &DCC_TELNET_ID;
1313 tothwolf 1.58 dcc[i].u.chat = calloc(1, sizeof(struct chat_info));
1314 segfault 1.1
1315 fabian 1.22 /* Copy acceptable-nick/host mask */
1316 segfault 1.1 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 fabian 1.22 /* Copy acceptable-nick/host mask */
1322 ite 1.76 strlcpy(dcc[i].nick, dcc[idx].host, HANDLEN);
1323 segfault 1.1 dcc[i].timeval = now;
1324     strcpy(dcc[i].u.chat->con_chan, chanset ? chanset->name : "*");
1325 guppy 1.51
1326     /* Displays a telnet banner if the file exists. */
1327     show_telnet_banner(i);
1328    
1329 guppy 1.67 dprintf(i, "\n\n");
1330     sub_lang(i, _("%B (%E)\n\nPlease enter your nickname.\n"));
1331    
1332 guppy 1.65 if (learn_users)
1333 fabian 1.31 dprintf(i, "(If you are new, enter 'NEW' here.)\n");
1334 stdarg 1.80 }
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 ite 1.82 for (i = dcc_total; i > 0; --i) {
1345 stdarg 1.80 if (dcc[i].type) break;
1346     }
1347     if (newval < i+1) newval = i+1;
1348     dcc_total = newval;
1349     }
1350    
1351 stdarg 1.81 /* Use init_dcc_max to resize the array. */
1352     init_dcc_max(newval);
1353 stdarg 1.80
1354     return(0);
1355 segfault 1.1 }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23