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 /*
8  * Copyright (C) 1997 Robey Pointer
9  * Copyright (C) 1999 - 2021 Eggheads Development Team
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25 
26 #include "main.h"
27 #include <errno.h>
28 #include "modules.h"
29 #include "tandem.h"
30 
31 /* Includes for botnet md5 challenge/response code <cybah> */
32 #include "md5/md5.h"
33 
34 extern struct userrec *userlist;
35 extern struct chanset_t *chanset;
36 extern Tcl_Interp *interp;
37 extern time_t now;
38 extern char botnetnick[], ver[], origbotname[], notify_new[];
39 extern int egg_numver, connect_timeout, conmask, backgrd, max_dcc,
40            make_userfile, default_flags, raw_log, ignore_time,
41            par_telnet_flood;
42 
43 #ifdef TLS
44 extern int tls_vfybots, ssl_files_loaded;
45 
46 int tls_vfyclients = 0;         /* Certificate validation mode for clients    */
47 int tls_vfydcc = 0;             /* Verify DCC chat/send user certificates     */
48 int tls_auth = 0;               /* Allow certificate authentication           */
49 #endif
50 
51 struct dcc_t *dcc = NULL;       /* DCC list                                   */
52 int dcc_total = 0;              /* Total dcc's                                */
53 int require_p = 0;              /* Require 'p' access to get on the
54                                  * party line?                                */
55 int allow_new_telnets = 0;      /* Allow people to introduce themselves
56                                  * via telnet                                 */
57 int stealth_telnets = 0;        /* Be paranoid? <cybah>                       */
58 int use_telnet_banner = 0;      /* Display telnet banner?                     */
59 int password_timeout = 180;     /* Time to wait for a password from a user    */
60 int bot_timeout = 60;           /* Bot timeout value                          */
61 int identtimeout = 5;           /* Timeout value for ident lookups            */
62 int dupwait_timeout = 5;        /* Timeout for rejecting duplicate entries    */
63 int protect_telnet = 1;         /* Even bother with ident lookups :)          */
64 int flood_telnet_thr = 5;       /* Number of telnet connections to be
65                                  * considered a flood                         */
66 int flood_telnet_time = 60;     /* In how many seconds?                       */
67 char network[41] = "unknown-net";      /* Name of the IRC network you're on   */
68 char bannerfile[121] = "text/banner";  /* File displayed on telnet login      */
69 char stealth_prompt[81] = "\n\nNickname.\n"; /* stealth_telnet prompt string  */
70 
71 static void dcc_telnet_hostresolved(int);
72 static void dcc_telnet_got_ident(int, char *);
73 static void dcc_telnet_pass(int, int);
74 
75 
76 /* This is not a universal telnet detector. You need to send WILL STATUS to the
77  * other side and pass the reply to this function. A telnet client will respond
78  * to this with either DO or DONT STATUS.
79  */
detect_telnet(unsigned char * buf)80 static int detect_telnet(unsigned char *buf)
81 {
82   if (!buf || !buf[0] || !buf[1])
83     return 0;
84   while (buf[2]) {
85     if (buf[0] == TLN_IAC && (buf[1] == TLN_DO || buf[1] == TLN_DONT) &&
86         buf[2] == TLN_STATUS)
87       return 1;
88     buf++;
89   }
90   return 0;
91 }
92 
93 /* Escape telnet IAC and prepend CR to LF */
escape_telnet(char * s)94 static char *escape_telnet(char *s)
95 {
96   static char buf[1024];
97   char *p;
98 
99   for (p = buf; *s && (p < (buf + sizeof(buf) - 2)); *p++ = *s++)
100     if ((unsigned char) *s == TLN_IAC)
101       *p++ = *s;
102     else if (*s == '\n')
103       *p++ = '\r';
104   *p = 0;
105 
106   return buf;
107 }
108 
strip_telnet(int sock,char * buf,int * len)109 static void strip_telnet(int sock, char *buf, int *len)
110 {
111   unsigned char *p = (unsigned char *) buf, *o = (unsigned char *) buf;
112   int mark;
113 
114   while (*p != 0) {
115     while ((*p != TLN_IAC) && (*p != 0))
116       *o++ = *p++;
117     if (*p == TLN_IAC) {
118       p++;
119       mark = 2;
120       if (!*p)
121         mark = 1;               /* bogus */
122       if ((*p >= TLN_WILL) && (*p <= TLN_DONT)) {
123         mark = 3;
124         if (!*(p + 1))
125           mark = 2;             /* bogus */
126       } else if (*p == TLN_WILL) {
127         /* WILL X -> response: DONT X */
128         /* except WILL ECHO which we just smile and ignore */
129         if (*(p + 1) != TLN_ECHO) {
130           safe_write(sock, TLN_IAC_C TLN_DONT_C, 2);
131           safe_write(sock, p + 1, 1);
132         }
133       } else if (*p == TLN_DO) {
134         /* DO X -> response: WONT X */
135         /* except DO ECHO which we just smile and ignore */
136         if (*(p + 1) != TLN_ECHO) {
137           safe_write(sock, TLN_IAC_C TLN_WONT_C, 2);
138           safe_write(sock, p + 1, 1);
139         }
140       } else if (*p == TLN_AYT) {
141         /* "Are You There?" */
142         /* response is: "Hell, yes!" */
143         static unsigned char sb[] = "\r\n[Hell, yes!]\r\n";
144         safe_write(sock, sb, sizeof sb);
145       } else if (*p == TLN_IAC) {
146         /* IAC character in data, escaped with another IAC */
147         *o++ = *p++;
148         mark = 1;
149       }
150       /* Anything else can probably be ignored */
151       p += mark - 1;
152       *len = *len - mark;
153     }
154   }
155   *o = *p;
156 }
157 
greet_new_bot(int idx)158 static void greet_new_bot(int idx)
159 {
160   int bfl = bot_flags(dcc[idx].user);
161   int i;
162 
163   dcc[idx].timeval = now;
164   dcc[idx].u.bot->version[0] = 0;
165   dcc[idx].u.bot->numver = 0;
166   if (bfl & BOT_REJECT) {
167     putlog(LOG_BOTS, "*", DCC_REJECT, dcc[idx].nick);
168     dprintf(idx, "bye %s\n", "rejected");
169     killsock(dcc[idx].sock);
170     lostdcc(idx);
171     return;
172   }
173   if (bfl & BOT_LEAF)
174     dcc[idx].status |= STAT_LEAF;
175   dcc[idx].status |= STAT_LINKING;
176 #ifndef NO_OLD_BOTNET
177   dprintf(idx, "version %d %d %s <%s>\n", egg_numver, HANDLEN, ver, network);
178 #else
179   dprintf(idx, "v %d %d %s <%s>\n", egg_numver, HANDLEN, ver, network);
180 #endif
181   for (i = 0; i < dcc_total; i++)
182     if (dcc[i].type == &DCC_FORK_BOT) {
183       killsock(dcc[i].sock);
184       lostdcc(i);
185     }
186 }
187 
bot_version(int idx,char * par)188 static void bot_version(int idx, char *par)
189 {
190   char x[1024];
191   int l;
192 
193   dcc[idx].timeval = now;
194   if (in_chain(dcc[idx].nick)) {
195     dprintf(idx, "error Sorry, already connected.\n");
196     dprintf(idx, "bye\n");
197     killsock(dcc[idx].sock);
198     lostdcc(idx);
199     return;
200   }
201   if ((par[0] >= '0') && (par[0] <= '9')) {
202     char *work;
203 
204     work = newsplit(&par);
205     dcc[idx].u.bot->numver = atoi(work);
206   } else
207     dcc[idx].u.bot->numver = 0;
208 
209 #ifndef NO_OLD_BOTNET
210   if (b_numver(idx) < NEAT_BOTNET) {
211 #if HANDLEN != 9
212     putlog(LOG_BOTS, "*", "Non-matching handle lengths with %s, they use 9 "
213            "characters.", dcc[idx].nick);
214     dprintf(idx, "error Non-matching handle length: mine %d, yours 9\n",
215             HANDLEN);
216     dprintf(idx, "bye %s\n", "bad handlen");
217     killsock(dcc[idx].sock);
218     lostdcc(idx);
219     return;
220 #else
221     dprintf(idx, "thisbot %s\n", botnetnick);
222 #endif
223   } else {
224 #endif
225     dprintf(idx, "tb %s\n", botnetnick);
226     l = atoi(newsplit(&par));
227     if (l != HANDLEN) {
228       putlog(LOG_BOTS, "*", "Non-matching handle lengths with %s, they use %d "
229              "characters.", dcc[idx].nick, l);
230       dprintf(idx, "error Non-matching handle length: mine %d, yours %d\n",
231               HANDLEN, l);
232       dprintf(idx, "bye %s\n", "bad handlen");
233       killsock(dcc[idx].sock);
234       lostdcc(idx);
235       return;
236     }
237 #ifndef NO_OLD_BOTNET
238   }
239 #endif
240   strlcpy(dcc[idx].u.bot->version, par, 120);
241   putlog(LOG_BOTS, "*", DCC_LINKED, dcc[idx].nick);
242   botnet_send_nlinked(idx, dcc[idx].nick, botnetnick, '!',
243                       dcc[idx].u.bot->numver);
244   touch_laston(dcc[idx].user, "linked", now);
245   dump_links(idx);
246   dcc[idx].type = &DCC_BOT;
247   addbot(dcc[idx].nick, dcc[idx].nick, botnetnick, '-', dcc[idx].u.bot->numver);
248   check_tcl_link(dcc[idx].nick, botnetnick);
249   egg_snprintf(x, sizeof x, "v %d", dcc[idx].u.bot->numver);
250   bot_share(idx, x);
251   dprintf(idx, "el\n");
252 }
253 
failed_link(int idx)254 void failed_link(int idx)
255 {
256   char s[NICKLEN + 18], s1[512];
257 
258   if (dcc[idx].u.bot->linker[0]) {
259     egg_snprintf(s, sizeof s, "Couldn't link to %s.", dcc[idx].nick);
260     strcpy(s1, dcc[idx].u.bot->linker);
261     add_note(s1, botnetnick, s, -2, 0);
262   }
263   if (dcc[idx].u.bot->numver >= -1)
264     putlog(LOG_BOTS, "*", DCC_LINKFAIL, dcc[idx].nick);
265   killsock(dcc[idx].sock);
266   strcpy(s, dcc[idx].nick);
267   lostdcc(idx);
268   autolink_cycle(s);          /* Check for more auto-connections */
269   killsock(dcc[idx].sock);
270   dcc[idx].timeval = now;
271   return;
272 }
273 
cont_link(int idx,char * buf,int i)274 static void cont_link(int idx, char *buf, int i)
275 {
276   char x[1024];
277   int atr = bot_flags(dcc[idx].user);
278   int users, bots;
279 
280   if (atr & BOT_HUB) {
281     /* Disconnect all +a bots because we just got a hub */
282     for (i = 0; i < dcc_total; i++) {
283       if ((i != idx) && (bot_flags(dcc[i].user) & BOT_ALT)) {
284         if ((dcc[i].type == &DCC_FORK_BOT) || (dcc[i].type == &DCC_BOT_NEW)) {
285           killsock(dcc[i].sock);
286           lostdcc(i);
287         }
288       }
289     }
290     /* Just those currently in the process of linking */
291     if (in_chain(dcc[idx].nick)) {
292       i = nextbot(dcc[idx].nick);
293       if (i > 0) {
294         bots = bots_in_subtree(findbot(dcc[idx].nick));
295         users = users_in_subtree(findbot(dcc[idx].nick));
296         egg_snprintf(x, sizeof x,
297                      "Unlinked %s (restructure) (lost %d bot%s and %d user%s)",
298                      dcc[i].nick, bots, (bots != 1) ? "s" : "",
299                      users, (users != 1) ? "s" : "");
300         putlog(LOG_BOTS, "*", "%s.", x);
301         botnet_send_unlinked(i, dcc[i].nick, x);
302         dprintf(i, "bye %s\n", "restructure");
303         killsock(dcc[i].sock);
304         lostdcc(i);
305       }
306     }
307   }
308   dcc[idx].type = &DCC_BOT_NEW;
309   dcc[idx].u.bot->numver = 0;
310 
311   /* Don't send our password here, just the username. The code later on
312    * will determine if the password needs to be sent in cleartext or if
313    * we can send an MD5 digest. <cybah>
314    */
315   dprintf(idx, "%s\n", botnetnick);
316   return;
317 }
318 
319 /* This function generates a digest by combining 'challenge' with
320  * 'password' and then sends it to the other bot. <Cybah>
321  */
dcc_bot_digest(int idx,char * challenge,char * password)322 static void dcc_bot_digest(int idx, char *challenge, char *password)
323 {
324   MD5_CTX md5context;
325   char digest_string[33];       /* 32 for digest in hex + null */
326   unsigned char digest[16];
327   int i;
328 
329   MD5_Init(&md5context);
330   MD5_Update(&md5context, (unsigned char *) challenge, strlen(challenge));
331   MD5_Update(&md5context, (unsigned char *) password, strlen(password));
332   MD5_Final(digest, &md5context);
333 
334   for (i = 0; i < 16; i++)
335     sprintf(digest_string + (i * 2), "%.2x", digest[i]);
336   dprintf(idx, "digest %s\n", digest_string);
337   explicit_bzero(digest_string, sizeof digest_string);
338   explicit_bzero(digest, sizeof digest);
339   putlog(LOG_BOTS, "*", "Received challenge from %s... sending response ...",
340          dcc[idx].nick);
341 }
342 
dcc_bot_new(int idx,char * buf,int x)343 static void dcc_bot_new(int idx, char *buf, int x)
344 {
345   struct userrec *u = get_user_by_handle(userlist, dcc[idx].nick);
346   char *code;
347 
348   if (raw_log) {
349     if (!strncmp(buf, "s ", 2))
350       putlog(LOG_BOTSHRIN, "*", "{b<-%s} %s", dcc[idx].nick, buf + 2);
351     else
352       putlog(LOG_BOTNETIN, "*", "[b<-%s] %s", dcc[idx].nick, buf);
353   }
354 
355   code = newsplit(&buf);
356   if (!strcasecmp(code, "*hello!"))
357     greet_new_bot(idx);
358   else if (!strcasecmp(code, "version") || !strcasecmp(code, "v"))
359     bot_version(idx, buf);
360   else if (!strcasecmp(code, "badpass"))
361     /* We entered the wrong password */
362     putlog(LOG_BOTS, "*", DCC_BADPASS, dcc[idx].nick);
363   else if (!strcasecmp(code, "passreq")) {
364     char *pass = get_user(&USERENTRY_PASS, u);
365 
366     if (!pass || !strcmp(pass, "-")) {
367       putlog(LOG_BOTS, "*", DCC_PASSREQ, dcc[idx].nick);
368       dprintf(idx, "-\n");
369     } else {
370       /* Determine if the other end supports an MD5 digest instead of a
371        * cleartext password. <Cybah>
372        */
373       if (buf && buf[0] && strchr(buf, '<') && strchr(buf + 1, '>'))
374         dcc_bot_digest(idx, buf, pass);
375       else
376         dprintf(idx, "%s\n", pass);
377     }
378   } else if (!strcasecmp(code, "error"))
379     putlog(LOG_BOTS, "*", DCC_LINKERROR, dcc[idx].nick, buf);
380   /* Ignore otherwise */
381 }
382 
eof_dcc_bot_new(int idx)383 static void eof_dcc_bot_new(int idx)
384 {
385   putlog(LOG_BOTS, "*", DCC_LOSTBOT, dcc[idx].nick, dcc[idx].port);
386   killsock(dcc[idx].sock);
387   lostdcc(idx);
388 }
389 
timeout_dcc_bot_new(int idx)390 static void timeout_dcc_bot_new(int idx)
391 {
392   putlog(LOG_BOTS, "*", DCC_TIMEOUT, dcc[idx].nick,
393          dcc[idx].host, dcc[idx].port);
394   killsock(dcc[idx].sock);
395   lostdcc(idx);
396 }
397 
display_dcc_bot_new(int idx,char * buf)398 static void display_dcc_bot_new(int idx, char *buf)
399 {
400   long tv;
401 
402   tv = now - dcc[idx].timeval;
403   sprintf(buf, "bot*  waited %lis", tv);
404 }
405 
expmem_dcc_bot_(void * x)406 static int expmem_dcc_bot_(void *x)
407 {
408   return sizeof(struct bot_info);
409 }
410 
free_dcc_bot_(int n,void * x)411 static void free_dcc_bot_(int n, void *x)
412 {
413   if (dcc[n].type == &DCC_BOT) {
414     unvia(n, findbot(dcc[n].nick));
415     rembot(dcc[n].nick);
416   }
417   nfree(x);
418 }
419 
out_dcc_bot(int idx,char * buf,void * x)420 static void out_dcc_bot(int idx, char *buf, void *x)
421 {
422   size_t len = strlen(buf);
423   /* We don't really use x here, so "use it" for the compiler */
424   (void)x;
425 
426   if (raw_log) {
427     /* strip \n from end as putlog appends this */
428     char *p = buf, *fnd = NULL;
429 
430     if (len && buf[len - 1] == '\n') {
431       /* Make a copy as buf could be const */
432       fnd = nmalloc(len);
433       strlcpy(fnd, buf, len);
434       p = fnd;
435     }
436 
437     if (!strncmp(p, "s ", 2))
438       putlog(LOG_BOTSHROUT, "*", "{b->%s} %s", dcc[idx].nick, p + 2);
439     else
440       putlog(LOG_BOTNETOUT, "*", "[b->%s] %s", dcc[idx].nick, p);
441 
442     if (fnd)
443       nfree(fnd);
444 
445   }
446 
447   tputs(dcc[idx].sock, buf, len);
448 }
449 
450 struct dcc_table DCC_BOT_NEW = {
451   "BOT_NEW",
452   0,
453   eof_dcc_bot_new,
454   dcc_bot_new,
455   &bot_timeout,
456   timeout_dcc_bot_new,
457   display_dcc_bot_new,
458   expmem_dcc_bot_,
459   free_dcc_bot_,
460   out_dcc_bot
461 };
462 
463 /* Hash function for tandem bot commands */
464 extern botcmd_t C_bot[];
465 
dcc_bot(int idx,char * code,int i)466 static void dcc_bot(int idx, char *code, int i)
467 {
468   char *msg;
469   int f;
470 
471   if (raw_log) {
472     if (!strncmp(code, "s ", 2))
473       putlog(LOG_BOTSHRIN, "*", "{b<-%s} %s", dcc[idx].nick, code + 2);
474     else
475       putlog(LOG_BOTNETIN, "*", "[b<-%s] %s", dcc[idx].nick, code);
476   }
477   msg = strchr(code, ' ');
478   if (msg) {
479     *msg = 0;
480     msg++;
481   } else
482     msg = "";
483   for (f = i = 0; C_bot[i].name && !f; i++) {
484     int y = strcasecmp(code, C_bot[i].name);
485 
486     if (!y) {
487       /* Found a match */
488       (C_bot[i].func) (idx, msg);
489       f = 1;
490     } else if (y < 0)
491       return;
492   }
493 }
494 
eof_dcc_bot(int idx)495 static void eof_dcc_bot(int idx)
496 {
497   char x[1024];
498   int bots, users;
499 
500   bots = bots_in_subtree(findbot(dcc[idx].nick));
501   users = users_in_subtree(findbot(dcc[idx].nick));
502   egg_snprintf(x, sizeof x,
503                "Lost bot: %s (lost %d bot%s and %d user%s)",
504                dcc[idx].nick, bots, (bots != 1) ? "s" : "", users,
505                (users != 1) ? "s" : "");
506   putlog(LOG_BOTS, "*", "%s.", x);
507   botnet_send_unlinked(idx, dcc[idx].nick, x);
508   killsock(dcc[idx].sock);
509   lostdcc(idx);
510 }
511 
display_dcc_bot(int idx,char * buf)512 static void display_dcc_bot(int idx, char *buf)
513 {
514   int i = simple_sprintf(buf, "bot   flags: ");
515 
516   buf[i++] = b_status(idx) & STAT_PINGED ? 'P' : 'p';
517   buf[i++] = b_status(idx) & STAT_SHARE ? 'U' : 'u';
518   buf[i++] = b_status(idx) & STAT_CALLED ? 'C' : 'c';
519   buf[i++] = b_status(idx) & STAT_OFFERED ? 'O' : 'o';
520   buf[i++] = b_status(idx) & STAT_SENDING ? 'S' : 's';
521   buf[i++] = b_status(idx) & STAT_GETTING ? 'G' : 'g';
522   buf[i++] = b_status(idx) & STAT_WARNED ? 'W' : 'w';
523   buf[i++] = b_status(idx) & STAT_LEAF ? 'L' : 'l';
524   buf[i++] = b_status(idx) & STAT_LINKING ? 'I' : 'i';
525   buf[i++] = b_status(idx) & STAT_AGGRESSIVE ? 'a' : 'A';
526   buf[i++] = 0;
527 }
528 
display_dcc_fork_bot(int idx,char * buf)529 static void display_dcc_fork_bot(int idx, char *buf)
530 {
531   sprintf(buf, "conn  bot");
532 }
533 
534 struct dcc_table DCC_BOT = {
535   "BOT",
536   DCT_BOT | DCT_VALIDIDX,
537   eof_dcc_bot,
538   dcc_bot,
539   NULL,
540   NULL,
541   display_dcc_bot,
542   expmem_dcc_bot_,
543   free_dcc_bot_,
544   out_dcc_bot
545 };
546 
547 struct dcc_table DCC_FORK_BOT = {
548   "FORK_BOT",
549   0,
550   failed_link,
551   cont_link,
552   &connect_timeout,
553   failed_link,
554   display_dcc_fork_bot,
555   expmem_dcc_bot_,
556   free_dcc_bot_,
557   out_dcc_bot
558 };
559 
560 /* This function generates a digest by combining a challenge consisting
561  * of our process id + connection time + botnetnick.  The digest is then
562  * compared to the one given by the remote bot.
563  *
564  * Returns 1 if the digest matches, otherwise returns 0.
565  * <Cybah>
566  */
dcc_bot_check_digest(int idx,char * remote_digest)567 static int dcc_bot_check_digest(int idx, char *remote_digest)
568 {
569   MD5_CTX md5context;
570   char digest_string[33];       /* 32 for digest in hex + null */
571   unsigned char digest[16];
572   int i, ret;
573   char *password = get_user(&USERENTRY_PASS, dcc[idx].user);
574 
575   if (!password)
576     return 1;
577 
578   MD5_Init(&md5context);
579 
580   egg_snprintf(digest_string, 33, "<%lx%x@", (long) getpid(),
581                (unsigned int) dcc[idx].timeval);
582   MD5_Update(&md5context, (unsigned char *) digest_string,
583              strlen(digest_string));
584   MD5_Update(&md5context, (unsigned char *) botnetnick, strlen(botnetnick));
585   MD5_Update(&md5context, (unsigned char *) ">", 1);
586   MD5_Update(&md5context, (unsigned char *) password, strlen(password));
587 
588   MD5_Final(digest, &md5context);
589 
590   for (i = 0; i < 16; i++)
591     sprintf(digest_string + (i * 2), "%.2x", digest[i]);
592 
593   ret = strcmp(digest_string, remote_digest);
594   explicit_bzero(digest_string, sizeof digest_string);
595   explicit_bzero(digest, sizeof digest);
596 
597   if (!ret)
598     return 1;
599 
600   putlog(LOG_BOTS, "*", "Response (password hash) from %s incorrect",
601          dcc[idx].nick);
602   return 0;
603 }
604 
dcc_chat_pass(int idx,char * buf,int atr)605 static void dcc_chat_pass(int idx, char *buf, int atr)
606 {
607   char pass[PASSWORDLEN];
608 
609   if (!atr)
610     return;
611   if (dcc[idx].status & STAT_TELNET)
612     strip_telnet(dcc[idx].sock, buf, &atr);
613   else if (detect_telnet((unsigned char *) buf))
614     buf += 3; /* 'IAC','DO(DONT)','STATUS' */
615   atr = dcc[idx].user ? dcc[idx].user->flags : 0;
616 
617   if (atr & USER_BOT) {
618     if (raw_log) {
619       if (!strncmp(buf, "s ", 2))
620         putlog(LOG_BOTSHRIN, "*", "{b<-%s} %s", dcc[idx].nick, buf + 2);
621       else
622         putlog(LOG_BOTNETIN, "*", "[b<-%s] %s", dcc[idx].nick, buf);
623     }
624     /* No password set? */
625     if (u_pass_match(dcc[idx].user, "-")) {
626       makepass(pass);
627       set_user(&USERENTRY_PASS, dcc[idx].user, pass);
628       changeover_dcc(idx, &DCC_BOT_NEW, sizeof(struct bot_info));
629 
630       dcc[idx].status = STAT_CALLED;
631       dprintf(idx, "*hello!\n");
632       greet_new_bot(idx);
633 #ifdef NO_OLD_BOTNET
634       dprintf(idx, "h %s\n", pass);
635 #else
636       dprintf(idx, "handshake %s\n", pass);
637 #endif
638       explicit_bzero(pass, sizeof pass);
639       return;
640     }
641   }
642   /* Check for MD5 digest from remote _bot_. <cybah> */
643   if ((atr & USER_BOT) && !strncasecmp(buf, "digest ", 7)) {
644     if (dcc_bot_check_digest(idx, buf + 7)) {
645       nfree(dcc[idx].u.chat);
646       dcc[idx].type = &DCC_BOT_NEW;
647       dcc[idx].u.bot = get_data_ptr(sizeof(struct bot_info));
648       dcc[idx].status = STAT_CALLED;
649       dprintf(idx, "*hello!\n");
650       greet_new_bot(idx);
651       return;
652     } else {
653       /* Invalid password/digest */
654       /* change here temp to use bot output */
655       struct dcc_table *old = dcc[idx].type;
656       dcc[idx].type = &DCC_BOT_NEW;
657       dprintf(idx, "badpass\n");
658       /* change back to original for general kill */
659       dcc[idx].type = old;
660       putlog(LOG_MISC, "*", DCC_BADLOGIN, dcc[idx].nick, dcc[idx].host,
661              dcc[idx].port);
662       killsock(dcc[idx].sock);
663       lostdcc(idx);
664       return;
665     }
666   }
667 
668 #ifdef TLS
669   /* Skip checking the password if the user is already identified by
670    * fingerprint.
671    */
672   if (dcc[idx].status & STAT_FPRINT || u_pass_match(dcc[idx].user, buf)) {
673 #else
674   if (u_pass_match(dcc[idx].user, buf)) {
675 #endif
676     if (atr & USER_BOT) {
677       nfree(dcc[idx].u.chat);
678       dcc[idx].type = &DCC_BOT_NEW;
679       dcc[idx].u.bot = get_data_ptr(sizeof(struct bot_info));
680 
681       dcc[idx].status = STAT_CALLED;
682       dprintf(idx, "*hello!\n");
683       greet_new_bot(idx);
684     } else {
685       /* Log entry for successful login -slennox 3/28/1999 */
686       putlog(LOG_MISC, "*", DCC_LOGGEDIN, dcc[idx].nick,
687              dcc[idx].host, dcc[idx].port);
688       if (dcc[idx].u.chat->away) {
689         nfree(dcc[idx].u.chat->away);
690         dcc[idx].u.chat->away = NULL;
691       }
692       dcc[idx].type = &DCC_CHAT;
693       dcc[idx].status &= ~STAT_CHAT;
694       dcc[idx].u.chat->con_flags = (atr & USER_MASTER) ? conmask : 0;
695       dcc[idx].u.chat->channel = -2;
696       /* Turn echo back on for telnet sessions (send IAC WON'T ECHO). */
697       if (dcc[idx].status & STAT_TELNET)
698         tputs(dcc[idx].sock, TLN_IAC_C TLN_WONT_C TLN_ECHO_C "\n", 4);
699       dcc_chatter(idx);
700     }
701   } else {
702     if (atr & USER_BOT) {
703       /* change here temp to use bot output */
704       struct dcc_table *old = dcc[idx].type;
705       dcc[idx].type = &DCC_BOT_NEW;
706       dprintf(idx, "badpass\n");
707       dcc[idx].type = old;
708     } else
709       dprintf(idx, DCC_HOUSTON);
710     putlog(LOG_MISC, "*", DCC_BADLOGIN, dcc[idx].nick,
711            dcc[idx].host, dcc[idx].port);
712     if (dcc[idx].u.chat->away) {        /* su from a dumb user */
713       /* Turn echo back on for telnet sessions (send IAC WON'T ECHO). */
714       if (dcc[idx].status & STAT_TELNET)
715         tputs(dcc[idx].sock, TLN_IAC_C TLN_WONT_C TLN_ECHO_C "\n", 4);
716       dcc[idx].user = get_user_by_handle(userlist, dcc[idx].u.chat->away);
717       strlcpy(dcc[idx].nick, dcc[idx].u.chat->away, sizeof dcc[idx].nick);
718       nfree(dcc[idx].u.chat->away);
719       nfree(dcc[idx].u.chat->su_nick);
720       dcc[idx].u.chat->away = NULL;
721       dcc[idx].u.chat->su_nick = NULL;
722       dcc[idx].type = &DCC_CHAT;
723       if (dcc[idx].u.chat->channel < GLOBAL_CHANS)
724         botnet_send_join_idx(idx, -1);
725       chanout_but(-1, dcc[idx].u.chat->channel, DCC_JOIN, dcc[idx].nick);
726     } else {
727       killsock(dcc[idx].sock);
728       lostdcc(idx);
729     }
730   }
731 }
732 
733 static void eof_dcc_general(int idx)
734 {
735   putlog(LOG_MISC, "*", DCC_LOSTDCC, dcc[idx].nick,
736          dcc[idx].host, dcc[idx].port);
737   killsock(dcc[idx].sock);
738   lostdcc(idx);
739 }
740 
741 static void tout_dcc_chat_pass(int idx)
742 {
743   dprintf(idx, "Timeout.\n");
744   putlog(LOG_MISC, "*", DCC_PWDTIMEOUT, dcc[idx].nick, dcc[idx].host);
745   killsock(dcc[idx].sock);
746   lostdcc(idx);
747 }
748 
749 static void display_dcc_chat_pass(int idx, char *buf)
750 {
751   long tv;
752 
753   tv = now - dcc[idx].timeval;
754   sprintf(buf, "pass  waited %lis", tv);
755 }
756 
757 static int expmem_dcc_general(void *x)
758 {
759   struct chat_info *p = (struct chat_info *) x;
760   int tot = sizeof(struct chat_info);
761 
762   if (p->away)
763     tot += strlen(p->away) + 1;
764   if (p->buffer) {
765     struct msgq *q = p->buffer;
766 
767     while (q) {
768       tot += sizeof(struct list_type);
769 
770       tot += q->len + 1;
771       q = q->next;
772     }
773   }
774   if (p->su_nick)
775     tot += strlen(p->su_nick) + 1;
776   return tot;
777 }
778 
779 static void kill_dcc_general(int idx, void *x)
780 {
781   struct chat_info *p = (struct chat_info *) x;
782 
783   if (p) {
784     if (p->buffer) {
785       struct msgq *r, *q;
786 
787       for (r = dcc[idx].u.chat->buffer; r; r = q) {
788         q = r->next;
789         nfree(r->msg);
790         nfree(r);
791       }
792     }
793     if (p->away) {
794       nfree(p->away);
795     }
796     nfree(p);
797   }
798 }
799 
800 /* Remove the color control codes that mIRC,pIRCh etc use to make
801  * their client seem so fecking cool! (Sorry, Khaled, you are a nice
802  * guy, but when you added this feature you forced people to either
803  * use your *SHAREWARE* client or face screenfulls of crap!)
804  */
805 void strip_mirc_codes(int flags, char *text)
806 {
807   char *dd = text;
808 
809   while (*text) {
810     switch (*text) {
811     case 3:                    /* mIRC colors? */
812       if (flags & STRIP_COLOR) {
813         if (egg_isdigit(text[1])) { /* Is the first char a number? */
814           text += 2;            /* Skip over the ^C and the first digit */
815           if (egg_isdigit(*text))
816             text++;             /* Is this a double digit number? */
817           if (*text == ',') {   /* Do we have a background color next? */
818             if (egg_isdigit(text[1]))
819               text += 2;        /* Skip over the first background digit */
820             if (egg_isdigit(*text))
821               text++;           /* Is it a double digit? */
822           }
823         } else
824           text++;
825         continue;
826       }
827       break;
828     case 2:                    /* Bold text */
829       if (flags & STRIP_BOLD) {
830         text++;
831         continue;
832       }
833       break;
834     case 0x16:                 /* Reverse video */
835       if (flags & STRIP_REVERSE) {
836         text++;
837         continue;
838       }
839       break;
840     case 0x1f:                 /* Underlined text */
841       if (flags & STRIP_UNDERLINE) {
842         text++;
843         continue;
844       }
845       break;
846     case 033:
847       if (flags & STRIP_ANSI) {
848         text++;
849         if (*text == '[') {
850           text++;
851           while ((*text == ';') || egg_isdigit(*text))
852             text++;
853           if (*text)
854             text++;             /* also kill the following char */
855         }
856         continue;
857       }
858       break;
859     case 7:
860       if (flags & STRIP_BELLS) {
861         text++;
862         continue;
863       }
864       break;
865     case 017:                  /* Ordinary (mIRC ctrl+o) */
866       if (flags & STRIP_ORDINARY) {
867         text++;
868         continue;
869       }
870       break;
871     case 29:                   /* Italics */
872       if (flags & STRIP_ITALICS) {
873         text++;
874         continue;
875       }
876       break;
877     }
878     *dd++ = *text++;            /* Move on to the next char */
879   }
880   *dd = 0;
881 }
882 
883 static void append_line(int idx, char *line)
884 {
885   int l = strlen(line);
886   struct msgq *p, *q;
887   struct chat_info *c = (dcc[idx].type == &DCC_CHAT) ? dcc[idx].u.chat :
888                         dcc[idx].u.file->chat;
889 
890   if (c->current_lines > 1000) {
891     /* They're probably trying to fill up the bot nuke the sods :) */
892     for (p = c->buffer; p; p = q) {
893       q = p->next;
894       nfree(p->msg);
895       nfree(p);
896     }
897     c->buffer = 0;
898     dcc[idx].status &= ~STAT_PAGE;
899     do_boot(idx, botnetnick, "too many pages - sendq full");
900     return;
901   }
902   if ((c->line_count < c->max_line) && (c->buffer == NULL)) {
903     c->line_count++;
904     tputs(dcc[idx].sock, line, l);
905   } else {
906     c->current_lines++;
907     if (c->buffer == NULL)
908       q = NULL;
909     else
910       for (q = c->buffer; q->next; q = q->next);
911 
912     p = get_data_ptr(sizeof(struct msgq));
913 
914     p->len = l;
915     p->msg = get_data_ptr(l + 1);
916     p->next = NULL;
917     strcpy(p->msg, line);
918     if (q == NULL)
919       c->buffer = p;
920     else
921       q->next = p;
922   }
923 }
924 
925 static void out_dcc_general(int idx, char *buf, void *x)
926 {
927   struct chat_info *p = (struct chat_info *) x;
928   char *y = buf;
929 
930   strip_mirc_codes(p->strip_flags, buf);
931   if (dcc[idx].status & STAT_TELNET)
932     y = escape_telnet(buf);
933   if (dcc[idx].status & STAT_PAGE)
934     append_line(idx, y);
935   else
936     tputs(dcc[idx].sock, y, strlen(y));
937 }
938 
939 struct dcc_table DCC_CHAT_PASS = {
940   "CHAT_PASS",
941   0,
942   eof_dcc_general,
943   dcc_chat_pass,
944   &password_timeout,
945   tout_dcc_chat_pass,
946   display_dcc_chat_pass,
947   expmem_dcc_general,
948   kill_dcc_general,
949   out_dcc_general
950 };
951 
952 /* Make sure ANSI code is just for color-changing */
953 int check_ansi(char *v)
954 {
955   int count = 2;
956 
957   if (*v++ != '\033')
958     return 1;
959   if (*v++ != '[')
960     return 1;
961   while (*v) {
962     if (*v == 'm')
963       return 0;
964     if ((*v != ';') && ((*v < '0') || (*v > '9')))
965       return count;
966     v++;
967     count++;
968   }
969   return count;
970 }
971 
972 static void eof_dcc_chat(int idx)
973 {
974   putlog(LOG_MISC, "*", DCC_LOSTDCC, dcc[idx].nick,
975          dcc[idx].host, dcc[idx].port);
976   if (dcc[idx].u.chat->channel >= 0) {
977     chanout_but(idx, dcc[idx].u.chat->channel, "*** %s lost dcc link.\n",
978                 dcc[idx].nick);
979     if (dcc[idx].u.chat->channel < GLOBAL_CHANS)
980       botnet_send_part_idx(idx, "lost dcc link");
981     check_tcl_chpt(botnetnick, dcc[idx].nick, dcc[idx].sock,
982                    dcc[idx].u.chat->channel);
983   }
984   check_tcl_chof(dcc[idx].nick, dcc[idx].sock);
985   killsock(dcc[idx].sock);
986   lostdcc(idx);
987 }
988 
989 static void dcc_chat(int idx, char *buf, int i)
990 {
991   int nathan = 0, doron = 0, fixed = 0;
992   char *v, *d, filtbuf[2048];
993 
994   if (dcc[idx].status & STAT_TELNET)
995     strip_telnet(dcc[idx].sock, buf, &i);
996   if (buf[0] && (buf[0] != '.') &&
997       detect_dcc_flood(&dcc[idx].timeval, dcc[idx].u.chat, idx))
998     return;
999   dcc[idx].timeval = now;
1000   if (buf[0]) {
1001     const char *filt = check_tcl_filt(idx, buf);
1002     if (filt != buf) {
1003       strlcpy(filtbuf, filt, sizeof(filtbuf));
1004       buf = filtbuf;
1005     }
1006   }
1007   if (buf[0]) {
1008     /* Check for beeps and cancel annoying ones */
1009     v = buf;
1010     d = buf;
1011     while (*v)
1012       switch (*v) {
1013       case 7:                  /* Beep - no more than 3 */
1014         nathan++;
1015         if (nathan > 3)
1016           v++;
1017         else
1018           *d++ = *v++;
1019         break;
1020       case 8:                  /* Backspace - for lame telnet's :) */
1021         if (d > buf) {
1022           d--;
1023         }
1024         v++;
1025         break;
1026       case 27:                 /* ESC - ansi code? */
1027         doron = check_ansi(v);
1028         /* If it's valid, append a return-to-normal code at the end */
1029         if (!doron) {
1030           *d++ = *v++;
1031           fixed = 1;
1032         } else
1033           v += doron;
1034         break;
1035       case '\r':               /* Weird pseudo-linefeed */
1036         v++;
1037         break;
1038       default:
1039         *d++ = *v++;
1040       }
1041     if (fixed)
1042       strcpy(d, "\033[0m");
1043     else
1044       *d = 0;
1045     if (buf[0]) {               /* Nothing to say - maybe paging... */
1046       if ((buf[0] == '.') || (dcc[idx].u.chat->channel < 0)) {
1047         if (buf[0] == '.')
1048           buf++;
1049         v = newsplit(&buf);
1050         rmspace(buf);
1051         if (check_tcl_dcc(v, idx, buf)) {
1052           if (dcc[idx].u.chat->channel >= 0)
1053             check_tcl_chpt(botnetnick, dcc[idx].nick, dcc[idx].sock,
1054                            dcc[idx].u.chat->channel);
1055           check_tcl_chof(dcc[idx].nick, dcc[idx].sock);
1056           dprintf(idx, "*** Ja mata!\n");
1057           flush_lines(idx, dcc[idx].u.chat);
1058           putlog(LOG_MISC, "*", DCC_CLOSED, dcc[idx].nick, dcc[idx].host);
1059           if (dcc[idx].u.chat->channel >= 0) {
1060             chanout_but(-1, dcc[idx].u.chat->channel,
1061                         "*** %s left the party line%s%s\n",
1062                         dcc[idx].nick, buf[0] ? ": " : ".", buf);
1063             if (dcc[idx].u.chat->channel < GLOBAL_CHANS)
1064               botnet_send_part_idx(idx, buf);
1065           }
1066           if (dcc[idx].u.chat->su_nick) {
1067             dcc[idx].user = get_user_by_handle(userlist,
1068                                                dcc[idx].u.chat->su_nick);
1069             strlcpy(dcc[idx].nick, dcc[idx].u.chat->su_nick, sizeof dcc[idx].nick);
1070             dcc[idx].type = &DCC_CHAT;
1071             dprintf(idx, "Returning to real nick %s!\n",
1072                     dcc[idx].u.chat->su_nick);
1073             nfree(dcc[idx].u.chat->su_nick);
1074             dcc[idx].u.chat->su_nick = NULL;
1075             dcc_chatter(idx);
1076             if (dcc[idx].u.chat->channel < GLOBAL_CHANS &&
1077                 dcc[idx].u.chat->channel >= 0)
1078               botnet_send_join_idx(idx, -1);
1079             return;
1080           } else if ((dcc[idx].sock != STDOUT) || backgrd) {
1081             killsock(dcc[idx].sock);
1082             lostdcc(idx);
1083             return;
1084           } else {
1085             dprintf(DP_STDOUT, "\n### SIMULATION RESET\n\n");
1086             dcc_chatter(idx);
1087             return;
1088           }
1089         }
1090       } else if (buf[0] == ',') {
1091         int me = 0;
1092 
1093         if ((buf[1] == 'm') && (buf[2] == 'e') && buf[3] == ' ')
1094           me = 1;
1095         for (i = 0; i < dcc_total; i++) {
1096           int ok = 0;
1097 
1098           if ((dcc[i].type->flags & DCT_MASTER) &&
1099               ((dcc[i].type != &DCC_CHAT) || (dcc[i].u.chat->channel >= 0)) &&
1100               ((i != idx) || (dcc[idx].status & STAT_ECHO)))
1101             ok = 1;
1102           if (ok) {
1103             struct userrec *u = get_user_by_handle(userlist, dcc[i].nick);
1104 
1105             if (u && (u->flags & USER_MASTER)) {
1106               if (me)
1107                 dprintf(i, "-> %s%s\n", dcc[idx].nick, buf + 3);
1108               else
1109                 dprintf(i, "-%s-> %s\n", dcc[idx].nick, buf + 1);
1110             }
1111           }
1112         }
1113       } else if (buf[0] == '\'') {
1114         int me = 0;
1115 
1116         if ((buf[1] == 'm') && (buf[2] == 'e') &&
1117             ((buf[3] == ' ') || (buf[3] == '\'') || (buf[3] == ',')))
1118           me = 1;
1119         for (i = 0; i < dcc_total; i++) {
1120           if (dcc[i].type->flags & DCT_CHAT) {
1121             if (me)
1122               dprintf(i, "=> %s%s\n", dcc[idx].nick, buf + 3);
1123             else
1124               dprintf(i, "=%s=> %s\n", dcc[idx].nick, buf + 1);
1125           }
1126         }
1127       } else {
1128         if (dcc[idx].u.chat->away != NULL)
1129           not_away(idx);
1130         if (dcc[idx].status & STAT_ECHO)
1131           chanout_but(-1, dcc[idx].u.chat->channel,
1132                       "<%s> %s\n", dcc[idx].nick, buf);
1133         else
1134           chanout_but(idx, dcc[idx].u.chat->channel, "<%s> %s\n",
1135                       dcc[idx].nick, buf);
1136         botnet_send_chan(-1, botnetnick, dcc[idx].nick,
1137                          dcc[idx].u.chat->channel, buf);
1138         check_tcl_chat(dcc[idx].nick, dcc[idx].u.chat->channel, buf);
1139       }
1140     }
1141   }
1142   if (dcc[idx].type == &DCC_CHAT)       /* Could have change to files */
1143     if (dcc[idx].status & STAT_PAGE)
1144       flush_lines(idx, dcc[idx].u.chat);
1145 }
1146 
1147 static void display_dcc_chat(int idx, char *buf)
1148 {
1149   int i = simple_sprintf(buf, "chat  flags: ");
1150 
1151   buf[i++] = dcc[idx].status & STAT_CHAT ? 'C' : 'c';
1152   buf[i++] = dcc[idx].status & STAT_PARTY ? 'P' : 'p';
1153   buf[i++] = dcc[idx].status & STAT_TELNET ? 'T' : 't';
1154   buf[i++] = dcc[idx].status & STAT_ECHO ? 'E' : 'e';
1155   buf[i++] = dcc[idx].status & STAT_PAGE ? 'P' : 'p';
1156   simple_sprintf(buf + i, "/%d", dcc[idx].u.chat->channel);
1157 }
1158 
1159 struct dcc_table DCC_CHAT = {
1160   "CHAT",
1161   DCT_CHAT | DCT_MASTER | DCT_SHOWWHO | DCT_VALIDIDX | DCT_SIMUL |
1162     DCT_CANBOOT | DCT_REMOTEWHO,
1163   eof_dcc_chat,
1164   dcc_chat,
1165   NULL,
1166   NULL,
1167   display_dcc_chat,
1168   expmem_dcc_general,
1169   kill_dcc_general,
1170   out_dcc_general
1171 };
1172 
1173 static int lasttelnets;
1174 static char lasttelnethost[UHOSTLEN + 15];
1175 static time_t lasttelnettime;
1176 
1177 /* A modified detect_flood for incoming telnet flood protection.
1178  */
1179 static int detect_telnet_flood(char *floodhost)
1180 {
1181   struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0 };
1182 
1183   get_user_flagrec(get_user_by_host(floodhost), &fr, NULL);
1184   if (!flood_telnet_thr || (glob_friend(fr) && !par_telnet_flood))
1185     return 0;                   /* No flood protection */
1186   if (strcasecmp(lasttelnethost, floodhost)) {      /* New... */
1187     strlcpy(lasttelnethost, floodhost, sizeof lasttelnethost);
1188     lasttelnettime = now;
1189     lasttelnets = 0;
1190     return 0;
1191   }
1192   if (lasttelnettime < now - flood_telnet_time) {
1193     /* Flood timer expired, reset it */
1194     lasttelnettime = now;
1195     lasttelnets = 0;
1196     return 0;
1197   }
1198   lasttelnets++;
1199   if (lasttelnets >= flood_telnet_thr) {        /* FLOOD! */
1200     /* Reset counters */
1201     lasttelnets = 0;
1202     lasttelnettime = 0;
1203     lasttelnethost[0] = 0;
1204     putlog(LOG_MISC, "*", IRC_TELNETFLOOD, floodhost);
1205     addignore(floodhost, origbotname, "Telnet connection flood",
1206               now + (60 * ignore_time));
1207     return 1;
1208   }
1209   return 0;
1210 }
1211 
1212 static void dcc_telnet(int idx, char *buf, int i)
1213 {
1214   uint16_t port;
1215   int j = 0, sock;
1216 
1217   if (dcc_total + 1 > max_dcc && increase_socks_max()) {
1218     sockname_t name;
1219     j = answer(dcc[idx].sock, &name, &port, 0);
1220     if (j != -1) {
1221       dprintf(-j, "Sorry, too many connections already.\r\n");
1222       killsock(j);
1223     }
1224     return;
1225   }
1226   i = new_dcc(&DCC_DNSWAIT, sizeof(struct dns_info));
1227   sock = answer(dcc[idx].sock, &dcc[i].sockname, &port, 0);
1228   while ((sock == -1) && (errno == EAGAIN))
1229     sock = answer(dcc[idx].sock, &dcc[i].sockname, &port, 0);
1230   if (sock < 0) {
1231     putlog(LOG_MISC, "*", DCC_FAILED, strerror(errno));
1232     return;
1233   }
1234   /* Buffer data received on this socket.  */
1235   sockoptions(sock, EGG_OPTION_SET, SOCK_BUFFER);
1236 
1237   if (port < 1024) {
1238     putlog(LOG_BOTS, "*", DCC_BADSRC, iptostr(&dcc[i].sockname.addr.sa), port);
1239     killsock(sock);
1240     lostdcc(i);
1241     return;
1242   }
1243 
1244   dcc[i].u.dns->ip = &dcc[i].sockname;
1245   dcc[i].sock = sock;
1246   dcc[i].port = port;
1247 #ifdef TLS
1248   dcc[i].ssl = dcc[idx].ssl;
1249   if (dcc[i].ssl) {
1250     /* In order to support certificate CN validation we need to wait for the dns
1251      * lookup to complete. Additional we need to mark the socket virtual so we
1252      * won't read SSL client-hello before ssl_handshake has happened.
1253      * NOTE: TLS_VERIFYCN configurations value is inverted
1254      */
1255     if (!(tls_vfyclients & TLS_VERIFYCN))
1256       threaddata()->socklist[findsock(sock)].flags |= SOCK_VIRTUAL;
1257     else if (ssl_handshake(dcc[i].sock, TLS_LISTEN, tls_vfyclients,
1258         LOG_MISC, NULL, NULL)) {
1259       killsock(dcc[i].sock);
1260       lostdcc(i);
1261       return;
1262     }
1263   }
1264 #endif
1265   dcc[i].timeval = now;
1266   strcpy(dcc[i].nick, "*");
1267   dcc[i].u.dns->dns_success = dcc_telnet_hostresolved;
1268   dcc[i].u.dns->dns_failure = dcc_telnet_hostresolved;
1269   dcc[i].u.dns->dns_type = RES_HOSTBYIP;
1270   dcc[i].u.dns->ibuf = dcc[idx].sock;
1271   dcc[i].u.dns->type = &DCC_IDENTWAIT;
1272   dcc_dnshostbyip(&dcc[i].sockname);
1273 }
1274 
1275 static void dcc_telnet_hostresolved(int i)
1276 {
1277   int idx;
1278   int j = 0, sock;
1279   char s[sizeof lasttelnethost], *userhost;
1280 
1281   strlcpy(dcc[i].host, dcc[i].u.dns->host, UHOSTLEN);
1282 
1283   for (idx = 0; idx < dcc_total; idx++)
1284     if ((dcc[idx].type == &DCC_TELNET) &&
1285         (dcc[idx].sock == dcc[i].u.dns->ibuf)) {
1286       break;
1287     }
1288   if (dcc_total == idx) {
1289     putlog(LOG_BOTS, "*", "Lost listening socket while resolving %s",
1290            dcc[i].host);
1291     killsock(dcc[i].sock);
1292     lostdcc(i);
1293     return;
1294   }
1295   if (dcc[idx].host[0] == '@') {
1296     /* Restrict by hostname */
1297     if (!wild_match(dcc[idx].host + 1, dcc[i].host)) {
1298       putlog(LOG_BOTS, "*", DCC_BADHOST, dcc[i].host);
1299       killsock(dcc[i].sock);
1300       lostdcc(i);
1301       return;
1302     }
1303   }
1304   snprintf(s, sizeof s, "-telnet!telnet@%s", dcc[i].host);
1305   userhost = s + strlen("-telnet!");
1306   if (match_ignore(s) || detect_telnet_flood(s)) {
1307     killsock(dcc[i].sock);
1308     lostdcc(i);
1309     return;
1310   }
1311 
1312   putlog(LOG_MISC, "*", DCC_TELCONN, dcc[i].host, dcc[i].port);
1313 
1314 #ifdef TLS
1315   /* Remove SOCK_VIRTUAL and call ssl_handshake
1316    * Check out dcc_telnet for more details
1317    */
1318   if (dcc[i].ssl && !(tls_vfyclients & TLS_VERIFYCN)) {
1319     threaddata()->socklist[findsock(dcc[i].sock)].flags &= ~SOCK_VIRTUAL;
1320     if (ssl_handshake(dcc[i].sock, TLS_LISTEN, tls_vfyclients,
1321         LOG_MISC, dcc[i].host, NULL)) {
1322       killsock(dcc[i].sock);
1323       lostdcc(i);
1324       return;
1325     }
1326   }
1327 #endif
1328 
1329   /* Skip ident lookup for public script listeners */
1330   if ((dcc[idx].status & LSTN_PUBLIC) && !strcmp(dcc[idx].nick, "(script)")) {
1331     changeover_dcc(i, &DCC_SOCKET, 0);
1332     dcc[i].u.other = NULL;
1333     strcpy(dcc[i].nick, "*");
1334     strlcpy(dcc[i].host, userhost, UHOSTLEN);
1335     check_tcl_listen(dcc[idx].host, dcc[i].sock);
1336     return;
1337   }
1338 
1339   /* Skip ident lookup if disabled */
1340   if (identtimeout <= 0) {
1341     dcc[i].u.ident_sock = dcc[idx].sock;
1342     dcc_telnet_got_ident(i, userhost);
1343     return;
1344   }
1345 
1346   changeover_dcc(i, &DCC_IDENTWAIT, 0);
1347   dcc[i].timeval = now;
1348   dcc[i].u.ident_sock = dcc[idx].sock;
1349   sock = -1;
1350   j = new_dcc(&DCC_IDENT, 0);
1351   if (j < 0)
1352     putlog(LOG_MISC, "*", DCC_IDENTFAIL, dcc[i].host, strerror(errno));
1353   else {
1354     memcpy(&dcc[j].sockname, &dcc[i].sockname, sizeof(sockname_t));
1355     dcc[j].sock = getsock(dcc[j].sockname.family, 0);
1356     if (dcc[j].sock >= 0) {
1357       sockname_t name;
1358       name.addrlen = sizeof(name.addr);
1359       getsockname(dcc[i].sock, &name.addr.sa, &name.addrlen);
1360       bind(dcc[j].sock, &name.addr.sa, name.addrlen);
1361       setsnport(dcc[j].sockname, 113);
1362       if (connect(dcc[j].sock, &dcc[j].sockname.addr.sa,
1363           dcc[j].sockname.addrlen) < 0 && (errno != EINPROGRESS)) {
1364         killsock(dcc[j].sock);
1365         lostdcc(j);
1366         putlog(LOG_MISC, "*", DCC_IDENTFAIL, dcc[i].host, strerror(errno));
1367         j = 0;
1368       }
1369       sock = dcc[j].sock;
1370     }
1371   }
1372   if (j < 0) {
1373     dcc_telnet_got_ident(i, userhost);
1374     return;
1375   }
1376   dcc[j].sock = sock;
1377   dcc[j].port = 113;
1378   dcc[j].addr = dcc[i].addr;
1379   strcpy(dcc[j].host, dcc[i].host);
1380   strcpy(dcc[j].nick, "*");
1381   dcc[j].u.ident_sock = dcc[i].sock;
1382   dcc[j].timeval = now;
1383   dprintf(j, "%d, %d\n", dcc[i].port, dcc[idx].port);
1384 }
1385 
1386 static void eof_dcc_telnet(int idx)
1387 {
1388   putlog(LOG_MISC, "*", DCC_PORTDIE, dcc[idx].port);
1389   killsock(dcc[idx].sock);
1390   lostdcc(idx);
1391 }
1392 
1393 static void display_telnet(int idx, char *buf)
1394 {
1395 #ifdef TLS
1396   sprintf(buf, "lstn  %s%d%s", dcc[idx].ssl ? "+" : "", dcc[idx].port,
1397           (dcc[idx].status & LSTN_PUBLIC) ? " pub" : "");
1398 #else
1399   sprintf(buf, "lstn  %d%s", dcc[idx].port,
1400           (dcc[idx].status & LSTN_PUBLIC) ? " pub" : "");
1401 #endif
1402 }
1403 
1404 struct dcc_table DCC_TELNET = {
1405   "TELNET",
1406   DCT_LISTEN,
1407   eof_dcc_telnet,
1408   dcc_telnet,
1409   NULL,
1410   NULL,
1411   display_telnet,
1412   NULL,
1413   NULL,
1414   NULL
1415 };
1416 
1417 static void eof_dcc_dupwait(int idx)
1418 {
1419   putlog(LOG_BOTS, "*", DCC_LOSTDUP, dcc[idx].host);
1420   killsock(dcc[idx].sock);
1421   lostdcc(idx);
1422 }
1423 
1424 static void dcc_dupwait(int idx, char *buf, int i)
1425 {
1426   /* We just ignore any data at this point. */
1427   return;
1428 }
1429 
1430 /* We now check again. If the bot is still marked as duplicate, there is no
1431  * botnet lag we could push it on, so we just drop the connection.
1432  */
1433 static void timeout_dupwait(int idx)
1434 {
1435   char x[NICKLEN + UHOSTLEN];
1436 
1437   /* Still duplicate? */
1438   if (in_chain(dcc[idx].nick)) {
1439     egg_snprintf(x, sizeof x, "%s!%s", dcc[idx].nick, dcc[idx].host);
1440     dprintf(idx, "error Already connected.\n");
1441     putlog(LOG_BOTS, "*", DCC_DUPLICATE, x);
1442     killsock(dcc[idx].sock);
1443     lostdcc(idx);
1444   } else {
1445     /* Ha! Now it's gone and we can grant this bot access. */
1446     dcc_telnet_pass(idx, dcc[idx].u.dupwait->atr);
1447   }
1448 }
1449 
1450 static void display_dupwait(int idx, char *buf)
1451 {
1452   sprintf(buf, "wait  duplicate?");
1453 }
1454 
1455 static int expmem_dupwait(void *x)
1456 {
1457   struct dupwait_info *p = (struct dupwait_info *) x;
1458   int tot = sizeof(struct dupwait_info);
1459 
1460   if (p && p->chat && DCC_CHAT.expmem)
1461     tot += DCC_CHAT.expmem(p->chat);
1462   return tot;
1463 }
1464 
1465 static void kill_dupwait(int idx, void *x)
1466 {
1467   struct dupwait_info *p = (struct dupwait_info *) x;
1468 
1469   if (p) {
1470     if (p->chat && DCC_CHAT.kill)
1471       DCC_CHAT.kill(idx, p->chat);
1472     nfree(p);
1473   }
1474 }
1475 
1476 struct dcc_table DCC_DUPWAIT = {
1477   "DUPWAIT",
1478   DCT_VALIDIDX,
1479   eof_dcc_dupwait,
1480   dcc_dupwait,
1481   &dupwait_timeout,
1482   timeout_dupwait,
1483   display_dupwait,
1484   expmem_dupwait,
1485   kill_dupwait,
1486   out_dcc_bot
1487 };
1488 
1489 /* This function is called if a bot gets removed from the list. It checks
1490  * whether we have a pending duplicate connection for that bot and continues
1491  * with the login in that case.
1492  */
1493 void dupwait_notify(char *who)
1494 {
1495   int idx;
1496 
1497   Assert(who);
1498   for (idx = 0; idx < dcc_total; idx++)
1499     if ((dcc[idx].type == &DCC_DUPWAIT) &&
1500         !strcasecmp(dcc[idx].nick, who)) {
1501       dcc_telnet_pass(idx, dcc[idx].u.dupwait->atr);
1502       break;
1503     }
1504 }
1505 
1506 static void dcc_telnet_id(int idx, char *buf, int atr)
1507 {
1508   int ok = 0;
1509   struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0 };
1510   struct dcc_table *old = dcc[idx].type;
1511 
1512   if (detect_telnet((unsigned char *) buf)) {
1513     dcc[idx].status |= STAT_TELNET;
1514     strip_telnet(dcc[idx].sock, buf, &atr);
1515   } else
1516     dcc[idx].status &= ~STAT_TELNET;
1517   buf[HANDLEN] = 0;
1518   /* Toss out bad nicknames */
1519   if (dcc[idx].nick[0] != '@' && !wild_match(dcc[idx].nick, buf)) {
1520     dprintf(idx, "Sorry, that handle format is invalid.\n");
1521     putlog(LOG_BOTS, "*", DCC_BADNICK, dcc[idx].host);
1522     killsock(dcc[idx].sock);
1523     lostdcc(idx);
1524     return;
1525   }
1526   /* rxvt-unicode */
1527   if (!strncmp(buf, "\x1B[?1;2c", 7)) /* \e isn't C standard so we use \x1B instead */
1528     buf += 7;
1529   dcc[idx].user = get_user_by_handle(userlist, buf);
1530   get_user_flagrec(dcc[idx].user, &fr, NULL);
1531 
1532   if (glob_bot(fr) && raw_log) {
1533     if (!strncmp(buf, "s ", 2))
1534       putlog(LOG_BOTSHRIN, "*", "{b<-%s} %s", dcc[idx].user->handle, buf + 2);
1535     else
1536       putlog(LOG_BOTNETIN, "*", "[b<-%s] %s", dcc[idx].user->handle, buf);
1537   }
1538 #ifdef TLS
1539   if (dcc[idx].ssl && (tls_auth == 2)) {
1540     const char *uid = ssl_getuid(dcc[idx].sock);
1541 
1542     if (!uid || strcasecmp(uid, buf)) {
1543       if (glob_bot(fr)) {
1544         /* change here temp to use bot output */
1545         dcc[idx].type = &DCC_BOT_NEW;
1546         dprintf(idx, "error Certificate UID doesn't match handle\n");
1547         dcc[idx].type = old;
1548       } else
1549         dprintf(idx, "Your certificate UID doesn't match your handle.\n");
1550       killsock(dcc[idx].sock);
1551       lostdcc(idx);
1552       return;
1553     }
1554   }
1555 #endif
1556   /* Make sure users-only/bots-only connects are honored */
1557   if ((dcc[idx].status & STAT_BOTONLY) && !glob_bot(fr)) {
1558     dprintf(idx, "This telnet port is for bots only.\n");
1559     putlog(LOG_BOTS, "*", DCC_NONBOT, dcc[idx].host);
1560     killsock(dcc[idx].sock);
1561     lostdcc(idx);
1562     return;
1563   }
1564   if ((dcc[idx].status & STAT_USRONLY) && glob_bot(fr)) {
1565     /* change here temp to use bot output */
1566     dcc[idx].type = &DCC_BOT_NEW;
1567     dprintf(idx, "error Only users may connect at this port.\n");
1568     dcc[idx].type = old;
1569     putlog(LOG_BOTS, "*", DCC_NONUSER, dcc[idx].host);
1570     killsock(dcc[idx].sock);
1571     lostdcc(idx);
1572     return;
1573   }
1574   dcc[idx].status &= ~(STAT_BOTONLY | STAT_USRONLY);
1575   if (!strcasecmp(buf, "NEW") && (allow_new_telnets || make_userfile)) {
1576     dcc[idx].type = &DCC_TELNET_NEW;
1577     dcc[idx].timeval = now;
1578     dprintf(idx, "\n");
1579     dprintf(idx, IRC_TELNET, botnetnick);
1580     dprintf(idx, IRC_TELNET1);
1581     dprintf(idx, "\nEnter the handle you would like to use.\n");
1582     return;
1583   }
1584   if (chan_op(fr)) {
1585     if (!require_p)
1586       ok = 1;
1587   }
1588   if (!ok && (glob_party(fr) || glob_bot(fr)))
1589     ok = 1;
1590 
1591   if (!ok) {
1592     dprintf(idx, "You don't have access.\n");
1593     putlog(LOG_MISC, "*", DCC_INVHANDLE, dcc[idx].host, buf);
1594     killsock(dcc[idx].sock);
1595     lostdcc(idx);
1596     return;
1597   }
1598   correct_handle(buf);
1599   strlcpy(dcc[idx].nick, buf, sizeof dcc[idx].nick);
1600   if (glob_bot(fr)) {
1601     if (!strcasecmp(botnetnick, dcc[idx].nick)) {
1602       /* change here temp to use bot output */
1603       dcc[idx].type = &DCC_BOT_NEW;
1604       dprintf(idx, "error You cannot link using my botnetnick.\n");
1605       dcc[idx].type = old;
1606       putlog(LOG_BOTS, "*", DCC_MYBOTNETNICK, dcc[idx].host);
1607       killsock(dcc[idx].sock);
1608       lostdcc(idx);
1609       return;
1610     } else if (in_chain(dcc[idx].nick)) {
1611       struct chat_info *ci;
1612 
1613       ci = dcc[idx].u.chat;
1614       dcc[idx].type = &DCC_DUPWAIT;
1615       dcc[idx].u.dupwait = get_data_ptr(sizeof(struct dupwait_info));
1616       dcc[idx].u.dupwait->chat = ci;
1617       dcc[idx].u.dupwait->atr = atr;
1618       return;
1619     }
1620   }
1621   dcc_telnet_pass(idx, atr);
1622 }
1623 
1624 #ifdef TLS
1625 int dcc_fingerprint(int idx)
1626 {
1627   char *cf, *uf;
1628   struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0 };
1629 
1630   get_user_flagrec(dcc[idx].user, &fr, NULL);
1631   /* Check if fingerprint authentication is allowed or required. */
1632   if (dcc[idx].ssl && tls_auth) {
1633     /* Get the fingerprint of the current certificate */
1634     cf = ssl_getfp(dcc[idx].sock);
1635     /* Get the fingerprint of the user, if set */
1636     uf = get_user(&USERENTRY_FPRINT, dcc[idx].user);
1637     if (cf && uf && !strcasecmp(cf, uf)) {
1638       if (!glob_bot(fr))
1639         dprintf(idx, "Used your fingerprint for automatic authentication.\n");
1640       dcc[idx].status |= STAT_FPRINT;
1641       dcc_chat_pass(idx, "+", 1);
1642     /* Required? */
1643     } else if (tls_auth == 2) {
1644       if (glob_bot(fr)) {
1645         /* change here temp to use bot output */
1646         struct dcc_table *old = dcc[idx].type;
1647         dcc[idx].type = &DCC_BOT_NEW;
1648         dprintf(idx, "error fingerprint required\n");
1649         dcc[idx].type = old;
1650       } else
1651         dprintf(idx, "Certificate authentication required. "
1652                 "You need to set your fingerprint.\n");
1653       killsock(dcc[idx].sock);
1654       lostdcc(idx);
1655     }
1656     return 0;
1657   }
1658   return 1;
1659 }
1660 #endif
1661 
1662 static void dcc_telnet_pass(int idx, int atr)
1663 {
1664   int ok = 0;
1665   struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0 };
1666 
1667   get_user_flagrec(dcc[idx].user, &fr, NULL);
1668 #ifdef TLS
1669   /* Check if fingerprint authentication is allowed or required. */
1670   if (dcc[idx].ssl && tls_auth) {
1671     char *cf, *uf;
1672 
1673     /* Get the fingerprint of the current certificate */
1674     cf = ssl_getfp(dcc[idx].sock);
1675     /* Get the fingerprint of the user, if set */
1676     uf = get_user(&USERENTRY_FPRINT, dcc[idx].user);
1677     if (cf && uf && !strcasecmp(cf, uf)) {
1678       char fakepass[2] = "+";
1679 
1680       if (!glob_bot(fr))
1681         dprintf(idx, "Used your fingerprint for automatic authentication.\n");
1682       dcc[idx].status |= STAT_FPRINT;
1683       dcc_chat_pass(idx, fakepass, 1);
1684       return;
1685     /* Required? */
1686     } else if (tls_auth == 2) {
1687       if (glob_bot(fr)) {
1688         /* change here temp to use bot output */
1689         struct dcc_table *old = dcc[idx].type;
1690         dcc[idx].type = &DCC_BOT_NEW;
1691         dprintf(idx, "error fingerprint required\n");
1692         dcc[idx].type = old;
1693       } else
1694         dprintf(idx, "Certificate authentication required. "
1695                 "You need to set your fingerprint.\n");
1696       killsock(dcc[idx].sock);
1697       lostdcc(idx);
1698       return;
1699     }
1700   }
1701 #endif
1702   /* No password set? */
1703   if (!glob_bot(fr) && u_pass_match(dcc[idx].user, "-")) {
1704     dprintf(idx, "Can't telnet until you have a password set.\n");
1705     putlog(LOG_MISC, "*", DCC_NOPASS, dcc[idx].nick, dcc[idx].host);
1706     killsock(dcc[idx].sock);
1707     lostdcc(idx);
1708     return;
1709   }
1710   ok = 0;
1711   if (dcc[idx].type == &DCC_DUPWAIT) {
1712     struct chat_info *ci;
1713 
1714     ci = dcc[idx].u.dupwait->chat;
1715     nfree(dcc[idx].u.dupwait);
1716     dcc[idx].u.chat = ci;
1717   }
1718   dcc[idx].type = &DCC_CHAT_PASS;
1719   dcc[idx].timeval = now;
1720   if (glob_botmast(fr))
1721     ok = 1;
1722   else if (chan_op(fr)) {
1723     if (!require_p)
1724       ok = 1;
1725     else if (glob_party(fr))
1726       ok = 1;
1727   } else if (glob_party(fr)) {
1728     ok = 1;
1729     dcc[idx].status |= STAT_PARTY;
1730   }
1731   if (glob_bot(fr))
1732     ok = 1;
1733   if (!ok) {
1734     struct chat_info *ci;
1735 
1736     ci = dcc[idx].u.chat;
1737     dcc[idx].u.file = get_data_ptr(sizeof(struct file_info));
1738     dcc[idx].u.file->chat = ci;
1739   }
1740 
1741   if (glob_bot(fr)) {
1742     /* change here temp to use bot output */
1743     struct dcc_table *old = dcc[idx].type;
1744     dcc[idx].type = &DCC_BOT_NEW;
1745     /* Must generate a string consisting of our process ID and the current
1746      * time. The bot will add it's password to the end and use it to generate
1747      * an MD5 checksum (always 128bit). The checksum is sent back and this
1748      * end does the same. The remote bot is only allowed access if the
1749      * checksums match.
1750      *
1751      * Please don't fuck with 'timeval', or the digest we generate later for
1752      * authentication will not be correct - you've been warned ;)
1753      * <Cybah>
1754      */
1755     putlog(LOG_BOTS, "*", "Challenging %s...", dcc[idx].nick);
1756     /* Prefix with \n in case of newline-less ending stealth_prompt */
1757     dprintf(idx, "\npassreq <%x%x@%s>\n", getpid(), dcc[idx].timeval, botnetnick);
1758     dcc[idx].type = old;
1759   } else {
1760     /* NOTE: The MD5 digest used above to prevent cleartext passwords being
1761      *       sent across the net will _only_ work when we have the cleartext
1762      *       password. User passwords are encrypted (with blowfish usually)
1763      *       so the same thing cant be done. Botnet passwords are always
1764      *       stored in cleartext, or at least something that can be reversed.
1765      *       <Cybah>
1766      */
1767 
1768     /* Turn off remote telnet echo (send IAC WILL ECHO). */
1769     if (dcc[idx].status & STAT_TELNET) {
1770       char buf[1030];
1771       egg_snprintf(buf, sizeof buf, "\n%s%s\r\n", escape_telnet(DCC_ENTERPASS),
1772                TLN_IAC_C TLN_WILL_C TLN_ECHO_C);
1773       tputs(dcc[idx].sock, buf, strlen(buf));
1774     } else
1775       dprintf(idx, "\n%s\n", DCC_ENTERPASS);
1776   }
1777 }
1778 
1779 static void eof_dcc_telnet_id(int idx)
1780 {
1781   putlog(LOG_MISC, "*", DCC_LOSTCON, dcc[idx].host, dcc[idx].port);
1782   killsock(dcc[idx].sock);
1783   lostdcc(idx);
1784 }
1785 
1786 static void timeout_dcc_telnet_id(int idx)
1787 {
1788   dprintf(idx, "Timeout.\n");
1789   putlog(LOG_MISC, "*", DCC_TTIMEOUT, dcc[idx].host);
1790   killsock(dcc[idx].sock);
1791   lostdcc(idx);
1792 }
1793 
1794 static void display_dcc_telnet_id(int idx, char *buf)
1795 {
1796   long tv;
1797 
1798   tv = now - dcc[idx].timeval;
1799   sprintf(buf, "t-in  waited %lis", tv);
1800 }
1801 
1802 struct dcc_table DCC_TELNET_ID = {
1803   "TELNET_ID",
1804   0,
1805   eof_dcc_telnet_id,
1806   dcc_telnet_id,
1807   &password_timeout,
1808   timeout_dcc_telnet_id,
1809   display_dcc_telnet_id,
1810   expmem_dcc_general,
1811   kill_dcc_general,
1812   out_dcc_general
1813 };
1814 
1815 static void dcc_telnet_new(int idx, char *buf, int x)
1816 {
1817   int ok = 1;
1818   char work[1024], *p, *q, *r;
1819 
1820   buf[HANDLEN] = 0;
1821   if (dcc[idx].status & STAT_TELNET)
1822     strip_telnet(dcc[idx].sock, buf, &x);
1823   dcc[idx].timeval = now;
1824   for (x = 0; x < strlen(buf); x++)
1825     if (buf[x] <= 32)
1826       ok = 0;
1827   if (!ok) {
1828     dprintf(idx, "\nYou can't use weird symbols in your nick.\n");
1829     dprintf(idx, "Try another one please:\n");
1830   } else if (strchr(BADHANDCHARS, buf[0]) != NULL) {
1831     dprintf(idx, "\nYou can't start your nick with the character '%c'\n",
1832             buf[0]);
1833     dprintf(idx, "Try another one please:\n");
1834   } else if (get_user_by_handle(userlist, buf)) {
1835     dprintf(idx, "\nSorry, that handle is taken already.\n");
1836     dprintf(idx, "Try another one please:\n");
1837     return;
1838   } else if (!strcasecmp(buf, botnetnick))
1839     dprintf(idx, "Sorry, can't use my name for a nick.\n");
1840   else {
1841     strcpy(dcc[idx].nick, buf);
1842     if (make_userfile)
1843       userlist = adduser(userlist,
1844                  buf, "-telnet!*@*", "-", sanity_check(default_flags |
1845                  USER_PARTY | USER_MASTER | USER_OWNER));
1846     else {
1847       p = strchr(dcc[idx].host, '@');
1848       if (p) {
1849         q = p;
1850         *q = 0;
1851         p++;
1852         r = strchr(p, '.');
1853         if (!r)
1854           simple_sprintf(work, "-telnet!%s@%s", dcc[idx].host, p);
1855         else
1856           simple_sprintf(work, "-telnet!%s@*%s", dcc[idx].host, r);
1857         *q = '@';
1858       } else
1859         simple_sprintf(work, "-telnet!*@*%s", dcc[idx].host);
1860       userlist = adduser(userlist, buf, work, "-",
1861                          sanity_check(USER_PARTY | default_flags));
1862     }
1863     reaffirm_owners();
1864     dcc[idx].status = STAT_ECHO | STAT_TELNET;
1865     dcc[idx].type = &DCC_CHAT;  /* Just so next line will work */
1866     dcc[idx].user = get_user_by_handle(userlist, buf);
1867     check_dcc_attrs(dcc[idx].user, USER_PARTY | default_flags);
1868     dcc[idx].type = &DCC_TELNET_PW;
1869     if (make_userfile) {
1870       dprintf(idx, "\nYOU ARE THE MASTER/OWNER ON THIS BOT NOW\n");
1871       dprintf(idx, IRC_LIMBO);
1872       putlog(LOG_MISC, "*", DCC_INSTCOMPL, buf);
1873       make_userfile = 0;
1874       write_userfile(-1);
1875       add_note(buf, botnetnick, "Welcome to eggdrop! :)", -1, 0);
1876     }
1877     dprintf(idx, "\nOkay, now choose and enter a password:\n");
1878   }
1879 }
1880 
1881 static void dcc_telnet_pw(int idx, char *new, int x)
1882 {
1883   char *s;
1884 
1885   if (dcc[idx].status & STAT_TELNET)
1886     strip_telnet(dcc[idx].sock, new, &x);
1887   if ((s = check_validpass(dcc[idx].user, new))) {
1888     dprintf(idx, "%s\nChoose and enter a password:\n", s);
1889     return;
1890   }
1891   putlog(LOG_MISC, "*", DCC_NEWUSER, dcc[idx].nick, dcc[idx].host,
1892          dcc[idx].port);
1893   if (notify_new[0]) {
1894     char s[NICKLEN+UHOSTMAX+32], s1[NICKLEN+UHOSTMAX+32], s2[NICKLEN+UHOSTMAX+32];
1895 
1896     sprintf(s, "Introduced to %s, %s", dcc[idx].nick, dcc[idx].host);
1897     strcpy(s1, notify_new);
1898     splitc(s2, s1, ',');
1899     while (s2[0]) {
1900       rmspace(s2);
1901       add_note(s2, botnetnick, s, -1, 0);
1902       splitc(s2, s1, ',');
1903     }
1904     rmspace(s1);
1905     add_note(s1, botnetnick, s, -1, 0);
1906   }
1907   dprintf(idx, "\nRemember that!  You'll need it next time you log in.\n"
1908                "You now have an account on %s...\n\n\n", botnetnick);
1909   dcc[idx].type = &DCC_CHAT;
1910   dcc[idx].u.chat->channel = -2;
1911   dcc_chatter(idx);
1912 }
1913 
1914 static void eof_dcc_telnet_new(int idx)
1915 {
1916   putlog(LOG_MISC, "*", DCC_LOSTNEWUSER, dcc[idx].host, dcc[idx].port);
1917   killsock(dcc[idx].sock);
1918   lostdcc(idx);
1919 }
1920 
1921 static void eof_dcc_telnet_pw(int idx)
1922 {
1923   putlog(LOG_MISC, "*", DCC_LOSTNEWUSR2, dcc[idx].nick, dcc[idx].host,
1924          dcc[idx].port);
1925   deluser(dcc[idx].nick);
1926   killsock(dcc[idx].sock);
1927   lostdcc(idx);
1928 }
1929 
1930 static void tout_dcc_telnet_new(int idx)
1931 {
1932   dprintf(idx, "Guess you're not there.  Bye.\n");
1933   putlog(LOG_MISC, "*", DCC_TIMEOUTUSER, dcc[idx].host, dcc[idx].port);
1934   killsock(dcc[idx].sock);
1935   lostdcc(idx);
1936 }
1937 
1938 static void tout_dcc_telnet_pw(int idx)
1939 {
1940   dprintf(idx, "Guess you're not there.  Bye.\n");
1941   putlog(LOG_MISC, "*", DCC_TIMEOUTUSR2, dcc[idx].nick,
1942          dcc[idx].host, dcc[idx].port);
1943   killsock(dcc[idx].sock);
1944   lostdcc(idx);
1945 }
1946 
1947 static void display_dcc_telnet_new(int idx, char *buf)
1948 {
1949   long tv;
1950 
1951   tv = now - dcc[idx].timeval;
1952   sprintf(buf, "new   waited %lis", tv);
1953 }
1954 
1955 static void display_dcc_telnet_pw(int idx, char *buf)
1956 {
1957   long tv;
1958 
1959   tv = now - dcc[idx].timeval;
1960   sprintf(buf, "newp  waited %lis", tv);
1961 }
1962 
1963 struct dcc_table DCC_TELNET_NEW = {
1964   "TELNET_NEW",
1965   0,
1966   eof_dcc_telnet_new,
1967   dcc_telnet_new,
1968   &password_timeout,
1969   tout_dcc_telnet_new,
1970   display_dcc_telnet_new,
1971   expmem_dcc_general,
1972   kill_dcc_general,
1973   out_dcc_general
1974 };
1975 
1976 struct dcc_table DCC_TELNET_PW = {
1977   "TELNET_PW",
1978   0,
1979   eof_dcc_telnet_pw,
1980   dcc_telnet_pw,
1981   &password_timeout,
1982   tout_dcc_telnet_pw,
1983   display_dcc_telnet_pw,
1984   expmem_dcc_general,
1985   kill_dcc_general,
1986   out_dcc_general
1987 };
1988 
1989 static int call_tcl_func(char *name, int idx, char *args)
1990 {
1991   char s[12];
1992 
1993   snprintf(s, sizeof s, "%d", idx);
1994   Tcl_SetVar(interp, "_n", s, 0);
1995   Tcl_SetVar(interp, "_a", args, 0);
1996   if (Tcl_VarEval(interp, name, " $_n $_a", NULL) == TCL_ERROR) {
1997     putlog(LOG_MISC, "*", DCC_TCLERROR, name, tcl_resultstring());
1998     Tcl_BackgroundError(interp);
1999     return -1;
2000   }
2001   return tcl_resultint();
2002 }
2003 
2004 static void dcc_script(int idx, char *buf, int len)
2005 {
2006   long oldsock;
2007 
2008   if (dcc[idx].status & STAT_TELNET)
2009     strip_telnet(dcc[idx].sock, buf, &len);
2010   if (!len)
2011     return;
2012 
2013   dcc[idx].timeval = now;
2014   oldsock = dcc[idx].sock;      /* Remember the socket number.  */
2015   if (call_tcl_func(dcc[idx].u.script->command, dcc[idx].sock, buf)) {
2016     void *old_other = NULL;
2017 
2018     /* Check whether the socket and dcc entry are still valid. They
2019      * might have been killed by `killdcc'. */
2020     if (dcc[idx].sock != oldsock || idx > max_dcc)
2021       return;
2022 
2023     old_other = dcc[idx].u.script->u.other;
2024     dcc[idx].type = dcc[idx].u.script->type;
2025     nfree(dcc[idx].u.script);
2026     dcc[idx].u.other = old_other;
2027     if (dcc[idx].type == &DCC_SOCKET) {
2028       /* Kill the whole thing off */
2029       killsock(dcc[idx].sock);
2030       lostdcc(idx);
2031       return;
2032     }
2033     if (dcc[idx].type == &DCC_CHAT) {
2034       if (dcc[idx].u.chat->channel >= 0) {
2035         chanout_but(-1, dcc[idx].u.chat->channel, DCC_RETURN, dcc[idx].nick);
2036         if (dcc[idx].u.chat->channel < 10000)
2037           botnet_send_join_idx(idx, -1);
2038         check_tcl_chjn(botnetnick, dcc[idx].nick, dcc[idx].u.chat->channel,
2039                        geticon(idx), dcc[idx].sock, dcc[idx].host);
2040       }
2041     }
2042   }
2043 }
2044 
2045 static void eof_dcc_script(int idx)
2046 {
2047   void *old;
2048   int oldflags;
2049 
2050   /* This will stop a killdcc from working, in case the script tries
2051    * to kill it's controlling socket while handling an EOF <cybah>
2052    */
2053   oldflags = dcc[idx].type->flags;
2054   dcc[idx].type->flags &= ~(DCT_VALIDIDX);
2055   /* Tell the script they're gone: */
2056   call_tcl_func(dcc[idx].u.script->command, dcc[idx].sock, "");
2057   /* Restore the flags */
2058   dcc[idx].type->flags = oldflags;
2059   old = dcc[idx].u.script->u.other;
2060   dcc[idx].type = dcc[idx].u.script->type;
2061   nfree(dcc[idx].u.script);
2062   dcc[idx].u.other = old;
2063   /* Then let it fall thru to the real one */
2064   if (dcc[idx].type && dcc[idx].type->eof)
2065     dcc[idx].type->eof(idx);
2066   else {
2067     putlog(LOG_MISC, "*", DCC_DEADSOCKET, dcc[idx].sock, dcc[idx].type->name);
2068     killsock(dcc[idx].sock);
2069     lostdcc(idx);
2070   }
2071 }
2072 
2073 static void display_dcc_script(int idx, char *buf)
2074 {
2075   sprintf(buf, "scri  %s", dcc[idx].u.script->command);
2076 }
2077 
2078 static int expmem_dcc_script(void *x)
2079 {
2080   struct script_info *p = (struct script_info *) x;
2081   int tot = sizeof(struct script_info);
2082 
2083   if (p->type && p->u.other)
2084     tot += p->type->expmem(p->u.other);
2085   return tot;
2086 }
2087 
2088 static void kill_dcc_script(int idx, void *x)
2089 {
2090   struct script_info *p = (struct script_info *) x;
2091 
2092   if (p->type && p->u.other)
2093     p->type->kill(idx, p->u.other);
2094   nfree(p);
2095 }
2096 
2097 static void out_dcc_script(int idx, char *buf, void *x)
2098 {
2099   struct script_info *p = (struct script_info *) x;
2100 
2101   if (p && p->type && p->u.other)
2102     p->type->output(idx, buf, p->u.other);
2103   else
2104     tputs(dcc[idx].sock, buf, strlen(buf));
2105 }
2106 
2107 struct dcc_table DCC_SCRIPT = {
2108   "SCRIPT",
2109   DCT_VALIDIDX,
2110   eof_dcc_script,
2111   dcc_script,
2112   NULL,
2113   NULL,
2114   display_dcc_script,
2115   expmem_dcc_script,
2116   kill_dcc_script,
2117   out_dcc_script
2118 };
2119 
2120 static void dcc_socket(int idx, char *buf, int len)
2121 {
2122 }
2123 
2124 static void eof_dcc_socket(int idx)
2125 {
2126   killsock(dcc[idx].sock);
2127   lostdcc(idx);
2128 }
2129 
2130 static void display_dcc_socket(int idx, char *buf)
2131 {
2132   strcpy(buf, "sock  (stranded)");
2133 }
2134 
2135 struct dcc_table DCC_SOCKET = {
2136   "SOCKET",
2137   DCT_VALIDIDX,
2138   eof_dcc_socket,
2139   dcc_socket,
2140   NULL,
2141   NULL,
2142   display_dcc_socket,
2143   NULL,
2144   NULL,
2145   NULL
2146 };
2147 
2148 static void display_dcc_lost(int idx, char *buf)
2149 {
2150   strcpy(buf, "lost");
2151 }
2152 
2153 struct dcc_table DCC_LOST = {
2154   "LOST",
2155   0,
2156   NULL,
2157   dcc_socket,
2158   NULL,
2159   NULL,
2160   display_dcc_lost,
2161   NULL,
2162   NULL,
2163   NULL
2164 };
2165 
2166 void dcc_identwait(int idx, char *buf, int len)
2167 {
2168   /* Ignore anything now */
2169 }
2170 
2171 void eof_dcc_identwait(int idx)
2172 {
2173   int i;
2174 
2175   putlog(LOG_MISC, "*", DCC_LOSTCONN, dcc[idx].host, dcc[idx].port);
2176   for (i = 0; i < dcc_total; i++)
2177     if ((dcc[i].type == &DCC_IDENT) &&
2178         (dcc[i].u.ident_sock == dcc[idx].sock)) {
2179       killsock(dcc[i].sock);    /* Cleanup ident socket */
2180       dcc[i].u.other = 0;
2181       lostdcc(i);
2182       break;
2183     }
2184   killsock(dcc[idx].sock);      /* Cleanup waiting socket */
2185   dcc[idx].u.other = 0;
2186   lostdcc(idx);
2187 }
2188 
2189 static void display_dcc_identwait(int idx, char *buf)
2190 {
2191   long tv;
2192 
2193   tv = now - dcc[idx].timeval;
2194   sprintf(buf, "idtw  waited %lis", tv);
2195 }
2196 
2197 struct dcc_table DCC_IDENTWAIT = {
2198   "IDENTWAIT",
2199   0,
2200   eof_dcc_identwait,
2201   dcc_identwait,
2202   NULL,
2203   NULL,
2204   display_dcc_identwait,
2205   NULL,
2206   NULL,
2207   NULL
2208 };
2209 
2210 void dcc_ident(int idx, char *buf, int len)
2211 {
2212   char response[512], uid[512], buf1[UHOSTLEN];
2213   int i;
2214 
2215   *response = *uid = '\0';
2216   sscanf(buf, "%*[^:]:%[^:]:%*[^:]:%[^\n]\n", response, uid);
2217   rmspace(response);
2218   if (response[0] != 'U') {
2219     dcc[idx].timeval = now;
2220     return;
2221   }
2222   rmspace(uid);
2223   uid[20] = 0;                  /* 20 character ident max */
2224   for (i = 0; i < dcc_total; i++)
2225     if ((dcc[i].type == &DCC_IDENTWAIT) &&
2226         (dcc[i].sock == dcc[idx].u.ident_sock)) {
2227       simple_sprintf(buf1, "%s@%s", uid, dcc[idx].host);
2228       dcc_telnet_got_ident(i, buf1);
2229     }
2230   dcc[idx].u.other = 0;
2231   killsock(dcc[idx].sock);
2232   lostdcc(idx);
2233 }
2234 
2235 void eof_timeout_dcc_ident(int idx, const char *s)
2236 {
2237   char buf[UHOSTLEN];
2238   int i;
2239 
2240   for (i = 0; i < dcc_total; i++)
2241     if ((dcc[i].type == &DCC_IDENTWAIT) &&
2242         (dcc[i].sock == dcc[idx].u.ident_sock)) {
2243       putlog(LOG_MISC, "*", s);
2244       simple_sprintf(buf, "telnet@%s", dcc[idx].host);
2245       dcc_telnet_got_ident(i, buf);
2246     }
2247   killsock(dcc[idx].sock);
2248   dcc[idx].u.other = 0;
2249   lostdcc(idx);
2250 }
2251 
2252 void eof_dcc_ident(int idx)
2253 {
2254   eof_timeout_dcc_ident(idx, DCC_EOFIDENT);
2255 }
2256 
2257 void timeout_dcc_ident(int idx)
2258 {
2259   eof_timeout_dcc_ident(idx, DCC_TIMEOUTIDENT);
2260 }
2261 
2262 static void display_dcc_ident(int idx, char *buf)
2263 {
2264   sprintf(buf, "idnt  (sock %d)", dcc[idx].u.ident_sock);
2265 }
2266 
2267 struct dcc_table DCC_IDENT = {
2268   "IDENT",
2269   0,
2270   eof_dcc_ident,
2271   dcc_ident,
2272   &identtimeout,
2273   timeout_dcc_ident,
2274   display_dcc_ident,
2275   NULL,
2276   NULL,
2277   NULL
2278 };
2279 
2280 static void dcc_telnet_got_ident(int i, char *host)
2281 {
2282   int idx;
2283   char x[1024];
2284 
2285   for (idx = 0; idx < dcc_total; idx++)
2286     if ((dcc[idx].type == &DCC_TELNET) &&
2287         (dcc[idx].sock == dcc[i].u.ident_sock))
2288       break;
2289   dcc[i].u.other = 0;
2290   if (dcc_total == idx) {
2291     putlog(LOG_MISC, "*", DCC_LOSTIDENT);
2292     killsock(dcc[i].sock);
2293     lostdcc(i);
2294     return;
2295   }
2296   strlcpy(dcc[i].host, host, UHOSTLEN);
2297   egg_snprintf(x, sizeof x, "-telnet!%s", dcc[i].host);
2298   if (protect_telnet && !make_userfile) {
2299     struct userrec *u;
2300     int ok = 1;
2301 
2302     u = get_user_by_host(x);
2303     /* Not a user or +p & require p OR +o */
2304     if (!u)
2305       ok = 0;
2306     else if (require_p && !(u->flags & USER_PARTY))
2307       ok = 0;
2308     else if (!require_p && !(u->flags & USER_OP))
2309       ok = 0;
2310     if (!ok && u && (u->flags & USER_BOT))
2311       ok = 1;
2312     if (!ok && (dcc[idx].status & LSTN_PUBLIC))
2313       ok = 1;
2314     if (!ok) {
2315       putlog(LOG_MISC, "*", DCC_NOACCESS, dcc[i].host);
2316       killsock(dcc[i].sock);
2317       lostdcc(i);
2318       return;
2319     }
2320   }
2321   if (match_ignore(x)) {
2322     killsock(dcc[i].sock);
2323     lostdcc(i);
2324     return;
2325   }
2326 
2327   /* Script? */
2328   if (!strcmp(dcc[idx].nick, "(script)")) {
2329     dcc[i].type = &DCC_SOCKET;
2330     dcc[i].u.other = NULL;
2331     strcpy(dcc[i].nick, "*");
2332     check_tcl_listen(dcc[idx].host, dcc[i].sock);
2333     return;
2334   }
2335   /* Do not buffer data anymore. All received and stored data is passed
2336    * over to the dcc functions from now on.  */
2337   sockoptions(dcc[i].sock, EGG_OPTION_UNSET, SOCK_BUFFER);
2338 
2339   dcc[i].type = &DCC_TELNET_ID;
2340   dcc[i].u.chat = get_data_ptr(sizeof(struct chat_info));
2341   egg_bzero(dcc[i].u.chat, sizeof(struct chat_info));
2342 
2343   /* Note: we don't really care about telnet status here. We use the
2344    * STATUS option as a hopefully harmless way to detect if the other
2345    * side is a telnet client or not. */
2346   dprintf(i, TLN_IAC_C TLN_WILL_C TLN_STATUS_C);
2347 
2348   /* Copy acceptable-nick/host mask */
2349   dcc[i].status = STAT_TELNET | STAT_ECHO;
2350   if (!strcmp(dcc[idx].nick, "(bots)"))
2351     dcc[i].status |= STAT_BOTONLY;
2352   if (!strcmp(dcc[idx].nick, "(users)"))
2353     dcc[i].status |= STAT_USRONLY;
2354   /* Copy acceptable-nick/host mask */
2355   strlcpy(dcc[i].nick, dcc[idx].host, HANDLEN);
2356   dcc[i].timeval = now;
2357   strcpy(dcc[i].u.chat->con_chan, chanset ? chanset->dname : "*");
2358   /* Displays a customizable banner. */
2359   if (use_telnet_banner)
2360     show_banner(i);
2361   /* This is so we don't tell someone doing a portscan anything
2362    * about ourselves. <cybah>
2363    */
2364   if (stealth_telnets) {
2365     /* Show here so it doesn't interfere with newline-less stealth_prompt */
2366     if (allow_new_telnets)
2367       dprintf(i, "(If you are new, enter 'NEW' here.)\n");
2368     dprintf(i, stealth_prompt);
2369   } else {
2370     dprintf(i, "\n\n");
2371     sub_lang(i, MISC_BANNER);
2372     /* Show here so it doesn't get lost before the banner */
2373     if (allow_new_telnets)
2374       dprintf(i, "(If you are new, enter 'NEW' here.)\n");
2375   }
2376 }
2377