/[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.8 - (hide annotations) (download) (as text)
Fri Nov 26 13:20:29 2010 UTC (10 years, 11 months ago) by pseudo
Branch: MAIN
Changes since 1.7: +30 -27 lines
File MIME type: text/x-chdr
Added a little hack to send starttls before password exchange during the initial handshake.

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