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  * $Id: dcc.c,v 1.77 (1.0.2) 2004/04/17 22:47:36 [Xp-AvR] Exp $
8  */
9 
10 #include "main.h"
11 #include <ctype.h>
12 #include <errno.h>
13 #include "modules.h"
14 #include "tandem.h"
15 
16 /* Includes for botnet md5 challenge/response code */
17 #include "md5/md5.h"
18 
19 #define OLDHELLOMSG "averse-"
20 #define HELLOMSG "-eva-"
21 #define BOTID "*Av3rsE!XP"
22 
23 extern struct userrec *userlist;
24 extern struct chanset_t *chanset;
25 extern Tcl_Interp *interp;
26 extern time_t now;
27 extern char botnetnick[], ver[], origbotname[], notify_new[], userfileCryptKey[];
28 extern int EvangelineNumver, connect_timeout, conmask, backgrd, max_dcc,
29            make_userfile, default_flags, raw_log, ignore_time, first_start,
30            par_telnet_flood;
31 
32 struct dcc_t *dcc = NULL;       /* DCC list                                */
33 int dcc_total = 0;              /* Total dcc's                             */
34 char tempdir[121] = "";         /* Temporary directory                     */
35 int require_p = 1;              /* Require 'p' access to get on the party line? */
36 int allow_new_telnets = 0;      /* Allow people to introduce themselves via telnet */
37 int stealth_telnets = 1;        /* Be paranoid? <cybah>                    */
38 char network[41] = "IRCnet";    /* Name of the IRC network you're on  */
39 int password_timeout = 180;     /* Time to wait for a password from a user */
40 int bot_timeout = 60;           /* Bot timeout value                       */
41 int identtimeout = 5;           /* Timeout value for ident lookups         */
42 int dupwait_timeout = 5;        /* Timeout for rejecting duplicate entries */
43 int protect_telnet = 1;         /* Even bother with ident lookups :)       */
44 int flood_telnet_thr = 5;       /* Number of telnet connections to be considered a flood */
45 int flood_telnet_time = 60;     /* In how many seconds?                    */
46 int evangeline = 0;             /* Evangeline or other mod?                */
47 
48 static void dcc_telnet_hostresolved(int);
49 static void dcc_telnet_got_ident(int, char *);
50 static void dcc_telnet_pass(int, int);
51 
strip_telnet(int sock,char * buf,int * len)52 static void strip_telnet(int sock, char *buf, int *len)
53 {
54   unsigned char *p = (unsigned char *) buf, *o = (unsigned char *) buf;
55   int mark;
56 
57   while (*p != 0) {
58     while ((*p != TLN_IAC) && (*p != 0))
59       *o++ = *p++;
60     if (*p == TLN_IAC) {
61       p++;
62       mark = 2;
63       if (!*p)
64         mark = 1;
65       if ((*p >= TLN_WILL) && (*p <= TLN_DONT)) {
66         mark = 3;
67         if (!*(p + 1))
68           mark = 2;
69       }
70       if (*p == TLN_WILL) {
71         if (*(p + 1) != TLN_ECHO) {
72           write(sock, TLN_IAC_C TLN_DONT_C, 2);
73           write(sock, p + 1, 1);
74         }
75       }
76       if (*p == TLN_DO) {
77         if (*(p + 1) != TLN_ECHO) {
78           write(sock, TLN_IAC_C TLN_WONT_C, 2);
79           write(sock, p + 1, 1);
80         }
81       }
82       if (*p == TLN_AYT) {
83         write(sock, "\r\nHell, yes!\r\n", 14);
84       }
85       p += mark - 1;
86       *len = *len - mark;
87     }
88   }
89   *o = *p;
90 }
91 
greet_new_bot(int idx)92 static void greet_new_bot(int idx)
93 {
94   int bfl = bot_flags(dcc[idx].user);
95   int i;
96 
97   dcc[idx].timeval = now;
98   dcc[idx].u.bot->version[0] = 0;
99   dcc[idx].u.bot->numver = 0;
100   if (bfl & BOT_REJECT) {
101     putlog(LOG_BOTS, "*", DCC_REJECT, dcc[idx].nick);
102     dprintf(idx, "bye %s\n", "rejected");
103     killsock(dcc[idx].sock);
104     lostdcc(idx);
105     return;
106   }
107   if (bfl & BOT_LEAF)
108     dcc[idx].status |= STAT_LEAF;
109   dcc[idx].status |= STAT_LINKING;
110   if (evangeline) {
111     dprintf(idx, "v %d %d %s <%s>\n", EvangelineNumver, HANDLEN, ver, network);
112   } else {
113     dprintf(idx, "v %d 9 %s <%s>\n", EvangelineNumver, ver, network);
114   }
115   for (i = 0; i < dcc_total; i++)
116     if (dcc[i].type == &DCC_FORK_BOT) {
117       killsock(dcc[i].sock);
118       lostdcc(i);
119     }
120 }
121 
bot_version(int idx,char * par)122 static void bot_version(int idx, char *par)
123 {
124   char x[1024];
125 //  int l;
126 
127   dcc[idx].timeval = now;
128   if (in_chain(dcc[idx].nick)) {
129     dprintf(idx, "error Sorry, already connected.\n");
130     dprintf(idx, "bye\n");
131     killsock(dcc[idx].sock);
132     lostdcc(idx);
133     return;
134   }
135   if ((par[0] >= '0') && (par[0] <= '9')) {
136     char *work;
137 
138     work = newsplit(&par);
139     dcc[idx].u.bot->numver = atoi(work);
140   } else
141     dcc[idx].u.bot->numver = 0;
142 
143     dprintf(idx, "tb %s\n", botnetnick);
144 /*
145     l = atoi(newsplit(&par));
146     if (l != HANDLEN) {
147       putlog(LOG_BOTS, "*", "Non-matching handle lengths with %s, they use %d "
148              "characters.", dcc[idx].nick, l);
149       dprintf(idx, "error Non-matching handle length: mine %d, yours %d\n",
150               HANDLEN, l);
151       dprintf(idx, "bye %s\n", "bad handlen");
152       killsock(dcc[idx].sock);
153       lostdcc(idx);
154       return;
155     }
156 */
157   strncpyz(dcc[idx].u.bot->version, par, 120);
158   putlog(LOG_BOTS, "*", DCC_LINKED, dcc[idx].nick);
159   chatout("*** Linked to %s\n", dcc[idx].nick);
160   botnet_send_nlinked(idx, dcc[idx].nick, botnetnick, '!',
161                       dcc[idx].u.bot->numver);
162   touch_laston(dcc[idx].user, "linked", now);
163   dump_links(idx);
164   dcc[idx].type = &DCC_BOT;
165   addbot(dcc[idx].nick, dcc[idx].nick, botnetnick, '-', dcc[idx].u.bot->numver);
166   check_tcl_link(dcc[idx].nick, botnetnick);
167   EvangelineSnprintf(x, sizeof x, "v %d", dcc[idx].u.bot->numver);
168   bot_share(idx, x);
169   dprintf(idx, "el\n");
170 }
171 
failed_link(int idx)172 void failed_link(int idx)
173 {
174   char s[81], s1[512];
175 
176   if (dcc[idx].port >= dcc[idx].u.bot->port + 3) {
177     if (dcc[idx].u.bot->linker[0]) {
178       EvangelineSnprintf(s, sizeof s, "Couldn't link to %s.", dcc[idx].nick);
179       strcpy(s1, dcc[idx].u.bot->linker);
180       add_note(s1, botnetnick, s, -2, 0);
181     }
182     if (dcc[idx].u.bot->numver >= -1)
183       putlog(LOG_BOTS, "*", DCC_LINKFAIL, dcc[idx].nick);
184     killsock(dcc[idx].sock);
185     strcpy(s, dcc[idx].nick);
186     lostdcc(idx);
187     autolink_cycle(s);
188     return;
189   }
190 
191   killsock(dcc[idx].sock);
192   dcc[idx].sock = getsock(SOCK_STRONGCONN,getprotocol(dcc[idx].host));
193   dcc[idx].port++;
194   dcc[idx].timeval = now;
195   if (dcc[idx].sock < 0 ||
196       open_telnet_raw(dcc[idx].sock, dcc[idx].addr ?
197                       iptostr(htonl(dcc[idx].addr)) : dcc[idx].host,
198                       dcc[idx].port) < 0) {
199     failed_link(idx);
200   }
201 }
202 
cont_link(int idx,char * buf,int i)203 static void cont_link(int idx, char *buf, int i)
204 {
205   char x[1024];
206   int atr = bot_flags(dcc[idx].user);
207   int users, bots;
208 
209   if (atr & BOT_HUB) {
210     for (i = 0; i < dcc_total; i++) {
211       if ((i != idx) && (bot_flags(dcc[i].user) & BOT_ALT)) {
212         if ((dcc[i].type == &DCC_FORK_BOT) || (dcc[i].type == &DCC_BOT_NEW)) {
213           killsock(dcc[i].sock);
214           lostdcc(i);
215         }
216       }
217     }
218     if (in_chain(dcc[idx].nick)) {
219       i = nextbot(dcc[idx].nick);
220       if (i > 0) {
221         bots = bots_in_subtree(findbot(dcc[idx].nick));
222         users = users_in_subtree(findbot(dcc[idx].nick));
223         EvangelineSnprintf(x, sizeof x,
224                      "Unlinked %s (restructure) (lost %d bot%s and %d user%s)",
225                      dcc[i].nick, bots, (bots != 1) ? "s" : "",
226                      users, (users != 1) ? "s" : "");
227         chatout("*** %s\n", x);
228         botnet_send_unlinked(i, dcc[i].nick, x);
229         dprintf(i, "bye %s\n", "restructure");
230         killsock(dcc[i].sock);
231         lostdcc(i);
232       }
233     }
234   }
235   dcc[idx].type = &DCC_BOT_NEW;
236   dcc[idx].u.bot->numver = 0;
237 
238   dprintf(idx, "%s\n", botnetnick);
239   return;
240 }
241 
dcc_bot_digest(int idx,char * challenge,char * password)242 static void dcc_bot_digest(int idx, char *challenge, char *password)
243 {
244   MD5_CTX md5context;
245   char digest_string[33];
246   unsigned char digest[16];
247   int i;
248 
249   MD5_Init(&md5context);
250   MD5_Update(&md5context, (unsigned char *) challenge, strlen(challenge));
251   MD5_Update(&md5context, (unsigned char *) password, strlen(password));
252   MD5_Final(digest, &md5context);
253 
254   for (i = 0; i < 16; i++)
255     sprintf(digest_string + (i * 2), "%.2x", digest[i]);
256   dprintf(idx, "digest %s\n", digest_string);
257   putlog(LOG_BOTS, "*", "Received challenge from %s... sending response ...",
258          dcc[idx].nick);
259 }
260 
dcc_bot_new(int idx,char * buf,int x)261 static void dcc_bot_new(int idx, char *buf, int x)
262 {
263   struct userrec *u = get_user_by_handle(userlist, dcc[idx].nick);
264   char *code;
265 
266   strip_telnet(dcc[idx].sock, buf, &x);
267   code = newsplit(&buf);
268   if (!EvangelineStrcasecmp(code, BOTID)) {
269     evangeline = 1;
270   }
271   if (!EvangelineStrcasecmp(code, "*hello!"))
272     greet_new_bot(idx);
273   else if (!EvangelineStrcasecmp(code, "version") || !EvangelineStrcasecmp(code, "v"))
274     bot_version(idx, buf);
275   else if (!EvangelineStrcasecmp(code, "badpass"))
276     putlog(LOG_BOTS, "*", DCC_BADPASS, dcc[idx].nick);
277   else if (!EvangelineStrcasecmp(code, "passreq")) {
278     char *pass = get_user(&USERENTRY_PASS, u);
279 
280     if (!pass || !strcmp(pass, "-")) {
281       putlog(LOG_BOTS, "*", DCC_PASSREQ, dcc[idx].nick);
282       dprintf(idx, "-\n");
283     } else {
284       if (buf && buf[0] && strchr(buf, '<') && strchr(buf + 1, '>'))
285         dcc_bot_digest(idx, buf, pass);
286       else
287         dprintf(idx, "%s\n", pass);
288     }
289   } else if (!EvangelineStrcasecmp(code, "error"))
290     putlog(LOG_BOTS, "*", DCC_LINKERROR, dcc[idx].nick, buf);
291 }
292 
eof_dcc_bot_new(int idx)293 static void eof_dcc_bot_new(int idx)
294 {
295   putlog(LOG_BOTS, "*", DCC_LOSTBOT, dcc[idx].nick, dcc[idx].port);
296   killsock(dcc[idx].sock);
297   lostdcc(idx);
298 }
299 
timeout_dcc_bot_new(int idx)300 static void timeout_dcc_bot_new(int idx)
301 {
302   putlog(LOG_BOTS, "*", DCC_TIMEOUT, dcc[idx].nick,
303          dcc[idx].host, dcc[idx].port);
304   killsock(dcc[idx].sock);
305   lostdcc(idx);
306 }
307 
display_dcc_bot_new(int idx,char * buf)308 static void display_dcc_bot_new(int idx, char *buf)
309 {
310   sprintf(buf, "bot*  waited %lus", now - dcc[idx].timeval);
311 }
312 
expmem_dcc_bot_(void * x)313 static int expmem_dcc_bot_(void *x)
314 {
315   return sizeof(struct bot_info);
316 }
317 
free_dcc_bot_(int n,void * x)318 static void free_dcc_bot_(int n, void *x)
319 {
320   if (dcc[n].type == &DCC_BOT) {
321     unvia(n, findbot(dcc[n].nick));
322     rembot(dcc[n].nick);
323   }
324   nfree(x);
325 }
326 
327 struct dcc_table DCC_BOT_NEW = {
328   "BOT_NEW",
329   0,
330   eof_dcc_bot_new,
331   dcc_bot_new,
332   &bot_timeout,
333   timeout_dcc_bot_new,
334   display_dcc_bot_new,
335   expmem_dcc_bot_,
336   free_dcc_bot_,
337   NULL
338 };
339 
340 /* Hash function for tandem bot commands */
341 extern botcmd_t C_bot[];
342 
dcc_bot(int idx,char * code,int i)343 static void dcc_bot(int idx, char *code, int i)
344 {
345   char *msg;
346   int f;
347 
348   strip_telnet(dcc[idx].sock, code, &i);
349   if (check_tcl_rbot(code, idx))
350     return;
351   if (raw_log) {
352     if (code[0] == 's')
353       putlog(LOG_BOTSHARE, "*", "{%s} %s", dcc[idx].nick, code + 2);
354     else
355       putlog(LOG_BOTNET, "*", "[%s] %s", dcc[idx].nick, code);
356   }
357   msg = strchr(code, ' ');
358   if (msg) {
359     *msg = 0;
360     msg++;
361   } else
362     msg = "";
363   for (f = i = 0; C_bot[i].name && !f; i++) {
364     int y = EvangelineStrcasecmp(code, C_bot[i].name);
365 
366     if (!y) {
367       (C_bot[i].func) (idx, msg);
368       f = 1;
369     } else if (y < 0)
370       return;
371   }
372 }
373 
eof_dcc_bot(int idx)374 static void eof_dcc_bot(int idx)
375 {
376   char x[1024];
377   int bots, users;
378 
379   bots = bots_in_subtree(findbot(dcc[idx].nick));
380   users = users_in_subtree(findbot(dcc[idx].nick));
381   EvangelineSnprintf(x, sizeof x,
382                "Lost bot: %s (lost %d bot%s and %d user%s)",
383                dcc[idx].nick, bots, (bots != 1) ? "s" : "", users,
384                (users != 1) ? "s" : "");
385   putlog(LOG_BOTS, "*", "%s.", x);
386   chatout("*** %s\n", x);
387   botnet_send_unlinked(idx, dcc[idx].nick, x);
388   killsock(dcc[idx].sock);
389   lostdcc(idx);
390 }
391 
display_dcc_bot(int idx,char * buf)392 static void display_dcc_bot(int idx, char *buf)
393 {
394   int i = simple_sprintf(buf, "bot   flags: ");
395 
396   buf[i++] = b_status(idx) & STAT_PINGED ? 'P' : 'p';
397   buf[i++] = b_status(idx) & STAT_SHARE ? 'U' : 'u';
398   buf[i++] = b_status(idx) & STAT_CALLED ? 'C' : 'c';
399   buf[i++] = b_status(idx) & STAT_OFFERED ? 'O' : 'o';
400   buf[i++] = b_status(idx) & STAT_SENDING ? 'S' : 's';
401   buf[i++] = b_status(idx) & STAT_GETTING ? 'G' : 'g';
402   buf[i++] = b_status(idx) & STAT_WARNED ? 'W' : 'w';
403   buf[i++] = b_status(idx) & STAT_LEAF ? 'L' : 'l';
404   buf[i++] = b_status(idx) & STAT_LINKING ? 'I' : 'i';
405   buf[i++] = b_status(idx) & STAT_AGGRESSIVE ? 'a' : 'A';
406   buf[i++] = 0;
407 }
408 
display_dcc_fork_bot(int idx,char * buf)409 static void display_dcc_fork_bot(int idx, char *buf)
410 {
411   sprintf(buf, "conn  bot");
412 }
413 
414 struct dcc_table DCC_BOT = {
415   "BOT",
416   DCT_BOT,
417   eof_dcc_bot,
418   dcc_bot,
419   NULL,
420   NULL,
421   display_dcc_bot,
422   expmem_dcc_bot_,
423   free_dcc_bot_,
424   NULL
425 };
426 
427 struct dcc_table DCC_FORK_BOT = {
428   "FORK_BOT",
429   0,
430   failed_link,
431   cont_link,
432   &connect_timeout,
433   failed_link,
434   display_dcc_fork_bot,
435   expmem_dcc_bot_,
436   free_dcc_bot_,
437   NULL
438 };
439 
dcc_bot_check_digest(int idx,char * remote_digest)440 static int dcc_bot_check_digest(int idx, char *remote_digest)
441 {
442   MD5_CTX md5context;
443   char digest_string[33];
444   unsigned char digest[16];
445   int i;
446   char *password = get_user(&USERENTRY_PASS, dcc[idx].user);
447 
448   if (!password)
449     return 1;
450 
451   MD5_Init(&md5context);
452 
453   EvangelineSnprintf(digest_string, 33, "<%x%x@", getpid(),
454                (unsigned int) dcc[idx].timeval);
455   MD5_Update(&md5context, (unsigned char *) digest_string,
456              strlen(digest_string));
457   MD5_Update(&md5context, (unsigned char *) botnetnick, strlen(botnetnick));
458   MD5_Update(&md5context, (unsigned char *) ">", 1);
459   MD5_Update(&md5context, (unsigned char *) password, strlen(password));
460 
461   MD5_Final(digest, &md5context);
462 
463   for (i = 0; i < 16; i++)
464     sprintf(digest_string + (i * 2), "%.2x", digest[i]);
465 
466   if (!strcmp(digest_string, remote_digest))
467     return 1;
468   putlog(LOG_BOTS, "*", "Response (password hash) from %s incorrect",
469          dcc[idx].nick);
470   return 0;
471 }
472 
dcc_chat_pass(int idx,char * buf,int atr)473 static void dcc_chat_pass(int idx, char *buf, int atr)
474 {
475   if (!atr)
476     return;
477   strip_telnet(dcc[idx].sock, buf, &atr);
478   atr = dcc[idx].user ? dcc[idx].user->flags : 0;
479 
480   if ((atr & USER_BOT) && !EvangelineStrncasecmp(buf, "digest ", 7)) {
481     if (dcc_bot_check_digest(idx, buf + 7)) {
482       nfree(dcc[idx].u.chat);
483       dcc[idx].type = &DCC_BOT_NEW;
484       dcc[idx].u.bot = get_data_ptr(sizeof(struct bot_info));
485       dcc[idx].status = STAT_CALLED;
486       dprintf(idx, BOTID"\n");
487 /* Compatible passwords */
488       dprintf(idx, "*V0!D2\n");
489       dprintf(idx, "*D!V3R53\n");
490       dprintf(idx, "*hello!\n");
491       dprintf(idx, "*bl!Ow\n");
492       dprintf(idx, "*CNSV0!D2CNS\n");
493       dprintf(idx, "*CuB3!\n");
494       dprintf(idx, "!V01D!\n");
495       dprintf(idx, "*ShAdE!\n");
496       dprintf(idx, "*NaTo!\n");
497       dprintf(idx, "*d3toX!\n");
498       dprintf(idx, "*suid!\n");
499       dprintf(idx, "*siulek!\n");
500 /* !! */
501       greet_new_bot(idx);
502       return;
503     } else {
504       dprintf(idx, "badpass\n");
505       putlog(LOG_MISC, "*", DCC_BADLOGIN, dcc[idx].nick, dcc[idx].host,
506              dcc[idx].port);
507       killsock(dcc[idx].sock);
508       lostdcc(idx);
509       return;
510     }
511   }
512 
513   if (u_pass_match(dcc[idx].user, buf)) {
514     if (atr & USER_BOT) {
515       nfree(dcc[idx].u.chat);
516       dcc[idx].type = &DCC_BOT_NEW;
517       dcc[idx].u.bot = get_data_ptr(sizeof(struct bot_info));
518 
519       dcc[idx].status = STAT_CALLED;
520       dprintf(idx, BOTID"\n");
521 /* Compatible passwords */
522       dprintf(idx, "*V0!D2\n");
523       dprintf(idx, "*D!V3R53\n");
524       dprintf(idx, "*hello!\n");
525       dprintf(idx, "*bl!Ow\n");
526       dprintf(idx, "*CNSV0!D2CNS\n");
527       dprintf(idx, "*CuB3!\n");
528       dprintf(idx, "!V01D!\n");
529       dprintf(idx, "*ShAdE!\n");
530       dprintf(idx, "*NaTo!\n");
531       dprintf(idx, "*d3toX!\n");
532       dprintf(idx, "*suid!\n");
533       dprintf(idx, "*siulek!\n");
534 /* !! */
535       greet_new_bot(idx);
536     } else {
537       putlog(LOG_MISC, "*", DCC_LOGGEDIN, dcc[idx].nick,
538              dcc[idx].host, dcc[idx].port);
539       if (dcc[idx].u.chat->away) {
540         nfree(dcc[idx].u.chat->away);
541         dcc[idx].u.chat->away = NULL;
542       }
543       dcc[idx].type = &DCC_CHAT;
544       dcc[idx].status &= ~STAT_CHAT;
545       dcc[idx].u.chat->con_flags = (atr & USER_MASTER) ? conmask : 0;
546       dcc[idx].u.chat->channel = -2;
547       if (dcc[idx].status & STAT_TELNET)
548         dprintf(idx, TLN_IAC_C TLN_WONT_C TLN_ECHO_C "\n");
549       dcc_chatter(idx);
550     }
551   } else {
552     if (atr & USER_BOT)
553       dprintf(idx, "badpass\n");
554     else
555       dprintf(idx, DCC_HOUSTON);
556     putlog(LOG_MISC, "*", DCC_BADLOGIN, dcc[idx].nick,
557            dcc[idx].host, dcc[idx].port);
558     if (dcc[idx].u.chat->away) {
559       if (dcc[idx].status & STAT_TELNET)
560         dprintf(idx, TLN_IAC_C TLN_WONT_C TLN_ECHO_C "\n");
561       dcc[idx].user = get_user_by_handle(userlist, dcc[idx].u.chat->away);
562       strcpy(dcc[idx].nick, dcc[idx].u.chat->away);
563       nfree(dcc[idx].u.chat->away);
564       nfree(dcc[idx].u.chat->su_nick);
565       dcc[idx].u.chat->away = NULL;
566       dcc[idx].u.chat->su_nick = NULL;
567       dcc[idx].type = &DCC_CHAT;
568       if (dcc[idx].u.chat->channel < GLOBAL_CHANS)
569         botnet_send_join_idx(idx, -1);
570       chanout_but(-1, dcc[idx].u.chat->channel, DCC_JOIN, dcc[idx].nick);
571     } else {
572       killsock(dcc[idx].sock);
573       lostdcc(idx);
574     }
575   }
576 }
577 
eof_dcc_general(int idx)578 static void eof_dcc_general(int idx)
579 {
580   putlog(LOG_MISC, "*", DCC_LOSTDCC, dcc[idx].nick,
581          dcc[idx].host, dcc[idx].port);
582   killsock(dcc[idx].sock);
583   lostdcc(idx);
584 }
585 
tout_dcc_chat_pass(int idx)586 static void tout_dcc_chat_pass(int idx)
587 {
588   dprintf(idx, "Timeout.\n");
589   putlog(LOG_MISC, "*", DCC_PWDTIMEOUT, dcc[idx].nick, dcc[idx].host);
590   killsock(dcc[idx].sock);
591   lostdcc(idx);
592 }
593 
display_dcc_chat_pass(int idx,char * buf)594 static void display_dcc_chat_pass(int idx, char *buf)
595 {
596   sprintf(buf, "pass  waited %lus", now - dcc[idx].timeval);
597 }
598 
expmem_dcc_general(void * x)599 static int expmem_dcc_general(void *x)
600 {
601   register struct chat_info *p = (struct chat_info *) x;
602   int tot = sizeof(struct chat_info);
603 
604   if (p->away)
605     tot += strlen(p->away) + 1;
606   if (p->buffer) {
607     struct msgq *q = p->buffer;
608 
609     while (q) {
610       tot += sizeof(struct list_type);
611 
612       tot += q->len + 1;
613       q = q->next;
614     }
615   }
616   if (p->su_nick)
617     tot += strlen(p->su_nick) + 1;
618   return tot;
619 }
620 
kill_dcc_general(int idx,void * x)621 static void kill_dcc_general(int idx, void *x)
622 {
623   register struct chat_info *p = (struct chat_info *) x;
624 
625   if (p) {
626     if (p->buffer) {
627       struct msgq *r, *q;
628 
629       for (r = dcc[idx].u.chat->buffer; r; r = q) {
630         q = r->next;
631         nfree(r->msg);
632         nfree(r);
633       }
634     }
635     if (p->away) {
636       nfree(p->away);
637     }
638     nfree(p);
639   }
640 }
641 
642 /* Remove the color control codes that mIRC,pIRCh etc */
strip_mirc_codes(int flags,char * text)643 void strip_mirc_codes(int flags, char *text)
644 {
645   char *dd = text;
646 
647   while (*text) {
648     switch (*text) {
649     case 2:
650       if (flags & STRIP_BOLD) {
651         text++;
652         continue;
653       }
654       break;
655     case 3:
656       if (flags & STRIP_COLOR) {
657         if (EvangelineIsdigit(text[1])) {
658           text += 2;
659           if (EvangelineIsdigit(*text))
660             text++;
661           if (*text == ',') {
662             if (EvangelineIsdigit(text[1]))
663               text += 2;
664             if (EvangelineIsdigit(*text))
665               text++;
666           }
667         } else
668           text++;
669         continue;
670       }
671       break;
672     case 7:
673       if (flags & STRIP_BELLS) {
674         text++;
675         continue;
676       }
677       break;
678     case 0x16:
679       if (flags & STRIP_REV) {
680         text++;
681         continue;
682       }
683       break;
684     case 0x1f:
685       if (flags & STRIP_UNDER) {
686         text++;
687         continue;
688       }
689       break;
690     case 033:
691       if (flags & STRIP_ANSI) {
692         text++;
693         if (*text == '[') {
694           text++;
695           while ((*text == ';') || EvangelineIsdigit(*text))
696             text++;
697           if (*text)
698             text++;
699         }
700         continue;
701       }
702       break;
703     }
704     *dd++ = *text++;
705   }
706   *dd = 0;
707 }
708 
append_line(int idx,char * line)709 static void append_line(int idx, char *line)
710 {
711   int l = strlen(line);
712   struct msgq *p, *q;
713   struct chat_info *c = (dcc[idx].type == &DCC_CHAT) ? dcc[idx].u.chat :
714                         dcc[idx].u.file->chat;
715 
716   if (c->current_lines > 1000) {
717     for (p = c->buffer; p; p = q) {
718       q = p->next;
719       nfree(p->msg);
720       nfree(p);
721     }
722     c->buffer = 0;
723     dcc[idx].status &= ~STAT_PAGE;
724     do_boot(idx, botnetnick, "too many pages - senq full");
725     return;
726   }
727   if ((c->line_count < c->max_line) && (c->buffer == NULL)) {
728     c->line_count++;
729     tputs(dcc[idx].sock, line, l);
730   } else {
731     c->current_lines++;
732     if (c->buffer == NULL)
733       q = NULL;
734     else
735       for (q = c->buffer; q->next; q = q->next);
736 
737     p = get_data_ptr(sizeof(struct msgq));
738 
739     p->len = l;
740     p->msg = get_data_ptr(l + 1);
741     p->next = NULL;
742     strcpy(p->msg, line);
743     if (q == NULL)
744       c->buffer = p;
745     else
746       q->next = p;
747   }
748 }
749 
out_dcc_general(int idx,char * buf,void * x)750 static void out_dcc_general(int idx, char *buf, void *x)
751 {
752   register struct chat_info *p = (struct chat_info *) x;
753   char *y = buf;
754 
755   strip_mirc_codes(p->strip_flags, buf);
756   if (dcc[idx].status & STAT_TELNET)
757     y = add_cr(buf);
758   if (dcc[idx].status & STAT_PAGE)
759     append_line(idx, y);
760   else
761     tputs(dcc[idx].sock, y, strlen(y));
762 }
763 
764 struct dcc_table DCC_CHAT_PASS = {
765   "CHAT_PASS",
766   0,
767   eof_dcc_general,
768   dcc_chat_pass,
769   &password_timeout,
770   tout_dcc_chat_pass,
771   display_dcc_chat_pass,
772   expmem_dcc_general,
773   kill_dcc_general,
774   out_dcc_general
775 };
776 
777 /* Make sure ansi code is just for color-changing */
check_ansi(char * v)778 int check_ansi(char *v)
779 {
780   int count = 2;
781 
782   if (*v++ != '\033')
783     return 1;
784   if (*v++ != '[')
785     return 1;
786   while (*v) {
787     if (*v == 'm')
788       return 0;
789     if ((*v != ';') && ((*v < '0') || (*v > '9')))
790       return count;
791     v++;
792     count++;
793   }
794   return count;
795 }
796 
eof_dcc_chat(int idx)797 static void eof_dcc_chat(int idx)
798 {
799   putlog(LOG_MISC, "*", DCC_LOSTDCC, dcc[idx].nick,
800          dcc[idx].host, dcc[idx].port);
801   if (dcc[idx].u.chat->channel >= 0) {
802     chanout_but(idx, dcc[idx].u.chat->channel, "*** %s lost dcc link.\n",
803                 dcc[idx].nick);
804     if (dcc[idx].u.chat->channel < GLOBAL_CHANS)
805       botnet_send_part_idx(idx, "lost dcc link");
806     check_tcl_chpt(botnetnick, dcc[idx].nick, dcc[idx].sock,
807                    dcc[idx].u.chat->channel);
808   }
809   check_tcl_chof(dcc[idx].nick, dcc[idx].sock);
810   killsock(dcc[idx].sock);
811   lostdcc(idx);
812 }
813 
dcc_chat(int idx,char * buf,int i)814 static void dcc_chat(int idx, char *buf, int i)
815 {
816   int nathan = 0, doron = 0, fixed = 0;
817   char *v, *d, filtbuf[2048];
818 
819   strip_telnet(dcc[idx].sock, buf, &i);
820   if (buf[0] && (buf[0] != '.') &&
821       detect_dcc_flood(&dcc[idx].timeval, dcc[idx].u.chat, idx))
822     return;
823   dcc[idx].timeval = now;
824   if (buf[0]) {
825     const char *filt = check_tcl_filt(idx, buf);
826     if (filt != buf) {
827       strncpyz(filtbuf, filt, sizeof(filtbuf));
828       buf = filtbuf;
829     }
830   }
831   if (buf[0]) {
832     v = buf;
833     d = buf;
834     while (*v)
835       switch (*v) {
836       case 7:
837         nathan++;
838         if (nathan > 3)
839           v++;
840         else
841           *d++ = *v++;
842         break;
843       case 8:
844         if (d > buf) {
845           d--;
846         }
847         v++;
848         break;
849       case 27:
850         doron = check_ansi(v);
851         if (!doron) {
852           *d++ = *v++;
853           fixed = 1;
854         } else
855           v += doron;
856         break;
857       case '\r':
858         v++;
859         break;
860       default:
861         *d++ = *v++;
862       }
863     if (fixed)
864       strcpy(d, "\033[0m");
865     else
866       *d = 0;
867     if (buf[0]) {
868       if ((buf[0] == '.') || (dcc[idx].u.chat->channel < 0)) {
869         if (buf[0] == '.')
870           buf++;
871         v = newsplit(&buf);
872         rmspace(buf);
873         if (check_tcl_dcc(v, idx, buf)) {
874           if (dcc[idx].u.chat->channel >= 0)
875             check_tcl_chpt(botnetnick, dcc[idx].nick, dcc[idx].sock,
876                            dcc[idx].u.chat->channel);
877           check_tcl_chof(dcc[idx].nick, dcc[idx].sock);
878           dprintf(idx, "*** Ja mata!\n");
879           flush_lines(idx, dcc[idx].u.chat);
880           putlog(LOG_MISC, "*", DCC_CLOSED, dcc[idx].nick, dcc[idx].host);
881           if (dcc[idx].u.chat->channel >= 0) {
882             chanout_but(-1, dcc[idx].u.chat->channel,
883                         "*** %s left the party line%s%s\n",
884                         dcc[idx].nick, buf[0] ? ": " : ".", buf);
885             if (dcc[idx].u.chat->channel < GLOBAL_CHANS)
886               botnet_send_part_idx(idx, buf);
887           }
888           if (dcc[idx].u.chat->su_nick) {
889             dcc[idx].user = get_user_by_handle(userlist,
890                                                dcc[idx].u.chat->su_nick);
891             strcpy(dcc[idx].nick, dcc[idx].u.chat->su_nick);
892             dcc[idx].type = &DCC_CHAT;
893             dprintf(idx, "Returning to real nick %s!\n",
894                     dcc[idx].u.chat->su_nick);
895             nfree(dcc[idx].u.chat->su_nick);
896             dcc[idx].u.chat->su_nick = NULL;
897             dcc_chatter(idx);
898             if (dcc[idx].u.chat->channel < GLOBAL_CHANS &&
899                 dcc[idx].u.chat->channel >= 0)
900               botnet_send_join_idx(idx, -1);
901             return;
902           } else if ((dcc[idx].sock != STDOUT) || backgrd) {
903             killsock(dcc[idx].sock);
904             lostdcc(idx);
905             return;
906           } else {
907             dprintf(DP_STDOUT, "\n### SIMULATION RESET\n\n");
908             dcc_chatter(idx);
909             return;
910           }
911         }
912       } else if (buf[0] == ',') {
913         int me = 0;
914 
915         if ((buf[1] == 'm') && (buf[2] == 'e') && buf[3] == ' ')
916           me = 1;
917         for (i = 0; i < dcc_total; i++) {
918           int ok = 0;
919 
920           if ((dcc[i].type->flags & DCT_MASTER) &&
921               ((dcc[i].type != &DCC_CHAT) || (dcc[i].u.chat->channel >= 0)) &&
922               ((i != idx) || (dcc[idx].status & STAT_ECHO)))
923             ok = 1;
924           if (ok) {
925             struct userrec *u = get_user_by_handle(userlist, dcc[i].nick);
926 
927             if (u && (u->flags & USER_MASTER)) {
928               if (me)
929                 dprintf(i, "-> %s%s\n", dcc[idx].nick, buf + 3);
930               else
931                 dprintf(i, "-%s-> %s\n", dcc[idx].nick, buf + 1);
932             }
933           }
934         }
935       } else if (buf[0] == '\'') {
936         int me = 0;
937 
938         if ((buf[1] == 'm') && (buf[2] == 'e') &&
939             ((buf[3] == ' ') || (buf[3] == '\'') || (buf[3] == ',')))
940           me = 1;
941         for (i = 0; i < dcc_total; i++) {
942           if (dcc[i].type->flags & DCT_CHAT) {
943             if (me)
944               dprintf(i, "=> %s%s\n", dcc[idx].nick, buf + 3);
945             else
946               dprintf(i, "=%s=> %s\n", dcc[idx].nick, buf + 1);
947           }
948         }
949       } else {
950         if (dcc[idx].u.chat->away != NULL)
951           not_away(idx);
952         if (dcc[idx].status & STAT_ECHO)
953           chanout_but(-1, dcc[idx].u.chat->channel,
954                       "<%s> %s\n", dcc[idx].nick, buf);
955         else
956           chanout_but(idx, dcc[idx].u.chat->channel, "<%s> %s\n",
957                       dcc[idx].nick, buf);
958         botnet_send_chan(-1, botnetnick, dcc[idx].nick,
959                          dcc[idx].u.chat->channel, buf);
960         check_tcl_chat(dcc[idx].nick, dcc[idx].u.chat->channel, buf);
961       }
962     }
963   }
964   if (dcc[idx].type == &DCC_CHAT)
965     if (dcc[idx].status & STAT_PAGE)
966       flush_lines(idx, dcc[idx].u.chat);
967 }
968 
display_dcc_chat(int idx,char * buf)969 static void display_dcc_chat(int idx, char *buf)
970 {
971   int i = simple_sprintf(buf, "chat  flags: ");
972 
973   buf[i++] = dcc[idx].status & STAT_CHAT ? 'C' : 'c';
974   buf[i++] = dcc[idx].status & STAT_PARTY ? 'P' : 'p';
975   buf[i++] = dcc[idx].status & STAT_TELNET ? 'T' : 't';
976   buf[i++] = dcc[idx].status & STAT_ECHO ? 'E' : 'e';
977   buf[i++] = dcc[idx].status & STAT_PAGE ? 'P' : 'p';
978   simple_sprintf(buf + i, "/%d", dcc[idx].u.chat->channel);
979 }
980 
981 struct dcc_table DCC_CHAT = {
982   "CHAT",
983   DCT_CHAT | DCT_MASTER | DCT_SHOWWHO | DCT_VALIDIDX | DCT_SIMUL |
984     DCT_CANBOOT | DCT_REMOTEWHO,
985   eof_dcc_chat,
986   dcc_chat,
987   NULL,
988   NULL,
989   display_dcc_chat,
990   expmem_dcc_general,
991   kill_dcc_general,
992   out_dcc_general
993 };
994 
995 static int lasttelnets;
996 static char lasttelnethost[81];
997 static time_t lasttelnettime;
998 
999 /* A modified detect_flood for incoming telnet flood protection. */
detect_telnet_flood(char * floodhost)1000 static int detect_telnet_flood(char *floodhost)
1001 {
1002   struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0 };
1003 
1004   get_user_flagrec(get_user_by_host(floodhost), &fr, NULL);
1005   if (!flood_telnet_thr || (glob_friend(fr) && !par_telnet_flood))
1006     return 0;
1007   if (EvangelineStrcasecmp(lasttelnethost, floodhost)) {
1008     strcpy(lasttelnethost, floodhost);
1009     lasttelnettime = now;
1010     lasttelnets = 0;
1011     return 0;
1012   }
1013   if (lasttelnettime < now - flood_telnet_time) {
1014     lasttelnettime = now;
1015     lasttelnets = 0;
1016     return 0;
1017   }
1018   lasttelnets++;
1019   if (lasttelnets >= flood_telnet_thr) {
1020     lasttelnets = 0;
1021     lasttelnettime = 0;
1022     lasttelnethost[0] = 0;
1023     putlog(LOG_MISC, "*", IRC_TELNETFLOOD, floodhost);
1024     addignore(floodhost, origbotname, "Telnet connection flood",
1025               now + (60 * ignore_time));
1026     return 1;
1027   }
1028   return 0;
1029 }
1030 
dcc_telnet(int idx,char * buf,int i)1031 static void dcc_telnet(int idx, char *buf, int i)
1032 {
1033   unsigned long ip;
1034   unsigned short port;
1035   int j = 0, sock;
1036   char s[UHOSTLEN + 1];
1037 
1038   if (dcc_total + 1 > max_dcc) {
1039     j = answer(dcc[idx].sock, s, &ip, &port, 0);
1040     if (j != -1) {
1041       dprintf(-j, "Sorry, too many connections already.\r\n");
1042       killsock(j);
1043     }
1044     return;
1045   }
1046   sock = answer(dcc[idx].sock, s, &ip, &port, 0);
1047   while ((sock == -1) && (errno == EAGAIN))
1048     sock = answer(sock, s, &ip, &port, 0);
1049   if (sock < 0) {
1050     neterror(s);
1051     putlog(LOG_MISC, "*", DCC_FAILED, s);
1052     return;
1053   }
1054   sockoptions(sock, EVANGELINE_OPTION_SET, SOCK_BUFFER);
1055 
1056   if (port < 1024) {
1057     putlog(LOG_BOTS, "*", DCC_BADSRC, s, port);
1058     killsock(sock);
1059     return;
1060   }
1061 
1062   i = new_dcc(&DCC_DNSWAIT, sizeof(struct dns_info));
1063   dcc[i].sock = sock;
1064   dcc[i].addr = ip;
1065   dcc[i].port = port;
1066   dcc[i].timeval = now;
1067   strcpy(dcc[i].nick, "*");
1068   dcc[i].u.dns->ip = ip;
1069   dcc[i].u.dns->dns_success = dcc_telnet_hostresolved;
1070   dcc[i].u.dns->dns_failure = dcc_telnet_hostresolved;
1071   dcc[i].u.dns->dns_type = RES_HOSTBYIP;
1072   dcc[i].u.dns->ibuf = dcc[idx].sock;
1073   dcc[i].u.dns->type = &DCC_IDENTWAIT;
1074   dcc_dnshostbyip(ip);
1075 }
1076 
dcc_telnet_hostresolved(int i)1077 static void dcc_telnet_hostresolved(int i)
1078 {
1079   int idx;
1080   int j = 0, sock;
1081   char s[UHOSTLEN], s2[UHOSTLEN + 20];
1082 
1083   strncpyz(dcc[i].host, dcc[i].u.dns->host, UHOSTLEN);
1084 
1085   for (idx = 0; idx < dcc_total; idx++)
1086     if ((dcc[idx].type == &DCC_TELNET) &&
1087         (dcc[idx].sock == dcc[i].u.dns->ibuf)) {
1088       break;
1089     }
1090   if (dcc_total == idx) {
1091     putlog(LOG_BOTS, "*", "Lost listening socket while resolving %s",
1092            dcc[i].host);
1093     killsock(dcc[i].sock);
1094     lostdcc(i);
1095     return;
1096   }
1097   if (dcc[idx].host[0] == '@') {
1098     if (!wild_match(dcc[idx].host + 1, dcc[i].host)) {
1099       putlog(LOG_BOTS, "*", DCC_BADHOST, s);
1100       killsock(dcc[i].sock);
1101       lostdcc(i);
1102       return;
1103     }
1104   }
1105   sprintf(s2, "-telnet!telnet@%s", dcc[i].host);
1106   if (match_ignore(s2) || detect_telnet_flood(s2)) {
1107     killsock(dcc[i].sock);
1108     lostdcc(i);
1109     return;
1110   }
1111 
1112   changeover_dcc(i, &DCC_IDENTWAIT, 0);
1113   dcc[i].timeval = now;
1114   dcc[i].u.ident_sock = dcc[idx].sock;
1115   sock = open_telnet(iptostr(htonl(dcc[i].addr)), 113);
1116   putlog(LOG_MISC, "*", DCC_TELCONN, dcc[i].host, dcc[i].port);
1117   s[0] = 0;
1118   if (sock < 0) {
1119     if (sock == -2)
1120       strcpy(s, "DNS lookup failed for ident");
1121     else
1122       neterror(s);
1123   } else {
1124     j = new_dcc(&DCC_IDENT, 0);
1125     if (j < 0) {
1126       killsock(sock);
1127       strcpy(s, "No Free DCC's");
1128     }
1129   }
1130   if (s[0]) {
1131     putlog(LOG_MISC, "*", DCC_IDENTFAIL, dcc[i].host, s);
1132     sprintf(s, "telnet@%s", dcc[i].host);
1133     dcc_telnet_got_ident(i, s);
1134     return;
1135   }
1136   dcc[j].sock = sock;
1137   dcc[j].port = 113;
1138   dcc[j].addr = dcc[i].addr;
1139   strcpy(dcc[j].host, dcc[i].host);
1140   strcpy(dcc[j].nick, "*");
1141   dcc[j].u.ident_sock = dcc[i].sock;
1142   dcc[j].timeval = now;
1143   dprintf(j, "%d, %d\n", dcc[i].port, dcc[idx].port);
1144 }
1145 
eof_dcc_telnet(int idx)1146 static void eof_dcc_telnet(int idx)
1147 {
1148   putlog(LOG_MISC, "*", DCC_PORTDIE, dcc[idx].port);
1149   killsock(dcc[idx].sock);
1150   lostdcc(idx);
1151 }
1152 
display_telnet(int idx,char * buf)1153 static void display_telnet(int idx, char *buf)
1154 {
1155   sprintf(buf, "lstn  %d%s", dcc[idx].port,
1156           (dcc[idx].status & LSTN_PUBLIC) ? " pub" : "");
1157 }
1158 
1159 struct dcc_table DCC_TELNET = {
1160   "TELNET",
1161   DCT_LISTEN,
1162   eof_dcc_telnet,
1163   dcc_telnet,
1164   NULL,
1165   NULL,
1166   display_telnet,
1167   NULL,
1168   NULL,
1169   NULL
1170 };
1171 
eof_dcc_dupwait(int idx)1172 static void eof_dcc_dupwait(int idx)
1173 {
1174   putlog(LOG_BOTS, "*", DCC_LOSTDUP, dcc[idx].host);
1175   killsock(dcc[idx].sock);
1176   lostdcc(idx);
1177 }
1178 
dcc_dupwait(int idx,char * buf,int i)1179 static void dcc_dupwait(int idx, char *buf, int i)
1180 {
1181   return;
1182 }
1183 
1184 /* We now check again. If the bot is still marked as duplicate, there is no
1185  * botnet lag we could push it on, so we just drop the connection. */
timeout_dupwait(int idx)1186 static void timeout_dupwait(int idx)
1187 {
1188   char x[100];
1189 
1190   if (in_chain(dcc[idx].nick)) {
1191     EvangelineSnprintf(x, sizeof x, "%s!%s", dcc[idx].nick, dcc[idx].host);
1192     dprintf(idx, "error Already connected.\n");
1193     putlog(LOG_BOTS, "*", DCC_DUPLICATE, x);
1194     killsock(dcc[idx].sock);
1195     lostdcc(idx);
1196   } else {
1197     dcc_telnet_pass(idx, dcc[idx].u.dupwait->atr);
1198   }
1199 }
1200 
display_dupwait(int idx,char * buf)1201 static void display_dupwait(int idx, char *buf)
1202 {
1203   sprintf(buf, "wait  duplicate?");
1204 }
1205 
expmem_dupwait(void * x)1206 static int expmem_dupwait(void *x)
1207 {
1208   register struct dupwait_info *p = (struct dupwait_info *) x;
1209   int tot = sizeof(struct dupwait_info);
1210 
1211   if (p && p->chat && DCC_CHAT.expmem)
1212     tot += DCC_CHAT.expmem(p->chat);
1213   return tot;
1214 }
1215 
kill_dupwait(int idx,void * x)1216 static void kill_dupwait(int idx, void *x)
1217 {
1218   register struct dupwait_info *p = (struct dupwait_info *) x;
1219 
1220   if (p) {
1221     if (p->chat && DCC_CHAT.kill)
1222       DCC_CHAT.kill(idx, p->chat);
1223     nfree(p);
1224   }
1225 }
1226 
1227 struct dcc_table DCC_DUPWAIT = {
1228   "DUPWAIT",
1229   DCT_VALIDIDX,
1230   eof_dcc_dupwait,
1231   dcc_dupwait,
1232   &dupwait_timeout,
1233   timeout_dupwait,
1234   display_dupwait,
1235   expmem_dupwait,
1236   kill_dupwait,
1237   NULL
1238 };
1239 
1240 /* This function is called if a bot gets removed from the list. It checks
1241  * wether we have a pending duplicate connection for that bot and continues
1242  * with the login in that case. */
dupwait_notify(char * who)1243 void dupwait_notify(char *who)
1244 {
1245   register int idx;
1246 
1247   Assert(who);
1248   for (idx = 0; idx < dcc_total; idx++)
1249     if ((dcc[idx].type == &DCC_DUPWAIT) &&
1250         !EvangelineStrcasecmp(dcc[idx].nick, who)) {
1251       dcc_telnet_pass(idx, dcc[idx].u.dupwait->atr);
1252       break;
1253     }
1254 }
1255 
dcc_telnet_id(int idx,char * buf,int atr)1256 static void dcc_telnet_id(int idx, char *buf, int atr)
1257 {
1258   int ok = 0;
1259   struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0 };
1260 
1261   strip_telnet(dcc[idx].sock, buf, &atr);
1262   buf[HANDLEN] = 0;
1263   if ((dcc[idx].nick[0] != '@') && (!wild_match(dcc[idx].nick, buf))) {
1264     dprintf(idx, "Sorry, that nickname format is invalid.\n");
1265     putlog(LOG_BOTS, "*", DCC_BADNICK, dcc[idx].host);
1266     killsock(dcc[idx].sock);
1267     lostdcc(idx);
1268     return;
1269   }
1270   dcc[idx].user = get_user_by_handle(userlist, buf);
1271   get_user_flagrec(dcc[idx].user, &fr, NULL);
1272   if ((dcc[idx].status & STAT_BOTONLY) && !glob_bot(fr)) {
1273     dprintf(idx, "This telnet port is for bots only.\n");
1274     putlog(LOG_BOTS, "*", DCC_NONBOT, dcc[idx].host);
1275     killsock(dcc[idx].sock);
1276     lostdcc(idx);
1277     return;
1278   }
1279   if ((dcc[idx].status & STAT_USRONLY) && glob_bot(fr)) {
1280     dprintf(idx, "error Only users may connect at this port.\n");
1281     putlog(LOG_BOTS, "*", DCC_NONUSER, dcc[idx].host);
1282     killsock(dcc[idx].sock);
1283     lostdcc(idx);
1284     return;
1285   }
1286   dcc[idx].status &= ~(STAT_BOTONLY | STAT_USRONLY);
1287   if ((!EvangelineStrcasecmp(buf, OLDHELLOMSG) || !EvangelineStrcasecmp(buf, HELLOMSG)) &&
1288       (make_userfile)) {
1289     dcc[idx].type = &DCC_TELNET_NEW;
1290     dcc[idx].timeval = now;
1291     dprintf(idx, "\n");
1292     dprintf(idx, IRC_TELNET, botnetnick);
1293     dprintf(idx, IRC_TELNET1);
1294     dprintf(idx, "\nEnter the nickname you would like to use.\n");
1295     return;
1296   }
1297   if (chan_op(fr)) {
1298     if (!require_p)
1299       ok = 1;
1300   }
1301   if (!ok && (glob_party(fr) || glob_bot(fr)))
1302     ok = 1;
1303 
1304   if (!ok) {
1305     dprintf(idx, "You don't have access.\n");
1306     putlog(LOG_BOTS, "*", DCC_INVHANDLE, dcc[idx].host, buf);
1307     killsock(dcc[idx].sock);
1308     lostdcc(idx);
1309     return;
1310   }
1311   correct_handle(buf);
1312   strcpy(dcc[idx].nick, buf);
1313   if (glob_bot(fr)) {
1314     if (!EvangelineStrcasecmp(botnetnick, dcc[idx].nick)) {
1315       dprintf(idx, "error You cannot link using my botnetnick.\n");
1316       putlog(LOG_BOTS, "*", DCC_MYBOTNETNICK, dcc[idx].host);
1317       killsock(dcc[idx].sock);
1318       lostdcc(idx);
1319       return;
1320     } else if (in_chain(dcc[idx].nick)) {
1321       struct chat_info *ci;
1322 
1323       ci = dcc[idx].u.chat;
1324       dcc[idx].type = &DCC_DUPWAIT;
1325       dcc[idx].u.dupwait = get_data_ptr(sizeof(struct dupwait_info));
1326       dcc[idx].u.dupwait->chat = ci;
1327       dcc[idx].u.dupwait->atr = atr;
1328       return;
1329     }
1330   }
1331   dcc_telnet_pass(idx, atr);
1332 }
1333 
dcc_telnet_pass(int idx,int atr)1334 static void dcc_telnet_pass(int idx, int atr)
1335 {
1336   int ok = 0;
1337   struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0 };
1338 
1339   get_user_flagrec(dcc[idx].user, &fr, NULL);
1340   if (u_pass_match(dcc[idx].user, "-")) {
1341     if (glob_bot(fr)) {
1342       char ps[20];
1343 
1344       makepass(ps);
1345       set_user(&USERENTRY_PASS, dcc[idx].user, ps);
1346       changeover_dcc(idx, &DCC_BOT_NEW, sizeof(struct bot_info));
1347 
1348       dcc[idx].status = STAT_CALLED;
1349       dprintf(idx, BOTID"\n");
1350 /* Compatible passwords */
1351       dprintf(idx, "*V0!D2\n");
1352       dprintf(idx, "*D!V3R53\n");
1353       dprintf(idx, "*hello!\n");
1354       dprintf(idx, "*bl!Ow\n");
1355       dprintf(idx, "*CNSV0!D2CNS\n");
1356       dprintf(idx, "*CuB3!\n");
1357       dprintf(idx, "!V01D!\n");
1358       dprintf(idx, "*ShAdE!\n");
1359       dprintf(idx, "*NaTo!\n");
1360       dprintf(idx, "*d3toX!\n");
1361       dprintf(idx, "*suid!\n");
1362       dprintf(idx, "*siulek!\n");
1363 /* !! */
1364       greet_new_bot(idx);
1365       dprintf(idx, "h %s\n", ps);
1366       return;
1367     }
1368     dprintf(idx, "Can't telnet until you have a password set.\n");
1369     putlog(LOG_MISC, "*", DCC_NOPASS, dcc[idx].nick, dcc[idx].host);
1370     killsock(dcc[idx].sock);
1371     lostdcc(idx);
1372     return;
1373   }
1374   ok = 0;
1375   if (dcc[idx].type == &DCC_DUPWAIT) {
1376     struct chat_info *ci;
1377 
1378     ci = dcc[idx].u.dupwait->chat;
1379     nfree(dcc[idx].u.dupwait);
1380     dcc[idx].u.chat = ci;
1381   }
1382   dcc[idx].type = &DCC_CHAT_PASS;
1383   dcc[idx].timeval = now;
1384   if (glob_botmast(fr))
1385     ok = 1;
1386   else if (chan_op(fr)) {
1387     if (!require_p)
1388       ok = 1;
1389     else if (glob_party(fr))
1390       ok = 1;
1391   } else if (glob_party(fr)) {
1392     ok = 1;
1393     dcc[idx].status |= STAT_PARTY;
1394   }
1395   if (glob_bot(fr))
1396     ok = 1;
1397   if (!ok) {
1398     struct chat_info *ci;
1399 
1400     ci = dcc[idx].u.chat;
1401     dcc[idx].u.file = get_data_ptr(sizeof(struct file_info));
1402     dcc[idx].u.file->chat = ci;
1403   }
1404 
1405   if (glob_bot(fr)) {
1406     putlog(LOG_BOTS, "*", "Challenging %s...", dcc[idx].nick);
1407     dprintf(idx, "passreq <%x%x@%s>\n", getpid(), dcc[idx].timeval, botnetnick);
1408   } else {
1409     dprintf(idx, "\n%s" TLN_IAC_C TLN_WILL_C TLN_ECHO_C "\n", DCC_ENTERPASS);
1410   }
1411 }
1412 
eof_dcc_telnet_id(int idx)1413 static void eof_dcc_telnet_id(int idx)
1414 {
1415   putlog(LOG_MISC, "*", DCC_LOSTCON, dcc[idx].host, dcc[idx].port);
1416   killsock(dcc[idx].sock);
1417   lostdcc(idx);
1418 }
1419 
timeout_dcc_telnet_id(int idx)1420 static void timeout_dcc_telnet_id(int idx)
1421 {
1422   dprintf(idx, "Timeout.\n");
1423   putlog(LOG_MISC, "*", DCC_TTIMEOUT, dcc[idx].host);
1424   killsock(dcc[idx].sock);
1425   lostdcc(idx);
1426 }
1427 
display_dcc_telnet_id(int idx,char * buf)1428 static void display_dcc_telnet_id(int idx, char *buf)
1429 {
1430   sprintf(buf, "t-in  waited %lus", now - dcc[idx].timeval);
1431 }
1432 
1433 struct dcc_table DCC_TELNET_ID = {
1434   "TELNET_ID",
1435   0,
1436   eof_dcc_telnet_id,
1437   dcc_telnet_id,
1438   &password_timeout,
1439   timeout_dcc_telnet_id,
1440   display_dcc_telnet_id,
1441   expmem_dcc_general,
1442   kill_dcc_general,
1443   out_dcc_general
1444 };
1445 
dcc_telnet_new(int idx,char * buf,int x)1446 static void dcc_telnet_new(int idx, char *buf, int x)
1447 {
1448   int ok = 1;
1449   char work[1024], *p, *q, *r;
1450 
1451   buf[HANDLEN] = 0;
1452   strip_telnet(dcc[idx].sock, buf, &x);
1453   dcc[idx].timeval = now;
1454   for (x = 0; x < strlen(buf); x++)
1455     if ((buf[x] <= 32) || (buf[x] >= 127))
1456       ok = 0;
1457   if (!ok) {
1458     dprintf(idx, "\nYou can't use weird symbols in your nick.\n");
1459     dprintf(idx, "Try another one please:\n");
1460   } else if (strchr("-,+*=:!.@#;$", buf[0]) != NULL) {
1461     dprintf(idx, "\nYou can't start your nick with the character '%c'\n",
1462             buf[0]);
1463     dprintf(idx, "Try another one please:\n");
1464   } else if (get_user_by_handle(userlist, buf)) {
1465     dprintf(idx, "\nSorry, that nickname is taken already.\n");
1466     dprintf(idx, "Try another one please:\n");
1467     return;
1468   } else if (!EvangelineStrcasecmp(buf, botnetnick))
1469     dprintf(idx, "Sorry, can't use my name for a nick.\n");
1470   else {
1471     strcpy(dcc[idx].nick, buf);
1472     if (make_userfile)
1473       userlist = adduser(userlist,
1474                  buf, "-telnet!*@*", "-", sanity_check(default_flags |
1475                  USER_PARTY | USER_MASTER | USER_OWNER));
1476     else {
1477       p = strchr(dcc[idx].host, '@');
1478       if (p) {
1479         q = p;
1480         *q = 0;
1481         p++;
1482         r = strchr(p, '.');
1483         if (!r)
1484           simple_sprintf(work, "-telnet!%s@%s", dcc[idx].host, p);
1485         else
1486           simple_sprintf(work, "-telnet!%s@*%s", dcc[idx].host, r);
1487         *q = '@';
1488       } else
1489         simple_sprintf(work, "-telnet!*@*%s", dcc[idx].host);
1490       userlist = adduser(userlist, buf, work, "-",
1491                          sanity_check(USER_PARTY | default_flags));
1492     }
1493     reaffirm_owners();
1494     dcc[idx].status = STAT_ECHO | STAT_TELNET;
1495     dcc[idx].type = &DCC_CHAT;
1496     dcc[idx].user = get_user_by_handle(userlist, buf);
1497     check_dcc_attrs(dcc[idx].user, USER_PARTY | default_flags);
1498     dcc[idx].type = &DCC_TELNET_PW;
1499     if (make_userfile) {
1500       dprintf(idx, "\nYOU ARE THE MASTER/OWNER ON THIS BOT NOW\n");
1501       dprintf(idx, IRC_LIMBO);
1502       putlog(LOG_MISC, "*", DCC_INSTCOMPL, buf);
1503       make_userfile = 0;
1504       write_userfile(-1, userfileCryptKey);
1505     }
1506     dprintf(idx, "\nOkay, now choose and enter a password:\n");
1507     dprintf(idx, "(Only the first 15 letters are significant.)\n");
1508   }
1509 }
1510 
dcc_telnet_pw(int idx,char * buf,int x)1511 static void dcc_telnet_pw(int idx, char *buf, int x)
1512 {
1513   char *newpass;
1514   int ok;
1515 
1516   strip_telnet(dcc[idx].sock, buf, &x);
1517   buf[16] = 0;
1518   ok = 1;
1519   if (strlen(buf) < 4) {
1520     dprintf(idx, "\nTry to use at least 4 characters in your password.\n");
1521     dprintf(idx, "Choose and enter a password:\n");
1522     return;
1523   }
1524   for (x = 0; x < strlen(buf); x++)
1525     if ((buf[x] <= 32) || (buf[x] == 127))
1526       ok = 0;
1527   if (!ok) {
1528     dprintf(idx, "\nYou can't use weird symbols in your password.\n");
1529     dprintf(idx, "Try another one please:\n");
1530     return;
1531   }
1532   putlog(LOG_MISC, "*", DCC_NEWUSER, dcc[idx].nick, dcc[idx].host,
1533          dcc[idx].port);
1534   if (notify_new[0]) {
1535     char s[121], s1[121], s2[121];
1536 
1537     sprintf(s, "Introduced to %s, %s", dcc[idx].nick, dcc[idx].host);
1538     strcpy(s1, notify_new);
1539     splitc(s2, s1, ',');
1540     while (s2[0]) {
1541       rmspace(s2);
1542       add_note(s2, botnetnick, s, -1, 0);
1543       splitc(s2, s1, ',');
1544     }
1545     rmspace(s1);
1546     add_note(s1, botnetnick, s, -1, 0);
1547   }
1548   newpass = newsplit(&buf);
1549   set_user(&USERENTRY_PASS, dcc[idx].user, newpass);
1550   dprintf(idx, "\nRemember that!  You'll need it next time you log in.\n");
1551   dprintf(idx, "You now have an account on %s...\n\n\n", botnetnick);
1552   dcc[idx].type = &DCC_CHAT;
1553   dcc[idx].u.chat->channel = -2;
1554   first_start = 1;
1555   dcc_chatter(idx);
1556 }
1557 
eof_dcc_telnet_new(int idx)1558 static void eof_dcc_telnet_new(int idx)
1559 {
1560   putlog(LOG_MISC, "*", DCC_LOSTNEWUSER, dcc[idx].host, dcc[idx].port);
1561   killsock(dcc[idx].sock);
1562   lostdcc(idx);
1563 }
1564 
eof_dcc_telnet_pw(int idx)1565 static void eof_dcc_telnet_pw(int idx)
1566 {
1567   putlog(LOG_MISC, "*", DCC_LOSTNEWUSR2, dcc[idx].nick, dcc[idx].host,
1568          dcc[idx].port);
1569   deluser(dcc[idx].nick);
1570   killsock(dcc[idx].sock);
1571   lostdcc(idx);
1572 }
1573 
tout_dcc_telnet_new(int idx)1574 static void tout_dcc_telnet_new(int idx)
1575 {
1576   dprintf(idx, "Guess you're not there.  Bye.\n");
1577   putlog(LOG_MISC, "*", DCC_TIMEOUTUSER, dcc[idx].host, dcc[idx].port);
1578   killsock(dcc[idx].sock);
1579   lostdcc(idx);
1580 }
1581 
tout_dcc_telnet_pw(int idx)1582 static void tout_dcc_telnet_pw(int idx)
1583 {
1584   dprintf(idx, "Guess you're not there.  Bye.\n");
1585   putlog(LOG_MISC, "*", DCC_TIMEOUTUSR2, dcc[idx].nick,
1586          dcc[idx].host, dcc[idx].port);
1587   killsock(dcc[idx].sock);
1588   lostdcc(idx);
1589 }
1590 
display_dcc_telnet_new(int idx,char * buf)1591 static void display_dcc_telnet_new(int idx, char *buf)
1592 {
1593   sprintf(buf, "new   waited %lus", now - dcc[idx].timeval);
1594 }
1595 
display_dcc_telnet_pw(int idx,char * buf)1596 static void display_dcc_telnet_pw(int idx, char *buf)
1597 {
1598   sprintf(buf, "newp  waited %lus", now - dcc[idx].timeval);
1599 }
1600 
1601 struct dcc_table DCC_TELNET_NEW = {
1602   "TELNET_NEW",
1603   0,
1604   eof_dcc_telnet_new,
1605   dcc_telnet_new,
1606   &password_timeout,
1607   tout_dcc_telnet_new,
1608   display_dcc_telnet_new,
1609   expmem_dcc_general,
1610   kill_dcc_general,
1611   out_dcc_general
1612 };
1613 
1614 struct dcc_table DCC_TELNET_PW = {
1615   "TELNET_PW",
1616   0,
1617   eof_dcc_telnet_pw,
1618   dcc_telnet_pw,
1619   &password_timeout,
1620   tout_dcc_telnet_pw,
1621   display_dcc_telnet_pw,
1622   expmem_dcc_general,
1623   kill_dcc_general,
1624   out_dcc_general
1625 };
1626 
call_tcl_func(char * name,int idx,char * args)1627 static int call_tcl_func(char *name, int idx, char *args)
1628 {
1629   char s[11];
1630 
1631   sprintf(s, "%d", idx);
1632   Tcl_SetVar(interp, "_n", s, 0);
1633   Tcl_SetVar(interp, "_a", args, 0);
1634   if (Tcl_VarEval(interp, name, " $_n $_a", NULL) == TCL_ERROR) {
1635     putlog(LOG_MISC, "*", DCC_TCLERROR, name, Tcl_GetStringResult(interp));
1636     return -1;
1637   }
1638   int ret;
1639   Tcl_GetIntFromObj(interp, Tcl_GetObjResult(interp), &ret);
1640   return (ret);
1641 }
1642 
dcc_script(int idx,char * buf,int len)1643 static void dcc_script(int idx, char *buf, int len)
1644 {
1645   long oldsock;
1646 
1647   strip_telnet(dcc[idx].sock, buf, &len);
1648   if (!len)
1649     return;
1650 
1651   dcc[idx].timeval = now;
1652   oldsock = dcc[idx].sock;
1653   if (call_tcl_func(dcc[idx].u.script->command, dcc[idx].sock, buf)) {
1654     void *old_other = NULL;
1655 
1656     if (dcc[idx].sock != oldsock || idx > max_dcc)
1657       return;
1658 
1659     old_other = dcc[idx].u.script->u.other;
1660     dcc[idx].type = dcc[idx].u.script->type;
1661     nfree(dcc[idx].u.script);
1662     dcc[idx].u.other = old_other;
1663     if (dcc[idx].type == &DCC_SOCKET) {
1664       killsock(dcc[idx].sock);
1665       lostdcc(idx);
1666       return;
1667     }
1668     if (dcc[idx].type == &DCC_CHAT) {
1669       if (dcc[idx].u.chat->channel >= 0) {
1670         chanout_but(-1, dcc[idx].u.chat->channel, DCC_JOIN, dcc[idx].nick);
1671         if (dcc[idx].u.chat->channel < 10000)
1672           botnet_send_join_idx(idx, -1);
1673         check_tcl_chjn(botnetnick, dcc[idx].nick, dcc[idx].u.chat->channel,
1674                        geticon(idx), dcc[idx].sock, dcc[idx].host);
1675       }
1676       check_tcl_chon(dcc[idx].nick, dcc[idx].sock);
1677     }
1678   }
1679 }
1680 
eof_dcc_script(int idx)1681 static void eof_dcc_script(int idx)
1682 {
1683   void *old;
1684   int oldflags;
1685 
1686   oldflags = dcc[idx].type->flags;
1687   dcc[idx].type->flags &= ~(DCT_VALIDIDX);
1688   call_tcl_func(dcc[idx].u.script->command, dcc[idx].sock, "");
1689   dcc[idx].type->flags = oldflags;
1690   old = dcc[idx].u.script->u.other;
1691   dcc[idx].type = dcc[idx].u.script->type;
1692   nfree(dcc[idx].u.script);
1693   dcc[idx].u.other = old;
1694   if (dcc[idx].type && dcc[idx].type->eof)
1695     dcc[idx].type->eof(idx);
1696   else {
1697     putlog(LOG_MISC, "*", DCC_DEADSOCKET, dcc[idx].sock, dcc[idx].type->name);
1698     killsock(dcc[idx].sock);
1699     lostdcc(idx);
1700   }
1701 }
1702 
display_dcc_script(int idx,char * buf)1703 static void display_dcc_script(int idx, char *buf)
1704 {
1705   sprintf(buf, "scri  %s", dcc[idx].u.script->command);
1706 }
1707 
expmem_dcc_script(void * x)1708 static int expmem_dcc_script(void *x)
1709 {
1710   register struct script_info *p = (struct script_info *) x;
1711   int tot = sizeof(struct script_info);
1712 
1713   if (p->type && p->u.other)
1714     tot += p->type->expmem(p->u.other);
1715   return tot;
1716 }
1717 
kill_dcc_script(int idx,void * x)1718 static void kill_dcc_script(int idx, void *x)
1719 {
1720   register struct script_info *p = (struct script_info *) x;
1721 
1722   if (p->type && p->u.other)
1723     p->type->kill(idx, p->u.other);
1724   nfree(p);
1725 }
1726 
out_dcc_script(int idx,char * buf,void * x)1727 static void out_dcc_script(int idx, char *buf, void *x)
1728 {
1729   register struct script_info *p = (struct script_info *) x;
1730 
1731   if (p && p->type && p->u.other)
1732     p->type->output(idx, buf, p->u.other);
1733   else
1734     tputs(dcc[idx].sock, buf, strlen(buf));
1735 }
1736 
1737 struct dcc_table DCC_SCRIPT = {
1738   "SCRIPT",
1739   DCT_VALIDIDX,
1740   eof_dcc_script,
1741   dcc_script,
1742   NULL,
1743   NULL,
1744   display_dcc_script,
1745   expmem_dcc_script,
1746   kill_dcc_script,
1747   out_dcc_script
1748 };
1749 
dcc_socket(int idx,char * buf,int len)1750 static void dcc_socket(int idx, char *buf, int len)
1751 {
1752 }
1753 
eof_dcc_socket(int idx)1754 static void eof_dcc_socket(int idx)
1755 {
1756   killsock(dcc[idx].sock);
1757   lostdcc(idx);
1758 }
1759 
display_dcc_socket(int idx,char * buf)1760 static void display_dcc_socket(int idx, char *buf)
1761 {
1762   strcpy(buf, "sock  (stranded)");
1763 }
1764 
1765 struct dcc_table DCC_SOCKET = {
1766   "SOCKET",
1767   DCT_VALIDIDX,
1768   eof_dcc_socket,
1769   dcc_socket,
1770   NULL,
1771   NULL,
1772   display_dcc_socket,
1773   NULL,
1774   NULL,
1775   NULL
1776 };
1777 
display_dcc_lost(int idx,char * buf)1778 static void display_dcc_lost(int idx, char *buf)
1779 {
1780   strcpy(buf, "lost");
1781 }
1782 
1783 struct dcc_table DCC_LOST = {
1784   "LOST",
1785   0,
1786   NULL,
1787   dcc_socket,
1788   NULL,
1789   NULL,
1790   display_dcc_lost,
1791   NULL,
1792   NULL,
1793   NULL
1794 };
1795 
dcc_identwait(int idx,char * buf,int len)1796 void dcc_identwait(int idx, char *buf, int len)
1797 {
1798 }
1799 
eof_dcc_identwait(int idx)1800 void eof_dcc_identwait(int idx)
1801 {
1802   int i;
1803 
1804   putlog(LOG_MISC, "*", DCC_LOSTCONN, dcc[idx].host, dcc[idx].port);
1805   for (i = 0; i < dcc_total; i++)
1806     if ((dcc[i].type == &DCC_IDENT) &&
1807         (dcc[i].u.ident_sock == dcc[idx].sock)) {
1808       killsock(dcc[i].sock);
1809       dcc[i].u.other = 0;
1810       lostdcc(i);
1811       break;
1812     }
1813   killsock(dcc[idx].sock);
1814   dcc[idx].u.other = 0;
1815   lostdcc(idx);
1816 }
1817 
display_dcc_identwait(int idx,char * buf)1818 static void display_dcc_identwait(int idx, char *buf)
1819 {
1820   sprintf(buf, "idtw  waited %lus", now - dcc[idx].timeval);
1821 }
1822 
1823 struct dcc_table DCC_IDENTWAIT = {
1824   "IDENTWAIT",
1825   0,
1826   eof_dcc_identwait,
1827   dcc_identwait,
1828   NULL,
1829   NULL,
1830   display_dcc_identwait,
1831   NULL,
1832   NULL,
1833   NULL
1834 };
1835 
dcc_ident(int idx,char * buf,int len)1836 void dcc_ident(int idx, char *buf, int len)
1837 {
1838   char response[512], uid[512], buf1[UHOSTLEN];
1839   int i;
1840 
1841   sscanf(buf, "%*[^:]:%[^:]:%*[^:]:%[^\n]\n", response, uid);
1842   rmspace(response);
1843   if (response[0] != 'U') {
1844     dcc[idx].timeval = now;
1845     return;
1846   }
1847   rmspace(uid);
1848   uid[20] = 0;
1849   for (i = 0; i < dcc_total; i++)
1850     if ((dcc[i].type == &DCC_IDENTWAIT) &&
1851         (dcc[i].sock == dcc[idx].u.ident_sock)) {
1852       simple_sprintf(buf1, "%s@%s", uid, dcc[idx].host);
1853       dcc_telnet_got_ident(i, buf1);
1854     }
1855   dcc[idx].u.other = 0;
1856   killsock(dcc[idx].sock);
1857   lostdcc(idx);
1858 }
1859 
eof_dcc_ident(int idx)1860 void eof_dcc_ident(int idx)
1861 {
1862   char buf[UHOSTLEN];
1863   int i;
1864 
1865   for (i = 0; i < dcc_total; i++)
1866     if ((dcc[i].type == &DCC_IDENTWAIT) &&
1867         (dcc[i].sock == dcc[idx].u.ident_sock)) {
1868       putlog(LOG_MISC, "*", DCC_EOFIDENT);
1869       simple_sprintf(buf, "telnet@%s", dcc[idx].host);
1870       dcc_telnet_got_ident(i, buf);
1871     }
1872   killsock(dcc[idx].sock);
1873   dcc[idx].u.other = 0;
1874   lostdcc(idx);
1875 }
1876 
display_dcc_ident(int idx,char * buf)1877 static void display_dcc_ident(int idx, char *buf)
1878 {
1879   sprintf(buf, "idnt  (sock %d)", dcc[idx].u.ident_sock);
1880 }
1881 
1882 struct dcc_table DCC_IDENT = {
1883   "IDENT",
1884   0,
1885   eof_dcc_ident,
1886   dcc_ident,
1887   &identtimeout,
1888   eof_dcc_ident,
1889   display_dcc_ident,
1890   NULL,
1891   NULL,
1892   NULL
1893 };
1894 
dcc_telnet_got_ident(int i,char * host)1895 static void dcc_telnet_got_ident(int i, char *host)
1896 {
1897   int idx;
1898   char x[1024];
1899 
1900   for (idx = 0; idx < dcc_total; idx++)
1901     if ((dcc[idx].type == &DCC_TELNET) &&
1902         (dcc[idx].sock == dcc[i].u.ident_sock))
1903       break;
1904   dcc[i].u.other = 0;
1905   if (dcc_total == idx) {
1906     putlog(LOG_MISC, "*", DCC_LOSTIDENT);
1907     killsock(dcc[i].sock);
1908     lostdcc(i);
1909     return;
1910   }
1911   strncpyz(dcc[i].host, host, UHOSTLEN);
1912   EvangelineSnprintf(x, sizeof x, "-telnet!%s", dcc[i].host);
1913   if (protect_telnet && !make_userfile) {
1914     struct userrec *u;
1915     int ok = 1;
1916 
1917     u = get_user_by_host(x);
1918     if (!u)
1919       ok = 0;
1920     else if (require_p && !(u->flags & USER_PARTY))
1921       ok = 0;
1922     else if (!require_p && !(u->flags & USER_OP))
1923       ok = 0;
1924     if (!ok && u && (u->flags & USER_BOT))
1925       ok = 1;
1926     if (!ok && (dcc[idx].status & LSTN_PUBLIC))
1927       ok = 1;
1928     if (!ok) {
1929       putlog(LOG_MISC, "*", DCC_NOACCESS, dcc[i].host);
1930       killsock(dcc[i].sock);
1931       lostdcc(i);
1932       return;
1933     }
1934   }
1935   if (match_ignore(x)) {
1936     killsock(dcc[i].sock);
1937     lostdcc(i);
1938     return;
1939   }
1940   if (!strcmp(dcc[idx].nick, "(script)")) {
1941     dcc[i].type = &DCC_SOCKET;
1942     dcc[i].u.other = NULL;
1943     strcpy(dcc[i].nick, "*");
1944     check_tcl_listen(dcc[idx].host, dcc[i].sock);
1945     return;
1946   }
1947   sockoptions(dcc[i].sock, EVANGELINE_OPTION_UNSET, SOCK_BUFFER);
1948 
1949   dcc[i].type = &DCC_TELNET_ID;
1950   dcc[i].u.chat = get_data_ptr(sizeof(struct chat_info));
1951   EvangelineBzero(dcc[i].u.chat, sizeof(struct chat_info));
1952 
1953   dcc[i].status = STAT_TELNET | STAT_ECHO;
1954   if (!strcmp(dcc[idx].nick, "(bots)"))
1955     dcc[i].status |= STAT_BOTONLY;
1956   if (!strcmp(dcc[idx].nick, "(users)"))
1957     dcc[i].status |= STAT_USRONLY;
1958   strncpyz(dcc[i].nick, dcc[idx].host, HANDLEN);
1959   dcc[i].timeval = now;
1960   strcpy(dcc[i].u.chat->con_chan, chanset ? chanset->dname : "*");
1961   if (!stealth_telnets)
1962     dprintf(i, "%s\n", ver);
1963   else
1964     dprintf(i, "  \n\n");
1965 }
1966