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