/[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.7 - (hide annotations) (download) (as text)
Tue Nov 23 16:36:23 2010 UTC (10 years, 11 months ago) by pseudo
Branch: MAIN
Changes since 1.6: +52 -19 lines
File MIME type: text/x-chdr
Fixed a problem with sharing causing starttls to fail.
Moved STARTTLS early in the bot link process and synchronized the handshake.
Made it possible for ssl handshakes to complete even without data to be sent on the channel.
Fixed an ancient bug resulting in sending uninitialized strings when sharing bot addresses.
Enabled userfile sending over ssl.

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.7 * $Id: dcc.c,v 1.6 2010/10/31 14:40:38 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 #ifdef TLS
47 pseudo 1.7 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 pseudo 1.7
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     putlog(LOG_BOTS, "*", DCC_REJECT, dcc[idx].nick);
170     dprintf(idx, "bye %s\n", "rejected");
171     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     putlog(LOG_BOTS, "*", "Non-matching handle lengths with %s, they use 9 "
215     "characters.", dcc[idx].nick);
216     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     putlog(LOG_BOTS, "*", "Non-matching handle lengths with %s, they use %d "
231     "characters.", dcc[idx].nick, l);
232     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     putlog(LOG_BOTS, "*", DCC_LINKED, dcc[idx].nick);
244     chatout("*** Linked to %s\n", dcc[idx].nick);
245     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     putlog(LOG_BOTS, "*", DCC_LINKFAIL, dcc[idx].nick);
269     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     egg_snprintf(x, sizeof x,
306     "Unlinked %s (restructure) (lost %d bot%s and %d user%s)",
307     dcc[i].nick, bots, (bots != 1) ? "s" : "",
308     users, (users != 1) ? "s" : "");
309     chatout("*** %s\n", x);
310     botnet_send_unlinked(i, dcc[i].nick, x);
311     dprintf(i, "bye %s\n", "restructure");
312     killsock(dcc[i].sock);
313     lostdcc(i);
314     }
315     }
316     }
317     dcc[idx].type = &DCC_BOT_NEW;
318     dcc[idx].u.bot->numver = 0;
319    
320     /* Don't send our password here, just the username. The code later on
321     * will determine if the password needs to be sent in cleartext or if
322     * we can send an MD5 digest. <cybah>
323     */
324     dprintf(idx, "%s\n", botnetnick);
325     return;
326     }
327    
328     /* This function generates a digest by combining 'challenge' with
329     * 'password' and then sends it to the other bot. <Cybah>
330     */
331     static void dcc_bot_digest(int idx, char *challenge, char *password)
332     {
333     MD5_CTX md5context;
334     char digest_string[33]; /* 32 for digest in hex + null */
335     unsigned char digest[16];
336     int i;
337    
338     MD5_Init(&md5context);
339     MD5_Update(&md5context, (unsigned char *) challenge, strlen(challenge));
340     MD5_Update(&md5context, (unsigned char *) password, strlen(password));
341     MD5_Final(digest, &md5context);
342    
343     for (i = 0; i < 16; i++)
344     sprintf(digest_string + (i * 2), "%.2x", digest[i]);
345     dprintf(idx, "digest %s\n", digest_string);
346     putlog(LOG_BOTS, "*", "Received challenge from %s... sending response ...",
347     dcc[idx].nick);
348     }
349    
350     static void dcc_bot_new(int idx, char *buf, int x)
351     {
352     struct userrec *u = get_user_by_handle(userlist, dcc[idx].nick);
353     char *code;
354    
355     code = newsplit(&buf);
356     if (!egg_strcasecmp(code, "*hello!"))
357     greet_new_bot(idx);
358     else if (!egg_strcasecmp(code, "version") || !egg_strcasecmp(code, "v"))
359     bot_version(idx, buf);
360     else if (!egg_strcasecmp(code, "badpass"))
361     /* We entered the wrong password */
362     putlog(LOG_BOTS, "*", DCC_BADPASS, dcc[idx].nick);
363     else if (!egg_strcasecmp(code, "passreq")) {
364     char *pass = get_user(&USERENTRY_PASS, u);
365    
366 pseudo 1.7 #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     putlog(LOG_BOTS, "*", DCC_PASSREQ, dcc[idx].nick);
381     dprintf(idx, "-\n");
382     } else {
383     /* Determine if the other end supports an MD5 digest instead of a
384     * cleartext password. <Cybah>
385     */
386     if (buf && buf[0] && strchr(buf, '<') && strchr(buf + 1, '>'))
387     dcc_bot_digest(idx, buf, pass);
388     else
389     dprintf(idx, "%s\n", pass);
390     }
391 pseudo 1.7 #ifdef TLS
392     } else if (!egg_strcasecmp(code, "starttls") && !dcc[idx].ssl) {
393     /* Mark the connection for secure communication, but don't switch yet.
394     * The hub has to send a plaintext passreq right after the starttls command
395     * and if we switch now, we'll break the handshake. Instead, we'll only
396     * send a confirmation to the peer and wait for the passreq.
397     */
398     putlog(LOG_BOTS, "*", "Got STARTTLS from %s. Replying...", dcc[idx].nick);
399     dcc[idx].status |= STAT_STARTTLS;
400     /* needs to have space to be distinguished from a plaintext password */
401     dprintf(idx, "starttls -\n");
402     #endif
403 simple 1.1 } else if (!egg_strcasecmp(code, "error"))
404     putlog(LOG_BOTS, "*", DCC_LINKERROR, dcc[idx].nick, buf);
405     /* Ignore otherwise */
406     }
407    
408     static void eof_dcc_bot_new(int idx)
409     {
410     putlog(LOG_BOTS, "*", DCC_LOSTBOT, dcc[idx].nick, dcc[idx].port);
411     killsock(dcc[idx].sock);
412     lostdcc(idx);
413     }
414    
415     static void timeout_dcc_bot_new(int idx)
416     {
417     putlog(LOG_BOTS, "*", DCC_TIMEOUT, dcc[idx].nick,
418     dcc[idx].host, dcc[idx].port);
419     killsock(dcc[idx].sock);
420     lostdcc(idx);
421     }
422    
423     static void display_dcc_bot_new(int idx, char *buf)
424     {
425     long tv;
426    
427     tv = now - dcc[idx].timeval;
428     sprintf(buf, "bot* waited %lis", tv);
429     }
430    
431     static int expmem_dcc_bot_(void *x)
432     {
433     return sizeof(struct bot_info);
434     }
435    
436     static void free_dcc_bot_(int n, void *x)
437     {
438     if (dcc[n].type == &DCC_BOT) {
439     unvia(n, findbot(dcc[n].nick));
440     rembot(dcc[n].nick);
441     }
442     nfree(x);
443     }
444    
445     struct dcc_table DCC_BOT_NEW = {
446     "BOT_NEW",
447     0,
448     eof_dcc_bot_new,
449     dcc_bot_new,
450     &bot_timeout,
451     timeout_dcc_bot_new,
452     display_dcc_bot_new,
453     expmem_dcc_bot_,
454     free_dcc_bot_,
455     NULL
456     };
457    
458     /* Hash function for tandem bot commands */
459     extern botcmd_t C_bot[];
460    
461     static void dcc_bot(int idx, char *code, int i)
462     {
463     char *msg;
464     int f;
465    
466     if (raw_log) {
467 pseudo 1.4 if (!strcmp(code, "s"))
468 simple 1.1 putlog(LOG_BOTSHARE, "*", "{%s} %s", dcc[idx].nick, code + 2);
469     else
470     putlog(LOG_BOTNET, "*", "[%s] %s", dcc[idx].nick, code);
471     }
472     msg = strchr(code, ' ');
473     if (msg) {
474     *msg = 0;
475     msg++;
476     } else
477     msg = "";
478     for (f = i = 0; C_bot[i].name && !f; i++) {
479     int y = egg_strcasecmp(code, C_bot[i].name);
480    
481     if (!y) {
482     /* Found a match */
483     (C_bot[i].func) (idx, msg);
484     f = 1;
485     } else if (y < 0)
486     return;
487     }
488     }
489    
490     static void eof_dcc_bot(int idx)
491     {
492     char x[1024];
493     int bots, users;
494    
495     bots = bots_in_subtree(findbot(dcc[idx].nick));
496     users = users_in_subtree(findbot(dcc[idx].nick));
497     egg_snprintf(x, sizeof x,
498     "Lost bot: %s (lost %d bot%s and %d user%s)",
499     dcc[idx].nick, bots, (bots != 1) ? "s" : "", users,
500     (users != 1) ? "s" : "");
501     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     putlog(LOG_BOTS, "*", "Response (password hash) from %s incorrect",
593     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     /* Check for MD5 digest from remote _bot_. <cybah> */
608 pseudo 1.7 #ifdef TLS
609     if ((atr & USER_BOT) && !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     #endif
619 simple 1.1 if ((atr & USER_BOT) && !egg_strncasecmp(buf, "digest ", 7)) {
620     if (dcc_bot_check_digest(idx, buf + 7)) {
621     nfree(dcc[idx].u.chat);
622     dcc[idx].type = &DCC_BOT_NEW;
623     dcc[idx].u.bot = get_data_ptr(sizeof(struct bot_info));
624     dcc[idx].status = STAT_CALLED;
625     dprintf(idx, "*hello!\n");
626     greet_new_bot(idx);
627     return;
628     } else {
629     /* Invalid password/digest */
630     dprintf(idx, "badpass\n");
631     putlog(LOG_MISC, "*", DCC_BADLOGIN, dcc[idx].nick, dcc[idx].host,
632     dcc[idx].port);
633     killsock(dcc[idx].sock);
634     lostdcc(idx);
635     return;
636     }
637     }
638    
639 pseudo 1.4 #ifdef TLS
640     /* Skip checking the password if the user is already identified by
641     * fingerprint.
642     */
643     if (dcc[idx].status & STAT_FPRINT || u_pass_match(dcc[idx].user, buf)) {
644     #else
645 simple 1.1 if (u_pass_match(dcc[idx].user, buf)) {
646 pseudo 1.4 #endif
647 simple 1.1 if (atr & USER_BOT) {
648     nfree(dcc[idx].u.chat);
649     dcc[idx].type = &DCC_BOT_NEW;
650     dcc[idx].u.bot = get_data_ptr(sizeof(struct bot_info));
651    
652     dcc[idx].status = STAT_CALLED;
653     dprintf(idx, "*hello!\n");
654     greet_new_bot(idx);
655     } else {
656     /* Log entry for successful login -slennox 3/28/1999 */
657     putlog(LOG_MISC, "*", DCC_LOGGEDIN, dcc[idx].nick,
658     dcc[idx].host, dcc[idx].port);
659     if (dcc[idx].u.chat->away) {
660     nfree(dcc[idx].u.chat->away);
661     dcc[idx].u.chat->away = NULL;
662     }
663     dcc[idx].type = &DCC_CHAT;
664     dcc[idx].status &= ~STAT_CHAT;
665     dcc[idx].u.chat->con_flags = (atr & USER_MASTER) ? conmask : 0;
666     dcc[idx].u.chat->channel = -2;
667     /* Turn echo back on for telnet sessions (send IAC WON'T ECHO). */
668     if (dcc[idx].status & STAT_TELNET)
669     tputs(dcc[idx].sock, TLN_IAC_C TLN_WONT_C TLN_ECHO_C "\n", 4);
670     dcc_chatter(idx);
671     }
672     } else {
673     if (atr & USER_BOT)
674     dprintf(idx, "badpass\n");
675     else
676     dprintf(idx, DCC_HOUSTON);
677     putlog(LOG_MISC, "*", DCC_BADLOGIN, dcc[idx].nick,
678     dcc[idx].host, dcc[idx].port);
679     if (dcc[idx].u.chat->away) { /* su from a dumb user */
680     /* Turn echo back on for telnet sessions (send IAC WON'T ECHO). */
681     if (dcc[idx].status & STAT_TELNET)
682     tputs(dcc[idx].sock, TLN_IAC_C TLN_WONT_C TLN_ECHO_C "\n", 4);
683     dcc[idx].user = get_user_by_handle(userlist, dcc[idx].u.chat->away);
684     strcpy(dcc[idx].nick, dcc[idx].u.chat->away);
685     nfree(dcc[idx].u.chat->away);
686     nfree(dcc[idx].u.chat->su_nick);
687     dcc[idx].u.chat->away = NULL;
688     dcc[idx].u.chat->su_nick = NULL;
689     dcc[idx].type = &DCC_CHAT;
690     if (dcc[idx].u.chat->channel < GLOBAL_CHANS)
691     botnet_send_join_idx(idx, -1);
692     chanout_but(-1, dcc[idx].u.chat->channel, DCC_JOIN, dcc[idx].nick);
693     } else {
694     killsock(dcc[idx].sock);
695     lostdcc(idx);
696     }
697     }
698     }
699    
700     static void eof_dcc_general(int idx)
701     {
702     putlog(LOG_MISC, "*", DCC_LOSTDCC, dcc[idx].nick,
703     dcc[idx].host, dcc[idx].port);
704     killsock(dcc[idx].sock);
705     lostdcc(idx);
706     }
707    
708     static void tout_dcc_chat_pass(int idx)
709     {
710     dprintf(idx, "Timeout.\n");
711     putlog(LOG_MISC, "*", DCC_PWDTIMEOUT, dcc[idx].nick, dcc[idx].host);
712     killsock(dcc[idx].sock);
713     lostdcc(idx);
714     }
715    
716     static void display_dcc_chat_pass(int idx, char *buf)
717     {
718     long tv;
719    
720     tv = now - dcc[idx].timeval;
721     sprintf(buf, "pass waited %lis", tv);
722     }
723    
724     static int expmem_dcc_general(void *x)
725     {
726     register struct chat_info *p = (struct chat_info *) x;
727     int tot = sizeof(struct chat_info);
728    
729     if (p->away)
730     tot += strlen(p->away) + 1;
731     if (p->buffer) {
732     struct msgq *q = p->buffer;
733    
734     while (q) {
735     tot += sizeof(struct list_type);
736    
737     tot += q->len + 1;
738     q = q->next;
739     }
740     }
741     if (p->su_nick)
742     tot += strlen(p->su_nick) + 1;
743     return tot;
744     }
745    
746     static void kill_dcc_general(int idx, void *x)
747     {
748     register struct chat_info *p = (struct chat_info *) x;
749    
750     if (p) {
751     if (p->buffer) {
752     struct msgq *r, *q;
753    
754     for (r = dcc[idx].u.chat->buffer; r; r = q) {
755     q = r->next;
756     nfree(r->msg);
757     nfree(r);
758     }
759     }
760     if (p->away) {
761     nfree(p->away);
762     }
763     nfree(p);
764     }
765     }
766    
767     /* Remove the color control codes that mIRC,pIRCh etc use to make
768     * their client seem so fecking cool! (Sorry, Khaled, you are a nice
769     * guy, but when you added this feature you forced people to either
770     * use your *SHAREWARE* client or face screenfulls of crap!)
771     */
772     void strip_mirc_codes(int flags, char *text)
773     {
774     char *dd = text;
775    
776     while (*text) {
777     switch (*text) {
778     case 2: /* Bold text */
779     if (flags & STRIP_BOLD) {
780     text++;
781     continue;
782     }
783     break;
784     case 3: /* mIRC colors? */
785     if (flags & STRIP_COLOR) {
786     if (egg_isdigit(text[1])) { /* Is the first char a number? */
787     text += 2; /* Skip over the ^C and the first digit */
788     if (egg_isdigit(*text))
789     text++; /* Is this a double digit number? */
790     if (*text == ',') { /* Do we have a background color next? */
791     if (egg_isdigit(text[1]))
792     text += 2; /* Skip over the first background digit */
793     if (egg_isdigit(*text))
794     text++; /* Is it a double digit? */
795     }
796     } else
797     text++;
798     continue;
799     }
800     break;
801     case 7:
802     if (flags & STRIP_BELLS) {
803     text++;
804     continue;
805     }
806     break;
807     case 0x16: /* Reverse video */
808     if (flags & STRIP_REV) {
809     text++;
810     continue;
811     }
812     break;
813     case 0x1f: /* Underlined text */
814     if (flags & STRIP_UNDER) {
815     text++;
816     continue;
817     }
818     break;
819     case 033:
820     if (flags & STRIP_ANSI) {
821     text++;
822     if (*text == '[') {
823     text++;
824     while ((*text == ';') || egg_isdigit(*text))
825     text++;
826     if (*text)
827     text++; /* also kill the following char */
828     }
829     continue;
830     }
831     break;
832     }
833     *dd++ = *text++; /* Move on to the next char */
834     }
835     *dd = 0;
836     }
837    
838     static void append_line(int idx, char *line)
839     {
840     int l = strlen(line);
841     struct msgq *p, *q;
842     struct chat_info *c = (dcc[idx].type == &DCC_CHAT) ? dcc[idx].u.chat :
843     dcc[idx].u.file->chat;
844    
845     if (c->current_lines > 1000) {
846     /* They're probably trying to fill up the bot nuke the sods :) */
847     for (p = c->buffer; p; p = q) {
848     q = p->next;
849     nfree(p->msg);
850     nfree(p);
851     }
852     c->buffer = 0;
853     dcc[idx].status &= ~STAT_PAGE;
854     do_boot(idx, botnetnick, "too many pages - sendq full");
855     return;
856     }
857     if ((c->line_count < c->max_line) && (c->buffer == NULL)) {
858     c->line_count++;
859     tputs(dcc[idx].sock, line, l);
860     } else {
861     c->current_lines++;
862     if (c->buffer == NULL)
863     q = NULL;
864     else
865     for (q = c->buffer; q->next; q = q->next);
866    
867     p = get_data_ptr(sizeof(struct msgq));
868    
869     p->len = l;
870     p->msg = get_data_ptr(l + 1);
871     p->next = NULL;
872     strcpy(p->msg, line);
873     if (q == NULL)
874     c->buffer = p;
875     else
876     q->next = p;
877     }
878     }
879    
880    
881     static void out_dcc_general(int idx, char *buf, void *x)
882     {
883     register struct chat_info *p = (struct chat_info *) x;
884     char *y = buf;
885    
886     strip_mirc_codes(p->strip_flags, buf);
887     if (dcc[idx].status & STAT_TELNET)
888     y = escape_telnet(buf);
889     if (dcc[idx].status & STAT_PAGE)
890     append_line(idx, y);
891     else
892     tputs(dcc[idx].sock, y, strlen(y));
893     }
894    
895     struct dcc_table DCC_CHAT_PASS = {
896     "CHAT_PASS",
897     0,
898     eof_dcc_general,
899     dcc_chat_pass,
900     &password_timeout,
901     tout_dcc_chat_pass,
902     display_dcc_chat_pass,
903     expmem_dcc_general,
904     kill_dcc_general,
905     out_dcc_general
906     };
907    
908     /* Make sure ANSI code is just for color-changing */
909     int check_ansi(char *v)
910     {
911     int count = 2;
912    
913     if (*v++ != '\033')
914     return 1;
915     if (*v++ != '[')
916     return 1;
917     while (*v) {
918     if (*v == 'm')
919     return 0;
920     if ((*v != ';') && ((*v < '0') || (*v > '9')))
921     return count;
922     v++;
923     count++;
924     }
925     return count;
926     }
927    
928     static void eof_dcc_chat(int idx)
929     {
930     putlog(LOG_MISC, "*", DCC_LOSTDCC, dcc[idx].nick,
931     dcc[idx].host, dcc[idx].port);
932     if (dcc[idx].u.chat->channel >= 0) {
933     chanout_but(idx, dcc[idx].u.chat->channel, "*** %s lost dcc link.\n",
934     dcc[idx].nick);
935     if (dcc[idx].u.chat->channel < GLOBAL_CHANS)
936     botnet_send_part_idx(idx, "lost dcc link");
937     check_tcl_chpt(botnetnick, dcc[idx].nick, dcc[idx].sock,
938     dcc[idx].u.chat->channel);
939     }
940     check_tcl_chof(dcc[idx].nick, dcc[idx].sock);
941     killsock(dcc[idx].sock);
942     lostdcc(idx);
943     }
944    
945     static void dcc_chat(int idx, char *buf, int i)
946     {
947     int nathan = 0, doron = 0, fixed = 0;
948     char *v, *d, filtbuf[2048];
949    
950     if (dcc[idx].status & STAT_TELNET)
951     strip_telnet(dcc[idx].sock, buf, &i);
952     if (buf[0] && (buf[0] != '.') &&
953     detect_dcc_flood(&dcc[idx].timeval, dcc[idx].u.chat, idx))
954     return;
955     dcc[idx].timeval = now;
956     if (buf[0]) {
957     const char *filt = check_tcl_filt(idx, buf);
958     if (filt != buf) {
959     strncpyz(filtbuf, filt, sizeof(filtbuf));
960     buf = filtbuf;
961     }
962     }
963     if (buf[0]) {
964     /* Check for beeps and cancel annoying ones */
965     v = buf;
966     d = buf;
967     while (*v)
968     switch (*v) {
969     case 7: /* Beep - no more than 3 */
970     nathan++;
971     if (nathan > 3)
972     v++;
973     else
974     *d++ = *v++;
975     break;
976     case 8: /* Backspace - for lame telnet's :) */
977     if (d > buf) {
978     d--;
979     }
980     v++;
981     break;
982     case 27: /* ESC - ansi code? */
983     doron = check_ansi(v);
984     /* If it's valid, append a return-to-normal code at the end */
985     if (!doron) {
986     *d++ = *v++;
987     fixed = 1;
988     } else
989     v += doron;
990     break;
991     case '\r': /* Weird pseudo-linefeed */
992     v++;
993     break;
994     default:
995     *d++ = *v++;
996     }
997     if (fixed)
998     strcpy(d, "\033[0m");
999     else
1000     *d = 0;
1001     if (buf[0]) { /* Nothing to say - maybe paging... */
1002     if ((buf[0] == '.') || (dcc[idx].u.chat->channel < 0)) {
1003     if (buf[0] == '.')
1004     buf++;
1005     v = newsplit(&buf);
1006     rmspace(buf);
1007     if (check_tcl_dcc(v, idx, buf)) {
1008     if (dcc[idx].u.chat->channel >= 0)
1009     check_tcl_chpt(botnetnick, dcc[idx].nick, dcc[idx].sock,
1010     dcc[idx].u.chat->channel);
1011     check_tcl_chof(dcc[idx].nick, dcc[idx].sock);
1012     dprintf(idx, "*** Ja mata!\n");
1013     flush_lines(idx, dcc[idx].u.chat);
1014     putlog(LOG_MISC, "*", DCC_CLOSED, dcc[idx].nick, dcc[idx].host);
1015     if (dcc[idx].u.chat->channel >= 0) {
1016     chanout_but(-1, dcc[idx].u.chat->channel,
1017     "*** %s left the party line%s%s\n",
1018     dcc[idx].nick, buf[0] ? ": " : ".", buf);
1019     if (dcc[idx].u.chat->channel < GLOBAL_CHANS)
1020     botnet_send_part_idx(idx, buf);
1021     }
1022     if (dcc[idx].u.chat->su_nick) {
1023     dcc[idx].user = get_user_by_handle(userlist,
1024     dcc[idx].u.chat->su_nick);
1025     strcpy(dcc[idx].nick, dcc[idx].u.chat->su_nick);
1026     dcc[idx].type = &DCC_CHAT;
1027     dprintf(idx, "Returning to real nick %s!\n",
1028     dcc[idx].u.chat->su_nick);
1029     nfree(dcc[idx].u.chat->su_nick);
1030     dcc[idx].u.chat->su_nick = NULL;
1031     dcc_chatter(idx);
1032     if (dcc[idx].u.chat->channel < GLOBAL_CHANS &&
1033     dcc[idx].u.chat->channel >= 0)
1034     botnet_send_join_idx(idx, -1);
1035     return;
1036     } else if ((dcc[idx].sock != STDOUT) || backgrd) {
1037     killsock(dcc[idx].sock);
1038     lostdcc(idx);
1039     return;
1040     } else {
1041     dprintf(DP_STDOUT, "\n### SIMULATION RESET\n\n");
1042     dcc_chatter(idx);
1043     return;
1044     }
1045     }
1046     } else if (buf[0] == ',') {
1047     int me = 0;
1048    
1049     if ((buf[1] == 'm') && (buf[2] == 'e') && buf[3] == ' ')
1050     me = 1;
1051     for (i = 0; i < dcc_total; i++) {
1052     int ok = 0;
1053    
1054     if ((dcc[i].type->flags & DCT_MASTER) &&
1055     ((dcc[i].type != &DCC_CHAT) || (dcc[i].u.chat->channel >= 0)) &&
1056     ((i != idx) || (dcc[idx].status & STAT_ECHO)))
1057     ok = 1;
1058     if (ok) {
1059     struct userrec *u = get_user_by_handle(userlist, dcc[i].nick);
1060    
1061     if (u && (u->flags & USER_MASTER)) {
1062     if (me)
1063     dprintf(i, "-> %s%s\n", dcc[idx].nick, buf + 3);
1064     else
1065     dprintf(i, "-%s-> %s\n", dcc[idx].nick, buf + 1);
1066     }
1067     }
1068     }
1069     } else if (buf[0] == '\'') {
1070     int me = 0;
1071    
1072     if ((buf[1] == 'm') && (buf[2] == 'e') &&
1073     ((buf[3] == ' ') || (buf[3] == '\'') || (buf[3] == ',')))
1074     me = 1;
1075     for (i = 0; i < dcc_total; i++) {
1076     if (dcc[i].type->flags & DCT_CHAT) {
1077     if (me)
1078     dprintf(i, "=> %s%s\n", dcc[idx].nick, buf + 3);
1079     else
1080     dprintf(i, "=%s=> %s\n", dcc[idx].nick, buf + 1);
1081     }
1082     }
1083     } else {
1084     if (dcc[idx].u.chat->away != NULL)
1085     not_away(idx);
1086     if (dcc[idx].status & STAT_ECHO)
1087     chanout_but(-1, dcc[idx].u.chat->channel,
1088     "<%s> %s\n", dcc[idx].nick, buf);
1089     else
1090     chanout_but(idx, dcc[idx].u.chat->channel, "<%s> %s\n",
1091     dcc[idx].nick, buf);
1092     botnet_send_chan(-1, botnetnick, dcc[idx].nick,
1093     dcc[idx].u.chat->channel, buf);
1094     check_tcl_chat(dcc[idx].nick, dcc[idx].u.chat->channel, buf);
1095     }
1096     }
1097     }
1098     if (dcc[idx].type == &DCC_CHAT) /* Could have change to files */
1099     if (dcc[idx].status & STAT_PAGE)
1100     flush_lines(idx, dcc[idx].u.chat);
1101     }
1102    
1103     static void display_dcc_chat(int idx, char *buf)
1104     {
1105     int i = simple_sprintf(buf, "chat flags: ");
1106    
1107     buf[i++] = dcc[idx].status & STAT_CHAT ? 'C' : 'c';
1108     buf[i++] = dcc[idx].status & STAT_PARTY ? 'P' : 'p';
1109     buf[i++] = dcc[idx].status & STAT_TELNET ? 'T' : 't';
1110     buf[i++] = dcc[idx].status & STAT_ECHO ? 'E' : 'e';
1111     buf[i++] = dcc[idx].status & STAT_PAGE ? 'P' : 'p';
1112     simple_sprintf(buf + i, "/%d", dcc[idx].u.chat->channel);
1113     }
1114    
1115     struct dcc_table DCC_CHAT = {
1116     "CHAT",
1117     DCT_CHAT | DCT_MASTER | DCT_SHOWWHO | DCT_VALIDIDX | DCT_SIMUL |
1118     DCT_CANBOOT | DCT_REMOTEWHO,
1119     eof_dcc_chat,
1120     dcc_chat,
1121     NULL,
1122     NULL,
1123     display_dcc_chat,
1124     expmem_dcc_general,
1125     kill_dcc_general,
1126     out_dcc_general
1127     };
1128    
1129     static int lasttelnets;
1130     static char lasttelnethost[81];
1131     static time_t lasttelnettime;
1132    
1133     /* A modified detect_flood for incoming telnet flood protection.
1134     */
1135     static int detect_telnet_flood(char *floodhost)
1136     {
1137     struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0 };
1138    
1139     get_user_flagrec(get_user_by_host(floodhost), &fr, NULL);
1140     if (!flood_telnet_thr || (glob_friend(fr) && !par_telnet_flood))
1141     return 0; /* No flood protection */
1142     if (egg_strcasecmp(lasttelnethost, floodhost)) { /* New... */
1143     strcpy(lasttelnethost, floodhost);
1144     lasttelnettime = now;
1145     lasttelnets = 0;
1146     return 0;
1147     }
1148     if (lasttelnettime < now - flood_telnet_time) {
1149     /* Flood timer expired, reset it */
1150     lasttelnettime = now;
1151     lasttelnets = 0;
1152     return 0;
1153     }
1154     lasttelnets++;
1155     if (lasttelnets >= flood_telnet_thr) { /* FLOOD! */
1156     /* Reset counters */
1157     lasttelnets = 0;
1158     lasttelnettime = 0;
1159     lasttelnethost[0] = 0;
1160     putlog(LOG_MISC, "*", IRC_TELNETFLOOD, floodhost);
1161     addignore(floodhost, origbotname, "Telnet connection flood",
1162     now + (60 * ignore_time));
1163     return 1;
1164     }
1165     return 0;
1166     }
1167    
1168     static void dcc_telnet(int idx, char *buf, int i)
1169     {
1170     unsigned short port;
1171     int j = 0, sock;
1172    
1173     if (dcc_total + 1 > max_dcc && increase_socks_max()) {
1174 pseudo 1.2 sockname_t name;
1175     j = answer(dcc[idx].sock, &name, &port, 0);
1176 simple 1.1 if (j != -1) {
1177     dprintf(-j, "Sorry, too many connections already.\r\n");
1178     killsock(j);
1179     }
1180     return;
1181     }
1182 pseudo 1.2 i = new_dcc(&DCC_DNSWAIT, sizeof(struct dns_info));
1183     sock = answer(dcc[idx].sock, &dcc[i].sockname, &port, 0);
1184 simple 1.1 while ((sock == -1) && (errno == EAGAIN))
1185 pseudo 1.2 sock = answer(dcc[idx].sock, &dcc[i].sockname, &port, 0);
1186 simple 1.1 if (sock < 0) {
1187 pseudo 1.2 putlog(LOG_MISC, "*", DCC_FAILED, strerror(errno));
1188 simple 1.1 return;
1189     }
1190     /* Buffer data received on this socket. */
1191     sockoptions(sock, EGG_OPTION_SET, SOCK_BUFFER);
1192    
1193     #if (SIZEOF_SHORT == 2)
1194     if (port < 1024) {
1195     #else
1196     if (port < 1024 || port > 65535) {
1197     #endif
1198 pseudo 1.2 putlog(LOG_BOTS, "*", DCC_BADSRC, iptostr(&dcc[i].sockname.addr.sa), port);
1199 simple 1.1 killsock(sock);
1200 pseudo 1.2 lostdcc(i);
1201 simple 1.1 return;
1202     }
1203    
1204 pseudo 1.2 dcc[i].u.dns->ip = &dcc[i].sockname;
1205 simple 1.1 dcc[i].sock = sock;
1206     dcc[i].port = port;
1207 pseudo 1.4 #ifdef TLS
1208     if (dcc[idx].ssl && ssl_handshake(sock, TLS_LISTEN, tls_vfyclients,
1209     LOG_MISC, NULL, NULL)) {
1210     killsock(sock);
1211     lostdcc(i);
1212     return;
1213     }
1214     dcc[i].ssl = dcc[idx].ssl;
1215     #endif
1216 simple 1.1 dcc[i].timeval = now;
1217     strcpy(dcc[i].nick, "*");
1218     dcc[i].u.dns->dns_success = dcc_telnet_hostresolved;
1219     dcc[i].u.dns->dns_failure = dcc_telnet_hostresolved;
1220     dcc[i].u.dns->dns_type = RES_HOSTBYIP;
1221     dcc[i].u.dns->ibuf = dcc[idx].sock;
1222     dcc[i].u.dns->type = &DCC_IDENTWAIT;
1223 pseudo 1.2 dcc_dnshostbyip(&dcc[i].sockname);
1224 simple 1.1 }
1225    
1226     static void dcc_telnet_hostresolved(int i)
1227     {
1228     int idx;
1229     int j = 0, sock;
1230 pseudo 1.2 char s[UHOSTLEN + 20];
1231 simple 1.1
1232     strncpyz(dcc[i].host, dcc[i].u.dns->host, UHOSTLEN);
1233    
1234     for (idx = 0; idx < dcc_total; idx++)
1235     if ((dcc[idx].type == &DCC_TELNET) &&
1236     (dcc[idx].sock == dcc[i].u.dns->ibuf)) {
1237     break;
1238     }
1239     if (dcc_total == idx) {
1240     putlog(LOG_BOTS, "*", "Lost listening socket while resolving %s",
1241     dcc[i].host);
1242     killsock(dcc[i].sock);
1243     lostdcc(i);
1244     return;
1245     }
1246     if (dcc[idx].host[0] == '@') {
1247     /* Restrict by hostname */
1248     if (!wild_match(dcc[idx].host + 1, dcc[i].host)) {
1249     putlog(LOG_BOTS, "*", DCC_BADHOST, dcc[i].host);
1250     killsock(dcc[i].sock);
1251     lostdcc(i);
1252     return;
1253     }
1254     }
1255 pseudo 1.2 sprintf(s, "-telnet!telnet@%s", dcc[i].host);
1256     if (match_ignore(s) || detect_telnet_flood(s)) {
1257 simple 1.1 killsock(dcc[i].sock);
1258     lostdcc(i);
1259     return;
1260     }
1261    
1262     changeover_dcc(i, &DCC_IDENTWAIT, 0);
1263     dcc[i].timeval = now;
1264     dcc[i].u.ident_sock = dcc[idx].sock;
1265 pseudo 1.2 sock = -1;
1266     j = new_dcc(&DCC_IDENT, 0);
1267     if (j < 0)
1268     putlog(LOG_MISC, "*", DCC_IDENTFAIL, dcc[i].host, strerror(errno));
1269     else {
1270     egg_memcpy(&dcc[j].sockname, &dcc[i].sockname, sizeof(sockname_t));
1271     dcc[j].sock = getsock(dcc[j].sockname.family, 0);
1272     if (dcc[j].sock >= 0) {
1273     sockname_t name;
1274     name.addrlen = sizeof(name.addr);
1275     getsockname(dcc[i].sock, &name.addr.sa, &name.addrlen);
1276     bind(dcc[j].sock, &name.addr.sa, name.addrlen);
1277     setsnport(dcc[j].sockname, 113);
1278     if (connect(dcc[j].sock, &dcc[j].sockname.addr.sa,
1279     dcc[j].sockname.addrlen) < 0 && (errno != EINPROGRESS)) {
1280     killsock(dcc[j].sock);
1281     lostdcc(j);
1282     putlog(LOG_MISC, "*", DCC_IDENTFAIL, dcc[i].host, strerror(errno));
1283     j = 0;
1284     }
1285     sock = dcc[j].sock;
1286 simple 1.1 }
1287     }
1288 pseudo 1.2 if (j < 0) {
1289 simple 1.1 sprintf(s, "telnet@%s", dcc[i].host);
1290     dcc_telnet_got_ident(i, s);
1291     return;
1292     }
1293     dcc[j].sock = sock;
1294     dcc[j].port = 113;
1295     dcc[j].addr = dcc[i].addr;
1296     strcpy(dcc[j].host, dcc[i].host);
1297     strcpy(dcc[j].nick, "*");
1298     dcc[j].u.ident_sock = dcc[i].sock;
1299     dcc[j].timeval = now;
1300     dprintf(j, "%d, %d\n", dcc[i].port, dcc[idx].port);
1301     }
1302    
1303     static void eof_dcc_telnet(int idx)
1304     {
1305     putlog(LOG_MISC, "*", DCC_PORTDIE, dcc[idx].port);
1306     killsock(dcc[idx].sock);
1307     lostdcc(idx);
1308     }
1309    
1310     static void display_telnet(int idx, char *buf)
1311     {
1312     sprintf(buf, "lstn %d%s", dcc[idx].port,
1313     (dcc[idx].status & LSTN_PUBLIC) ? " pub" : "");
1314     }
1315    
1316     struct dcc_table DCC_TELNET = {
1317     "TELNET",
1318     DCT_LISTEN,
1319     eof_dcc_telnet,
1320     dcc_telnet,
1321     NULL,
1322     NULL,
1323     display_telnet,
1324     NULL,
1325     NULL,
1326     NULL
1327     };
1328    
1329     static void eof_dcc_dupwait(int idx)
1330     {
1331     putlog(LOG_BOTS, "*", DCC_LOSTDUP, dcc[idx].host);
1332     killsock(dcc[idx].sock);
1333     lostdcc(idx);
1334     }
1335    
1336     static void dcc_dupwait(int idx, char *buf, int i)
1337     {
1338     /* We just ignore any data at this point. */
1339     return;
1340     }
1341    
1342     /* We now check again. If the bot is still marked as duplicate, there is no
1343     * botnet lag we could push it on, so we just drop the connection.
1344     */
1345     static void timeout_dupwait(int idx)
1346     {
1347     char x[100];
1348    
1349     /* Still duplicate? */
1350     if (in_chain(dcc[idx].nick)) {
1351     egg_snprintf(x, sizeof x, "%s!%s", dcc[idx].nick, dcc[idx].host);
1352     dprintf(idx, "error Already connected.\n");
1353     putlog(LOG_BOTS, "*", DCC_DUPLICATE, x);
1354     killsock(dcc[idx].sock);
1355     lostdcc(idx);
1356     } else {
1357     /* Ha! Now it's gone and we can grant this bot access. */
1358     dcc_telnet_pass(idx, dcc[idx].u.dupwait->atr);
1359     }
1360     }
1361    
1362     static void display_dupwait(int idx, char *buf)
1363     {
1364     sprintf(buf, "wait duplicate?");
1365     }
1366    
1367     static int expmem_dupwait(void *x)
1368     {
1369     register struct dupwait_info *p = (struct dupwait_info *) x;
1370     int tot = sizeof(struct dupwait_info);
1371    
1372     if (p && p->chat && DCC_CHAT.expmem)
1373     tot += DCC_CHAT.expmem(p->chat);
1374     return tot;
1375     }
1376    
1377     static void kill_dupwait(int idx, void *x)
1378     {
1379     register struct dupwait_info *p = (struct dupwait_info *) x;
1380    
1381     if (p) {
1382     if (p->chat && DCC_CHAT.kill)
1383     DCC_CHAT.kill(idx, p->chat);
1384     nfree(p);
1385     }
1386     }
1387    
1388     struct dcc_table DCC_DUPWAIT = {
1389     "DUPWAIT",
1390     DCT_VALIDIDX,
1391     eof_dcc_dupwait,
1392     dcc_dupwait,
1393     &dupwait_timeout,
1394     timeout_dupwait,
1395     display_dupwait,
1396     expmem_dupwait,
1397     kill_dupwait,
1398     NULL
1399     };
1400    
1401     /* This function is called if a bot gets removed from the list. It checks
1402     * wether we have a pending duplicate connection for that bot and continues
1403     * with the login in that case.
1404     */
1405     void dupwait_notify(char *who)
1406     {
1407     register int idx;
1408    
1409     Assert(who);
1410     for (idx = 0; idx < dcc_total; idx++)
1411     if ((dcc[idx].type == &DCC_DUPWAIT) &&
1412     !egg_strcasecmp(dcc[idx].nick, who)) {
1413     dcc_telnet_pass(idx, dcc[idx].u.dupwait->atr);
1414     break;
1415     }
1416     }
1417    
1418     static void dcc_telnet_id(int idx, char *buf, int atr)
1419     {
1420     int ok = 0;
1421     struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0 };
1422    
1423     if (detect_telnet((unsigned char *) buf)) {
1424     dcc[idx].status |= STAT_TELNET;
1425     strip_telnet(dcc[idx].sock, buf, &atr);
1426     } else
1427     dcc[idx].status &= ~STAT_TELNET;
1428     buf[HANDLEN] = 0;
1429     /* Toss out bad nicknames */
1430     if (dcc[idx].nick[0] != '@' && !wild_match(dcc[idx].nick, buf)) {
1431     dprintf(idx, "Sorry, that nickname format is invalid.\n");
1432     putlog(LOG_BOTS, "*", DCC_BADNICK, dcc[idx].host);
1433     killsock(dcc[idx].sock);
1434     lostdcc(idx);
1435     return;
1436     }
1437     dcc[idx].user = get_user_by_handle(userlist, buf);
1438     get_user_flagrec(dcc[idx].user, &fr, NULL);
1439 pseudo 1.4 #ifdef TLS
1440     if (dcc[idx].ssl && (tls_auth == 2)) {
1441     char *uid = ssl_getuid(dcc[idx].sock);
1442    
1443     if (!uid || strcasecmp(uid, buf)) {
1444     if (glob_bot(fr))
1445     dprintf(idx, "error Certificate UID doesn't match handle\n");
1446     else
1447     dprintf(idx, "Your certificate UID doesn't match your handle.\n");
1448     killsock(dcc[idx].sock);
1449     lostdcc(idx);
1450     return;
1451     }
1452     }
1453     #endif
1454 simple 1.1 /* Make sure users-only/bots-only connects are honored */
1455     if ((dcc[idx].status & STAT_BOTONLY) && !glob_bot(fr)) {
1456     dprintf(idx, "This telnet port is for bots only.\n");
1457     putlog(LOG_BOTS, "*", DCC_NONBOT, dcc[idx].host);
1458     killsock(dcc[idx].sock);
1459     lostdcc(idx);
1460     return;
1461     }
1462     if ((dcc[idx].status & STAT_USRONLY) && glob_bot(fr)) {
1463     dprintf(idx, "error Only users may connect at this port.\n");
1464     putlog(LOG_BOTS, "*", DCC_NONUSER, dcc[idx].host);
1465     killsock(dcc[idx].sock);
1466     lostdcc(idx);
1467     return;
1468     }
1469     dcc[idx].status &= ~(STAT_BOTONLY | STAT_USRONLY);
1470     if (!egg_strcasecmp(buf, "NEW") && (allow_new_telnets || make_userfile)) {
1471     dcc[idx].type = &DCC_TELNET_NEW;
1472     dcc[idx].timeval = now;
1473     dprintf(idx, "\n");
1474     dprintf(idx, IRC_TELNET, botnetnick);
1475     dprintf(idx, IRC_TELNET1);
1476     dprintf(idx, "\nEnter the nickname you would like to use.\n");
1477     return;
1478     }
1479     if (chan_op(fr)) {
1480     if (!require_p)
1481     ok = 1;
1482     }
1483     if (!ok && (glob_party(fr) || glob_bot(fr)))
1484     ok = 1;
1485    
1486     if (!ok) {
1487     dprintf(idx, "You don't have access.\n");
1488     putlog(LOG_BOTS, "*", DCC_INVHANDLE, dcc[idx].host, buf);
1489     killsock(dcc[idx].sock);
1490     lostdcc(idx);
1491     return;
1492     }
1493     correct_handle(buf);
1494     strcpy(dcc[idx].nick, buf);
1495     if (glob_bot(fr)) {
1496     if (!egg_strcasecmp(botnetnick, dcc[idx].nick)) {
1497     dprintf(idx, "error You cannot link using my botnetnick.\n");
1498     putlog(LOG_BOTS, "*", DCC_MYBOTNETNICK, dcc[idx].host);
1499     killsock(dcc[idx].sock);
1500     lostdcc(idx);
1501     return;
1502     } else if (in_chain(dcc[idx].nick)) {
1503     struct chat_info *ci;
1504    
1505     ci = dcc[idx].u.chat;
1506     dcc[idx].type = &DCC_DUPWAIT;
1507     dcc[idx].u.dupwait = get_data_ptr(sizeof(struct dupwait_info));
1508     dcc[idx].u.dupwait->chat = ci;
1509     dcc[idx].u.dupwait->atr = atr;
1510     return;
1511     }
1512     }
1513     dcc_telnet_pass(idx, atr);
1514     }
1515    
1516 pseudo 1.4 #ifdef TLS
1517     int dcc_fingerprint(idx)
1518     {
1519     char *cf, *uf;
1520     struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0 };
1521    
1522     get_user_flagrec(dcc[idx].user, &fr, NULL);
1523     /* Check if fingerprint authentication is allowed or required. */
1524     if (dcc[idx].ssl && tls_auth) {
1525     /* Get the fingerprint of the current certificate */
1526     cf = ssl_getfp(dcc[idx].sock);
1527     /* Get the fingerprint of the user, if set */
1528     uf = get_user(&USERENTRY_FPRINT, dcc[idx].user);
1529     if (cf && uf && !strcasecmp(cf, uf)) {
1530     if (!glob_bot(fr))
1531     dprintf(idx, "Used your fingerprint for automatic authentication.\n");
1532     dcc[idx].status |= STAT_FPRINT;
1533     dcc_chat_pass(idx, "+", 1);
1534     /* Required? */
1535     } else if (tls_auth == 2) {
1536     if (glob_bot(fr))
1537     dprintf(idx, "error fingerprint required\n");
1538     else
1539     dprintf(idx, "Certificate authentication required. "
1540     "You need to set your fingerprint.\n");
1541     killsock(dcc[idx].sock);
1542     lostdcc(idx);
1543     }
1544     return 0;
1545     }
1546     return 1;
1547     }
1548     #endif
1549    
1550 simple 1.1 static void dcc_telnet_pass(int idx, int atr)
1551     {
1552     int ok = 0;
1553     struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0 };
1554    
1555     get_user_flagrec(dcc[idx].user, &fr, NULL);
1556 pseudo 1.4 #ifdef TLS
1557     /* Check if fingerprint authentication is allowed or required. */
1558     if (dcc[idx].ssl && tls_auth) {
1559     char *cf, *uf;
1560    
1561     /* Get the fingerprint of the current certificate */
1562     cf = ssl_getfp(dcc[idx].sock);
1563     /* Get the fingerprint of the user, if set */
1564     uf = get_user(&USERENTRY_FPRINT, dcc[idx].user);
1565     if (cf && uf && !strcasecmp(cf, uf)) {
1566 pseudo 1.6 char fakepass[2] = "+";
1567    
1568 pseudo 1.4 if (!glob_bot(fr))
1569     dprintf(idx, "Used your fingerprint for automatic authentication.\n");
1570     dcc[idx].status |= STAT_FPRINT;
1571 pseudo 1.6 dcc_chat_pass(idx, fakepass, 1);
1572 pseudo 1.4 return;
1573     /* Required? */
1574     } else if (tls_auth == 2) {
1575     if (glob_bot(fr))
1576     dprintf(idx, "error fingerprint required\n");
1577     else
1578     dprintf(idx, "Certificate authentication required. "
1579     "You need to set your fingerprint.\n");
1580     killsock(dcc[idx].sock);
1581     lostdcc(idx);
1582     return;
1583     }
1584     }
1585     #endif
1586 simple 1.1 /* No password set? */
1587     if (u_pass_match(dcc[idx].user, "-")) {
1588     if (glob_bot(fr)) {
1589     char ps[20];
1590    
1591     makepass(ps);
1592     set_user(&USERENTRY_PASS, dcc[idx].user, ps);
1593     changeover_dcc(idx, &DCC_BOT_NEW, sizeof(struct bot_info));
1594    
1595     dcc[idx].status = STAT_CALLED;
1596     dprintf(idx, "*hello!\n");
1597     greet_new_bot(idx);
1598     #ifdef NO_OLD_BOTNET
1599     dprintf(idx, "h %s\n", ps);
1600     #else
1601     dprintf(idx, "handshake %s\n", ps);
1602     #endif
1603     return;
1604     }
1605     dprintf(idx, "Can't telnet until you have a password set.\n");
1606     putlog(LOG_MISC, "*", DCC_NOPASS, dcc[idx].nick, dcc[idx].host);
1607     killsock(dcc[idx].sock);
1608     lostdcc(idx);
1609     return;
1610     }
1611     ok = 0;
1612     if (dcc[idx].type == &DCC_DUPWAIT) {
1613     struct chat_info *ci;
1614    
1615     ci = dcc[idx].u.dupwait->chat;
1616     nfree(dcc[idx].u.dupwait);
1617     dcc[idx].u.chat = ci;
1618     }
1619     dcc[idx].type = &DCC_CHAT_PASS;
1620     dcc[idx].timeval = now;
1621     if (glob_botmast(fr))
1622     ok = 1;
1623     else if (chan_op(fr)) {
1624     if (!require_p)
1625     ok = 1;
1626     else if (glob_party(fr))
1627     ok = 1;
1628     } else if (glob_party(fr)) {
1629     ok = 1;
1630     dcc[idx].status |= STAT_PARTY;
1631     }
1632     if (glob_bot(fr))
1633     ok = 1;
1634     if (!ok) {
1635     struct chat_info *ci;
1636    
1637     ci = dcc[idx].u.chat;
1638     dcc[idx].u.file = get_data_ptr(sizeof(struct file_info));
1639     dcc[idx].u.file->chat = ci;
1640     }
1641    
1642     if (glob_bot(fr)) {
1643 pseudo 1.7 #ifdef TLS
1644     /* Ask the peer to switch to ssl communication. We'll continue using plain
1645     * text, until it replies with starttls itself. Bots which don't support ssl
1646     * will simply ignore the request and everything will go on as usual.
1647     */
1648     if (!dcc[idx].ssl) {
1649     dprintf(idx, "starttls\n");
1650     putlog(LOG_BOTS, "*", "Sent STARTTLS to %s...", dcc[idx].nick);
1651     }
1652     #endif
1653 simple 1.1 /* Must generate a string consisting of our process ID and the current
1654     * time. The bot will add it's password to the end and use it to generate
1655     * an MD5 checksum (always 128bit). The checksum is sent back and this
1656     * end does the same. The remote bot is only allowed access if the
1657     * checksums match.
1658     *
1659     * Please don't fuck with 'timeval', or the digest we generate later for
1660     * authentication will not be correct - you've been warned ;)
1661     * <Cybah>
1662     */
1663     putlog(LOG_BOTS, "*", "Challenging %s...", dcc[idx].nick);
1664     dprintf(idx, "passreq <%x%x@%s>\n", getpid(), dcc[idx].timeval, botnetnick);
1665     } else {
1666     /* NOTE: The MD5 digest used above to prevent cleartext passwords being
1667     * sent across the net will _only_ work when we have the cleartext
1668     * password. User passwords are encrypted (with blowfish usually)
1669     * so the same thing cant be done. Botnet passwords are always
1670     * stored in cleartext, or at least something that can be reversed.
1671     * <Cybah>
1672     */
1673    
1674     /* Turn off remote telnet echo (send IAC WILL ECHO). */
1675     if (dcc[idx].status & STAT_TELNET) {
1676     char buf[1030];
1677     snprintf(buf, sizeof buf, "\n%s%s\r\n", escape_telnet(DCC_ENTERPASS),
1678     TLN_IAC_C TLN_WILL_C TLN_ECHO_C);
1679     tputs(dcc[idx].sock, buf, strlen(buf));
1680     } else
1681     dprintf(idx, "\n%s\n", DCC_ENTERPASS);
1682     }
1683     }
1684    
1685     static void eof_dcc_telnet_id(int idx)
1686     {
1687     putlog(LOG_MISC, "*", DCC_LOSTCON, dcc[idx].host, dcc[idx].port);
1688     killsock(dcc[idx].sock);
1689     lostdcc(idx);
1690     }
1691    
1692     static void timeout_dcc_telnet_id(int idx)
1693     {
1694     dprintf(idx, "Timeout.\n");
1695     putlog(LOG_MISC, "*", DCC_TTIMEOUT, dcc[idx].host);
1696     killsock(dcc[idx].sock);
1697     lostdcc(idx);
1698     }
1699    
1700     static void display_dcc_telnet_id(int idx, char *buf)
1701     {
1702     long tv;
1703    
1704     tv = now - dcc[idx].timeval;
1705     sprintf(buf, "t-in waited %lis", tv);
1706     }
1707    
1708     struct dcc_table DCC_TELNET_ID = {
1709     "TELNET_ID",
1710     0,
1711     eof_dcc_telnet_id,
1712     dcc_telnet_id,
1713     &password_timeout,
1714     timeout_dcc_telnet_id,
1715     display_dcc_telnet_id,
1716     expmem_dcc_general,
1717     kill_dcc_general,
1718     out_dcc_general
1719     };
1720    
1721     static void dcc_telnet_new(int idx, char *buf, int x)
1722     {
1723     int ok = 1;
1724     char work[1024], *p, *q, *r;
1725    
1726     buf[HANDLEN] = 0;
1727     if (dcc[idx].status & STAT_TELNET)
1728     strip_telnet(dcc[idx].sock, buf, &x);
1729     dcc[idx].timeval = now;
1730     for (x = 0; x < strlen(buf); x++)
1731 pseudo 1.3 if (buf[x] <= 32)
1732 simple 1.1 ok = 0;
1733     if (!ok) {
1734     dprintf(idx, "\nYou can't use weird symbols in your nick.\n");
1735     dprintf(idx, "Try another one please:\n");
1736     } else if (strchr(BADHANDCHARS, buf[0]) != NULL) {
1737     dprintf(idx, "\nYou can't start your nick with the character '%c'\n",
1738     buf[0]);
1739     dprintf(idx, "Try another one please:\n");
1740     } else if (get_user_by_handle(userlist, buf)) {
1741     dprintf(idx, "\nSorry, that nickname is taken already.\n");
1742     dprintf(idx, "Try another one please:\n");
1743     return;
1744     } else if (!egg_strcasecmp(buf, botnetnick))
1745     dprintf(idx, "Sorry, can't use my name for a nick.\n");
1746     else {
1747     strcpy(dcc[idx].nick, buf);
1748     if (make_userfile)
1749     userlist = adduser(userlist,
1750     buf, "-telnet!*@*", "-", sanity_check(default_flags |
1751     USER_PARTY | USER_MASTER | USER_OWNER));
1752     else {
1753     p = strchr(dcc[idx].host, '@');
1754     if (p) {
1755     q = p;
1756     *q = 0;
1757     p++;
1758     r = strchr(p, '.');
1759     if (!r)
1760     simple_sprintf(work, "-telnet!%s@%s", dcc[idx].host, p);
1761     else
1762     simple_sprintf(work, "-telnet!%s@*%s", dcc[idx].host, r);
1763     *q = '@';
1764     } else
1765     simple_sprintf(work, "-telnet!*@*%s", dcc[idx].host);
1766     userlist = adduser(userlist, buf, work, "-",
1767     sanity_check(USER_PARTY | default_flags));
1768     }
1769     reaffirm_owners();
1770     dcc[idx].status = STAT_ECHO | STAT_TELNET;
1771     dcc[idx].type = &DCC_CHAT; /* Just so next line will work */
1772     dcc[idx].user = get_user_by_handle(userlist, buf);
1773     check_dcc_attrs(dcc[idx].user, USER_PARTY | default_flags);
1774     dcc[idx].type = &DCC_TELNET_PW;
1775     if (make_userfile) {
1776     dprintf(idx, "\nYOU ARE THE MASTER/OWNER ON THIS BOT NOW\n");
1777     dprintf(idx, IRC_LIMBO);
1778     putlog(LOG_MISC, "*", DCC_INSTCOMPL, buf);
1779     make_userfile = 0;
1780     write_userfile(-1);
1781     add_note(buf, botnetnick, "Welcome to eggdrop! :)", -1, 0);
1782     }
1783     dprintf(idx, "\nOkay, now choose and enter a password:\n");
1784     dprintf(idx, "(Only the first 15 letters are significant.)\n");
1785     }
1786     }
1787    
1788     static void dcc_telnet_pw(int idx, char *buf, int x)
1789     {
1790     char *newpass;
1791     int ok;
1792    
1793     if (dcc[idx].status & STAT_TELNET)
1794     strip_telnet(dcc[idx].sock, buf, &x);
1795     buf[16] = 0;
1796     ok = 1;
1797     if (strlen(buf) < 4) {
1798     dprintf(idx, "\nTry to use at least 4 characters in your password.\n");
1799     dprintf(idx, "Choose and enter a password:\n");
1800     return;
1801     }
1802     for (x = 0; x < strlen(buf); x++)
1803     if ((buf[x] <= 32) || (buf[x] == 127))
1804     ok = 0;
1805     if (!ok) {
1806     dprintf(idx, "\nYou can't use weird symbols in your password.\n");
1807     dprintf(idx, "Try another one please:\n");
1808     return;
1809     }
1810     putlog(LOG_MISC, "*", DCC_NEWUSER, dcc[idx].nick, dcc[idx].host,
1811     dcc[idx].port);
1812     if (notify_new[0]) {
1813     char s[121], s1[121], s2[121];
1814    
1815     sprintf(s, "Introduced to %s, %s", dcc[idx].nick, dcc[idx].host);
1816     strcpy(s1, notify_new);
1817     splitc(s2, s1, ',');
1818     while (s2[0]) {
1819     rmspace(s2);
1820     add_note(s2, botnetnick, s, -1, 0);
1821     splitc(s2, s1, ',');
1822     }
1823     rmspace(s1);
1824     add_note(s1, botnetnick, s, -1, 0);
1825     }
1826     newpass = newsplit(&buf);
1827     set_user(&USERENTRY_PASS, dcc[idx].user, newpass);
1828     dprintf(idx, "\nRemember that! You'll need it next time you log in.\n");
1829     dprintf(idx, "You now have an account on %s...\n\n\n", botnetnick);
1830     dcc[idx].type = &DCC_CHAT;
1831     dcc[idx].u.chat->channel = -2;
1832     dcc_chatter(idx);
1833     }
1834    
1835     static void eof_dcc_telnet_new(int idx)
1836     {
1837     putlog(LOG_MISC, "*", DCC_LOSTNEWUSER, dcc[idx].host, dcc[idx].port);
1838     killsock(dcc[idx].sock);
1839     lostdcc(idx);
1840     }
1841    
1842     static void eof_dcc_telnet_pw(int idx)
1843     {
1844     putlog(LOG_MISC, "*", DCC_LOSTNEWUSR2, dcc[idx].nick, dcc[idx].host,
1845     dcc[idx].port);
1846     deluser(dcc[idx].nick);
1847     killsock(dcc[idx].sock);
1848     lostdcc(idx);
1849     }
1850    
1851     static void tout_dcc_telnet_new(int idx)
1852     {
1853     dprintf(idx, "Guess you're not there. Bye.\n");
1854     putlog(LOG_MISC, "*", DCC_TIMEOUTUSER, dcc[idx].host, dcc[idx].port);
1855     killsock(dcc[idx].sock);
1856     lostdcc(idx);
1857     }
1858    
1859     static void tout_dcc_telnet_pw(int idx)
1860     {
1861     dprintf(idx, "Guess you're not there. Bye.\n");
1862     putlog(LOG_MISC, "*", DCC_TIMEOUTUSR2, dcc[idx].nick,
1863     dcc[idx].host, dcc[idx].port);
1864     killsock(dcc[idx].sock);
1865     lostdcc(idx);
1866     }
1867    
1868     static void display_dcc_telnet_new(int idx, char *buf)
1869     {
1870     long tv;
1871    
1872     tv = now - dcc[idx].timeval;
1873     sprintf(buf, "new waited %lis", tv);
1874     }
1875    
1876     static void display_dcc_telnet_pw(int idx, char *buf)
1877     {
1878     long tv;
1879    
1880     tv = now - dcc[idx].timeval;
1881     sprintf(buf, "newp waited %lis", tv);
1882     }
1883    
1884     struct dcc_table DCC_TELNET_NEW = {
1885     "TELNET_NEW",
1886     0,
1887     eof_dcc_telnet_new,
1888     dcc_telnet_new,
1889     &password_timeout,
1890     tout_dcc_telnet_new,
1891     display_dcc_telnet_new,
1892     expmem_dcc_general,
1893     kill