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

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

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


Revision 1.6.2.2 - (hide annotations) (download) (as text)
Wed Jan 12 13:54:00 2011 UTC (8 years, 6 months ago) by pseudo
Branch: gettext
Changes since 1.6.2.1: +2 -2 lines
File MIME type: text/x-chdr
Removed memcpy(), memset() and strftime() compatibility replacements.

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