/[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.8 - (hide annotations) (download) (as text)
Wed Jul 31 00:20:46 2013 UTC (6 years, 2 months ago) by thommey
Branch: gettext
Changes since 1.6.2.7: +21 -21 lines
File MIME type: text/x-chdr
apply two patches by robby

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