1/* vi: set sw=4 ts=4: */ 2/* 3 * Simple telnet server 4 * Bjorn Wesen, Axis Communications AB (bjornw@axis.com) 5 * 6 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * 8 * --------------------------------------------------------------------------- 9 * (C) Copyright 2000, Axis Communications AB, LUND, SWEDEN 10 **************************************************************************** 11 * 12 * The telnetd manpage says it all: 13 * 14 * Telnetd operates by allocating a pseudo-terminal device (see pty(4)) for 15 * a client, then creating a login process which has the slave side of the 16 * pseudo-terminal as stdin, stdout, and stderr. Telnetd manipulates the 17 * master side of the pseudo-terminal, implementing the telnet protocol and 18 * passing characters between the remote client and the login process. 19 * 20 * Vladimir Oleynik <dzo@simtreas.ru> 2001 21 * Set process group corrections, initial busybox port 22 */ 23//config:config TELNETD 24//config: bool "telnetd (12 kb)" 25//config: default y 26//config: select FEATURE_SYSLOG 27//config: help 28//config: A daemon for the TELNET protocol, allowing you to log onto the host 29//config: running the daemon. Please keep in mind that the TELNET protocol 30//config: sends passwords in plain text. If you can't afford the space for an 31//config: SSH daemon and you trust your network, you may say 'y' here. As a 32//config: more secure alternative, you should seriously consider installing the 33//config: very small Dropbear SSH daemon instead: 34//config: http://matt.ucc.asn.au/dropbear/dropbear.html 35//config: 36//config: Note that for busybox telnetd to work you need several things: 37//config: First of all, your kernel needs: 38//config: CONFIG_UNIX98_PTYS=y 39//config: 40//config: Next, you need a /dev/pts directory on your root filesystem: 41//config: 42//config: $ ls -ld /dev/pts 43//config: drwxr-xr-x 2 root root 0 Sep 23 13:21 /dev/pts/ 44//config: 45//config: Next you need the pseudo terminal master multiplexer /dev/ptmx: 46//config: 47//config: $ ls -la /dev/ptmx 48//config: crw-rw-rw- 1 root tty 5, 2 Sep 23 13:55 /dev/ptmx 49//config: 50//config: Any /dev/ttyp[0-9]* files you may have can be removed. 51//config: Next, you need to mount the devpts filesystem on /dev/pts using: 52//config: 53//config: mount -t devpts devpts /dev/pts 54//config: 55//config: You need to be sure that busybox has LOGIN and 56//config: FEATURE_SUID enabled. And finally, you should make 57//config: certain that busybox has been installed setuid root: 58//config: 59//config: chown root.root /bin/busybox 60//config: chmod 4755 /bin/busybox 61//config: 62//config: with all that done, telnetd _should_ work.... 63//config: 64//config:config FEATURE_TELNETD_STANDALONE 65//config: bool "Support standalone telnetd (not inetd only)" 66//config: default y 67//config: depends on TELNETD 68//config: help 69//config: Selecting this will make telnetd able to run standalone. 70//config: 71//config:config FEATURE_TELNETD_INETD_WAIT 72//config: bool "Support -w SEC option (inetd wait mode)" 73//config: default y 74//config: depends on FEATURE_TELNETD_STANDALONE 75//config: help 76//config: This option allows you to run telnetd in "inet wait" mode. 77//config: Example inetd.conf line (note "wait", not usual "nowait"): 78//config: 79//config: telnet stream tcp wait root /bin/telnetd telnetd -w10 80//config: 81//config: In this example, inetd passes _listening_ socket_ as fd 0 82//config: to telnetd when connection appears. 83//config: telnetd will wait for connections until all existing 84//config: connections are closed, and no new connections 85//config: appear during 10 seconds. Then it exits, and inetd continues 86//config: to listen for new connections. 87//config: 88//config: This option is rarely used. "tcp nowait" is much more usual 89//config: way of running tcp services, including telnetd. 90//config: You most probably want to say N here. 91 92//applet:IF_TELNETD(APPLET(telnetd, BB_DIR_USR_SBIN, BB_SUID_DROP)) 93 94//kbuild:lib-$(CONFIG_TELNETD) += telnetd.o 95 96//usage:#define telnetd_trivial_usage 97//usage: "[OPTIONS]" 98//usage:#define telnetd_full_usage "\n\n" 99//usage: "Handle incoming telnet connections" 100//usage: IF_NOT_FEATURE_TELNETD_STANDALONE(" via inetd") "\n" 101//usage: "\n -l LOGIN Exec LOGIN on connect" 102//usage: "\n -f ISSUE_FILE Display ISSUE_FILE instead of /etc/issue" 103//usage: "\n -K Close connection as soon as login exits" 104//usage: "\n (normally wait until all programs close slave pty)" 105//usage: IF_FEATURE_TELNETD_STANDALONE( 106//usage: "\n -p PORT Port to listen on" 107//usage: "\n -b ADDR[:PORT] Address to bind to" 108//usage: "\n -F Run in foreground" 109//usage: "\n -i Inetd mode" 110//usage: IF_FEATURE_TELNETD_INETD_WAIT( 111//usage: "\n -w SEC Inetd 'wait' mode, linger time SEC" 112//usage: "\n -S Log to syslog (implied by -i or without -F and -w)" 113//usage: ) 114//usage: ) 115 116#define DEBUG 0 117 118#include "libbb.h" 119#include "common_bufsiz.h" 120#include <syslog.h> 121 122#if DEBUG 123# define TELCMDS 124# define TELOPTS 125#endif 126#include <arpa/telnet.h> 127 128 129struct tsession { 130 struct tsession *next; 131 pid_t shell_pid; 132 int sockfd_read; 133 int sockfd_write; 134 int ptyfd; 135 smallint buffered_IAC_for_pty; 136 137 /* two circular buffers */ 138 /*char *buf1, *buf2;*/ 139/*#define TS_BUF1(ts) ts->buf1*/ 140/*#define TS_BUF2(ts) TS_BUF2(ts)*/ 141#define TS_BUF1(ts) ((unsigned char*)(ts + 1)) 142#define TS_BUF2(ts) (((unsigned char*)(ts + 1)) + BUFSIZE) 143 int rdidx1, wridx1, size1; 144 int rdidx2, wridx2, size2; 145}; 146 147/* Two buffers are directly after tsession in malloced memory. 148 * Make whole thing fit in 4k */ 149enum { BUFSIZE = (4 * 1024 - sizeof(struct tsession)) / 2 }; 150 151 152/* Globals */ 153struct globals { 154 struct tsession *sessions; 155 const char *loginpath; 156 const char *issuefile; 157 int maxfd; 158} FIX_ALIASING; 159#define G (*(struct globals*)bb_common_bufsiz1) 160#define INIT_G() do { \ 161 setup_common_bufsiz(); \ 162 G.loginpath = "/bin/login"; \ 163 G.issuefile = "/etc/issue.net"; \ 164} while (0) 165 166 167/* Write some buf1 data to pty, processing IACs. 168 * Update wridx1 and size1. Return < 0 on error. 169 * Buggy if IAC is present but incomplete: skips them. 170 */ 171static ssize_t 172safe_write_to_pty_decode_iac(struct tsession *ts) 173{ 174 unsigned wr; 175 ssize_t rc; 176 unsigned char *buf; 177 unsigned char *found; 178 179 buf = TS_BUF1(ts) + ts->wridx1; 180 wr = MIN(BUFSIZE - ts->wridx1, ts->size1); 181 /* wr is at least 1 here */ 182 183 if (ts->buffered_IAC_for_pty) { 184 /* Last time we stopped on a "dangling" IAC byte. 185 * We removed it from the buffer back then. 186 * Now pretend it's still there, and jump to IAC processing. 187 */ 188 ts->buffered_IAC_for_pty = 0; 189 wr++; 190 ts->size1++; 191 buf--; /* Yes, this can point before the buffer. It's ok */ 192 ts->wridx1--; 193 goto handle_iac; 194 } 195 196 found = memchr(buf, IAC, wr); 197 if (found != buf) { 198 /* There is a "prefix" of non-IAC chars. 199 * Write only them, and return. 200 */ 201 if (found) 202 wr = found - buf; 203 204 /* We map \r\n ==> \r for pragmatic reasons: 205 * many client implementations send \r\n when 206 * the user hits the CarriageReturn key. 207 * See RFC 1123 3.3.1 Telnet End-of-Line Convention. 208 */ 209 rc = wr; 210 found = memchr(buf, '\r', wr); 211 if (found) 212 rc = found - buf + 1; 213 rc = safe_write(ts->ptyfd, buf, rc); 214 if (rc <= 0) 215 return rc; 216 if (rc < wr /* don't look past available data */ 217 && buf[rc-1] == '\r' /* need this: imagine that write was _short_ */ 218 && (buf[rc] == '\n' || buf[rc] == '\0') 219 ) { 220 rc++; 221 } 222 goto update_and_return; 223 } 224 225 /* buf starts with IAC char. Process that sequence. 226 * Example: we get this from our own (bbox) telnet client: 227 * read(5, "\377\374\1""\377\373\37""\377\372\37\0\262\0@\377\360""\377\375\1""\377\375\3"): 228 * IAC WONT ECHO, IAC WILL NAWS, IAC SB NAWS <cols> <rows> IAC SE, IAC DO SGA 229 * Another example (telnet-0.17 from old-netkit): 230 * read(4, "\377\375\3""\377\373\30""\377\373\37""\377\373 ""\377\373!""\377\373\"""\377\373'" 231 * "\377\375\5""\377\373#""\377\374\1""\377\372\37\0\257\0I\377\360""\377\375\1"): 232 * IAC DO SGA, IAC WILL TTYPE, IAC WILL NAWS, IAC WILL TSPEED, IAC WILL LFLOW, IAC WILL LINEMODE, IAC WILL NEW_ENVIRON, 233 * IAC DO STATUS, IAC WILL XDISPLOC, IAC WONT ECHO, IAC SB NAWS <cols> <rows> IAC SE, IAC DO ECHO 234 */ 235 if (wr <= 1) { 236 /* Only the single IAC byte is in the buffer, eat it 237 * and set a flag "process the rest of the sequence 238 * next time we are here". 239 */ 240 //bb_error_msg("dangling IAC!"); 241 ts->buffered_IAC_for_pty = 1; 242 rc = 1; 243 goto update_and_return; 244 } 245 246 handle_iac: 247 /* 2-byte commands (240..250 and 255): 248 * IAC IAC (255) Literal 255. Supported. 249 * IAC SE (240) End of subnegotiation. Treated as NOP. 250 * IAC NOP (241) NOP. Supported. 251 * IAC BRK (243) Break. Like serial line break. TODO via tcsendbreak()? 252 * IAC AYT (246) Are you there. 253 * These don't look useful: 254 * IAC DM (242) Data mark. What is this? 255 * IAC IP (244) Suspend, interrupt or abort the process. (Ancient cousin of ^C). 256 * IAC AO (245) Abort output. "You can continue running, but do not send me the output". 257 * IAC EC (247) Erase character. The receiver should delete the last received char. 258 * IAC EL (248) Erase line. The receiver should delete everything up tp last newline. 259 * IAC GA (249) Go ahead. For half-duplex lines: "now you talk". 260 * Implemented only as part of NAWS: 261 * IAC SB (250) Subnegotiation of an option follows. 262 */ 263 if (buf[1] == IAC) { 264 /* Literal 255 (emacs M-DEL) */ 265 //bb_error_msg("255!"); 266 rc = safe_write(ts->ptyfd, &buf[1], 1); 267 /* 268 * If we went through buffered_IAC_for_pty==1 path, 269 * bailing out on error like below messes up the buffer. 270 * EAGAIN is highly unlikely here, other errors will be 271 * repeated on next write, let's just skip error check. 272 */ 273#if 0 274 if (rc <= 0) 275 return rc; 276#endif 277 rc = 2; 278 goto update_and_return; 279 } 280 if (buf[1] == AYT) { 281 if (ts->size2 == 0) { /* if nothing buffered yet... */ 282 /* Send back evidence that AYT was seen */ 283 unsigned char *buf2 = TS_BUF2(ts); 284 buf2[0] = IAC; 285 buf2[1] = NOP; 286 ts->wridx2 = 0; 287 ts->rdidx2 = ts->size2 = 2; 288 } 289 rc = 2; 290 goto update_and_return; 291 } 292 if (buf[1] >= 240 && buf[1] <= 249) { 293 /* NOP (241). Ignore (putty keepalive, etc) */ 294 /* All other 2-byte commands also treated as NOPs here */ 295 rc = 2; 296 goto update_and_return; 297 } 298 299 if (wr <= 2) { 300/* BUG: only 2 bytes of the IAC is in the buffer, we just eat them. 301 * This is not a practical problem since >2 byte IACs are seen only 302 * in initial negotiation, when buffer is empty 303 */ 304 rc = 2; 305 goto update_and_return; 306 } 307 308 if (buf[1] == SB) { 309 if (buf[2] == TELOPT_NAWS) { 310 /* IAC SB, TELOPT_NAWS, 4-byte, IAC SE */ 311 struct winsize ws; 312 if (wr <= 6) { 313/* BUG: incomplete, can't process */ 314 rc = wr; 315 goto update_and_return; 316 } 317 memset(&ws, 0, sizeof(ws)); /* pixel sizes are set to 0 */ 318 ws.ws_col = (buf[3] << 8) | buf[4]; 319 ws.ws_row = (buf[5] << 8) | buf[6]; 320 ioctl(ts->ptyfd, TIOCSWINSZ, (char *)&ws); 321 rc = 7; 322 /* trailing IAC SE will be eaten separately, as 2-byte NOP */ 323 goto update_and_return; 324 } 325 /* else: other subnegs not supported yet */ 326 } 327 328 /* Assume it is a 3-byte WILL/WONT/DO/DONT 251..254 command and skip it */ 329#if DEBUG 330 fprintf(stderr, "Ignoring IAC %s,%s\n", 331 TELCMD(buf[1]), TELOPT(buf[2])); 332#endif 333 rc = 3; 334 335 update_and_return: 336 ts->wridx1 += rc; 337 if (ts->wridx1 >= BUFSIZE) /* actually == BUFSIZE */ 338 ts->wridx1 = 0; 339 ts->size1 -= rc; 340 /* 341 * Hack. We cannot process IACs which wrap around buffer's end. 342 * Since properly fixing it requires writing bigger code, 343 * we rely instead on this code making it virtually impossible 344 * to have wrapped IAC (people don't type at 2k/second). 345 * It also allows for bigger reads in common case. 346 */ 347 if (ts->size1 == 0) { /* very typical */ 348 //bb_error_msg("zero size1"); 349 ts->rdidx1 = 0; 350 ts->wridx1 = 0; 351 return rc; 352 } 353 wr = ts->wridx1; 354 if (wr != 0 && wr < ts->rdidx1) { 355 /* Buffer is not wrapped yet. 356 * We can easily move it to the beginning. 357 */ 358 //bb_error_msg("moved %d", wr); 359 memmove(TS_BUF1(ts), TS_BUF1(ts) + wr, ts->size1); 360 ts->rdidx1 -= wr; 361 ts->wridx1 = 0; 362 } 363 return rc; 364} 365 366/* 367 * Converting single IAC into double on output 368 */ 369static size_t safe_write_double_iac(int fd, const char *buf, size_t count) 370{ 371 const char *IACptr; 372 size_t wr, rc, total; 373 374 total = 0; 375 while (1) { 376 if (count == 0) 377 return total; 378 if (*buf == (char)IAC) { 379 static const char IACIAC[] ALIGN1 = { IAC, IAC }; 380 rc = safe_write(fd, IACIAC, 2); 381/* BUG: if partial write was only 1 byte long, we end up emitting just one IAC */ 382 if (rc != 2) 383 break; 384 buf++; 385 total++; 386 count--; 387 continue; 388 } 389 /* count != 0, *buf != IAC */ 390 IACptr = memchr(buf, IAC, count); 391 wr = count; 392 if (IACptr) 393 wr = IACptr - buf; 394 rc = safe_write(fd, buf, wr); 395 if (rc != wr) 396 break; 397 buf += rc; 398 total += rc; 399 count -= rc; 400 } 401 /* here: rc - result of last short write */ 402 if ((ssize_t)rc < 0) { /* error? */ 403 if (total == 0) 404 return rc; 405 rc = 0; 406 } 407 return total + rc; 408} 409 410/* Must match getopt32 string */ 411enum { 412 OPT_WATCHCHILD = (1 << 2), /* -K */ 413 OPT_INETD = (1 << 3) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -i */ 414 OPT_PORT = (1 << 4) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -p PORT */ 415 OPT_FOREGROUND = (1 << 6) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -F */ 416 OPT_SYSLOG = (1 << 7) * ENABLE_FEATURE_TELNETD_INETD_WAIT, /* -S */ 417 OPT_WAIT = (1 << 8) * ENABLE_FEATURE_TELNETD_INETD_WAIT, /* -w SEC */ 418}; 419 420static struct tsession * 421make_new_session( 422 IF_FEATURE_TELNETD_STANDALONE(int sock) 423 IF_NOT_FEATURE_TELNETD_STANDALONE(void) 424) { 425#if !ENABLE_FEATURE_TELNETD_STANDALONE 426 enum { sock = 0 }; 427#endif 428 const char *login_argv[2]; 429 struct termios termbuf; 430 int fd, pid; 431 char tty_name[GETPTY_BUFSIZE]; 432 struct tsession *ts = xzalloc(sizeof(struct tsession) + BUFSIZE * 2); 433 434 /*ts->buf1 = (char *)(ts + 1);*/ 435 /*ts->buf2 = ts->buf1 + BUFSIZE;*/ 436 437 /* Got a new connection, set up a tty */ 438 fd = xgetpty(tty_name); 439 if (fd > G.maxfd) 440 G.maxfd = fd; 441 ts->ptyfd = fd; 442 ndelay_on(fd); 443 close_on_exec_on(fd); 444 445 /* SO_KEEPALIVE by popular demand */ 446 setsockopt_keepalive(sock); 447#if ENABLE_FEATURE_TELNETD_STANDALONE 448 ts->sockfd_read = sock; 449 ndelay_on(sock); 450 if (sock == 0) { /* We are called with fd 0 - we are in inetd mode */ 451 sock++; /* so use fd 1 for output */ 452 ndelay_on(sock); 453 } 454 ts->sockfd_write = sock; 455 if (sock > G.maxfd) 456 G.maxfd = sock; 457#else 458 /* ts->sockfd_read = 0; - done by xzalloc */ 459 ts->sockfd_write = 1; 460 ndelay_on(0); 461 ndelay_on(1); 462#endif 463 464 /* Make the telnet client understand we will echo characters so it 465 * should not do it locally. We don't tell the client to run linemode, 466 * because we want to handle line editing and tab completion and other 467 * stuff that requires char-by-char support. */ 468 { 469 static const char iacs_to_send[] ALIGN1 = { 470 IAC, DO, TELOPT_ECHO, 471 IAC, DO, TELOPT_NAWS, 472 /* This requires telnetd.ctrlSQ.patch (incomplete) */ 473 /*IAC, DO, TELOPT_LFLOW,*/ 474 IAC, WILL, TELOPT_ECHO, 475 IAC, WILL, TELOPT_SGA 476 }; 477 /* This confuses safe_write_double_iac(), it will try to duplicate 478 * each IAC... */ 479 //memcpy(TS_BUF2(ts), iacs_to_send, sizeof(iacs_to_send)); 480 //ts->rdidx2 = sizeof(iacs_to_send); 481 //ts->size2 = sizeof(iacs_to_send); 482 /* So just stuff it into TCP stream! (no error check...) */ 483#if ENABLE_FEATURE_TELNETD_STANDALONE 484 safe_write(sock, iacs_to_send, sizeof(iacs_to_send)); 485#else 486 safe_write(1, iacs_to_send, sizeof(iacs_to_send)); 487#endif 488 /*ts->rdidx2 = 0; - xzalloc did it */ 489 /*ts->size2 = 0;*/ 490 } 491 492 fflush_all(); 493 pid = vfork(); /* NOMMU-friendly */ 494 if (pid < 0) { 495 free(ts); 496 close(fd); 497 /* sock will be closed by caller */ 498 bb_perror_msg("vfork"); 499 return NULL; 500 } 501 if (pid > 0) { 502 /* Parent */ 503 ts->shell_pid = pid; 504 return ts; 505 } 506 507 /* Child */ 508 /* Careful - we are after vfork! */ 509 510 /* Restore default signal handling ASAP */ 511 bb_signals((1 << SIGCHLD) + (1 << SIGPIPE), SIG_DFL); 512 513 pid = getpid(); 514 515 if (ENABLE_FEATURE_UTMP) { 516 len_and_sockaddr *lsa = get_peer_lsa(sock); 517 char *hostname = NULL; 518 if (lsa) { 519 hostname = xmalloc_sockaddr2dotted(&lsa->u.sa); 520 free(lsa); 521 } 522 write_new_utmp(pid, LOGIN_PROCESS, tty_name, /*username:*/ "LOGIN", hostname); 523 free(hostname); 524 } 525 526 /* Make new session and process group */ 527 setsid(); 528 529 /* Open the child's side of the tty */ 530 /* NB: setsid() disconnects from any previous ctty's. Therefore 531 * we must open child's side of the tty AFTER setsid! */ 532 close(0); 533 xopen(tty_name, O_RDWR); /* becomes our ctty */ 534 xdup2(0, 1); 535 xdup2(0, 2); 536 tcsetpgrp(0, pid); /* switch this tty's process group to us */ 537 538 /* The pseudo-terminal allocated to the client is configured to operate 539 * in cooked mode, and with XTABS CRMOD enabled (see tty(4)) */ 540 tcgetattr(0, &termbuf); 541 termbuf.c_lflag |= ECHO; /* if we use readline we dont want this */ 542 termbuf.c_oflag |= ONLCR | XTABS; 543 termbuf.c_iflag |= ICRNL; 544 termbuf.c_iflag &= ~IXOFF; 545 /*termbuf.c_lflag &= ~ICANON;*/ 546 tcsetattr_stdin_TCSANOW(&termbuf); 547 548 /* Uses FILE-based I/O to stdout, but does fflush_all(), 549 * so should be safe with vfork. 550 * I fear, though, that some users will have ridiculously big 551 * issue files, and they may block writing to fd 1, 552 * (parent is supposed to read it, but parent waits 553 * for vforked child to exec!) */ 554 print_login_issue(G.issuefile, tty_name); 555 556 /* Exec shell / login / whatever */ 557 login_argv[0] = G.loginpath; 558 login_argv[1] = NULL; 559 /* exec busybox applet (if PREFER_APPLETS=y), if that fails, 560 * exec external program. 561 * NB: sock is either 0 or has CLOEXEC set on it. 562 * fd has CLOEXEC set on it too. These two fds will be closed here. 563 */ 564 BB_EXECVP(G.loginpath, (char **)login_argv); 565 /* _exit is safer with vfork, and we shouldn't send message 566 * to remote clients anyway */ 567 _exit(EXIT_FAILURE); /*bb_perror_msg_and_die("execv %s", G.loginpath);*/ 568} 569 570#if ENABLE_FEATURE_TELNETD_STANDALONE 571 572static void 573free_session(struct tsession *ts) 574{ 575 struct tsession *t; 576 577 if (option_mask32 & OPT_INETD) 578 exit(EXIT_SUCCESS); 579 580 /* Unlink this telnet session from the session list */ 581 t = G.sessions; 582 if (t == ts) 583 G.sessions = ts->next; 584 else { 585 while (t->next != ts) 586 t = t->next; 587 t->next = ts->next; 588 } 589 590#if 0 591 /* It was said that "normal" telnetd just closes ptyfd, 592 * doesn't send SIGKILL. When we close ptyfd, 593 * kernel sends SIGHUP to processes having slave side opened. */ 594 kill(ts->shell_pid, SIGKILL); 595 waitpid(ts->shell_pid, NULL, 0); 596#endif 597 close(ts->ptyfd); 598 close(ts->sockfd_read); 599 /* We do not need to close(ts->sockfd_write), it's the same 600 * as sockfd_read unless we are in inetd mode. But in inetd mode 601 * we do not reach this */ 602 free(ts); 603 604 /* Scan all sessions and find new maxfd */ 605 G.maxfd = 0; 606 ts = G.sessions; 607 while (ts) { 608 if (G.maxfd < ts->ptyfd) 609 G.maxfd = ts->ptyfd; 610 if (G.maxfd < ts->sockfd_read) 611 G.maxfd = ts->sockfd_read; 612#if 0 613 /* Again, sockfd_write == sockfd_read here */ 614 if (G.maxfd < ts->sockfd_write) 615 G.maxfd = ts->sockfd_write; 616#endif 617 ts = ts->next; 618 } 619} 620 621#else /* !FEATURE_TELNETD_STANDALONE */ 622 623/* Used in main() only, thus "return 0" actually is exit(EXIT_SUCCESS). */ 624#define free_session(ts) return 0 625 626#endif 627 628static void handle_sigchld(int sig UNUSED_PARAM) 629{ 630 pid_t pid; 631 struct tsession *ts; 632 int save_errno = errno; 633 634 /* Looping: more than one child may have exited */ 635 while (1) { 636 pid = wait_any_nohang(NULL); 637 if (pid <= 0) 638 break; 639 ts = G.sessions; 640 while (ts) { 641 if (ts->shell_pid == pid) { 642 ts->shell_pid = -1; 643 update_utmp_DEAD_PROCESS(pid); 644 break; 645 } 646 ts = ts->next; 647 } 648 } 649 650 errno = save_errno; 651} 652 653int telnetd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 654int telnetd_main(int argc UNUSED_PARAM, char **argv) 655{ 656 fd_set rdfdset, wrfdset; 657 unsigned opt; 658 int count; 659 struct tsession *ts; 660#if ENABLE_FEATURE_TELNETD_STANDALONE 661#define IS_INETD (opt & OPT_INETD) 662 int master_fd = master_fd; /* for compiler */ 663 int sec_linger = sec_linger; 664 char *opt_bindaddr = NULL; 665 char *opt_portnbr; 666#else 667 enum { 668 IS_INETD = 1, 669 master_fd = -1, 670 }; 671#endif 672 INIT_G(); 673 674 /* Even if !STANDALONE, we accept (and ignore) -i, thus people 675 * don't need to guess whether it's ok to pass -i to us */ 676 opt = getopt32(argv, "^" 677 "f:l:Ki" 678 IF_FEATURE_TELNETD_STANDALONE("p:b:F") 679 IF_FEATURE_TELNETD_INETD_WAIT("Sw:+") /* -w NUM */ 680 "\0" 681 /* -w implies -F. -w and -i don't mix */ 682 IF_FEATURE_TELNETD_INETD_WAIT("wF:i--w:w--i"), 683 &G.issuefile, &G.loginpath 684 IF_FEATURE_TELNETD_STANDALONE(, &opt_portnbr, &opt_bindaddr) 685 IF_FEATURE_TELNETD_INETD_WAIT(, &sec_linger) 686 ); 687 if (!IS_INETD /*&& !re_execed*/) { 688 /* inform that we start in standalone mode? 689 * May be useful when people forget to give -i */ 690 /*bb_error_msg("listening for connections");*/ 691 if (!(opt & OPT_FOREGROUND)) { 692 /* DAEMON_CHDIR_ROOT was giving inconsistent 693 * behavior with/without -F, -i */ 694 bb_daemonize_or_rexec(0 /*was DAEMON_CHDIR_ROOT*/, argv); 695 } 696 } 697 /* Redirect log to syslog early, if needed */ 698 if (IS_INETD || (opt & OPT_SYSLOG) || !(opt & OPT_FOREGROUND)) { 699 openlog(applet_name, LOG_PID, LOG_DAEMON); 700 logmode = LOGMODE_SYSLOG; 701 } 702#if ENABLE_FEATURE_TELNETD_STANDALONE 703 if (IS_INETD) { 704 G.sessions = make_new_session(0); 705 if (!G.sessions) /* pty opening or vfork problem, exit */ 706 return 1; /* make_new_session printed error message */ 707 } else { 708 master_fd = 0; 709 if (!(opt & OPT_WAIT)) { 710 unsigned portnbr = 23; 711 if (opt & OPT_PORT) 712 portnbr = xatou16(opt_portnbr); 713 master_fd = create_and_bind_stream_or_die(opt_bindaddr, portnbr); 714 xlisten(master_fd, 1); 715 } 716 close_on_exec_on(master_fd); 717 } 718#else 719 G.sessions = make_new_session(); 720 if (!G.sessions) /* pty opening or vfork problem, exit */ 721 return 1; /* make_new_session printed error message */ 722#endif 723 724 /* We don't want to die if just one session is broken */ 725 signal(SIGPIPE, SIG_IGN); 726 727 if (opt & OPT_WATCHCHILD) 728 signal(SIGCHLD, handle_sigchld); 729 else /* prevent dead children from becoming zombies */ 730 signal(SIGCHLD, SIG_IGN); 731 732/* 733 This is how the buffers are used. The arrows indicate data flow. 734 735 +-------+ wridx1++ +------+ rdidx1++ +----------+ 736 | | <-------------- | buf1 | <-------------- | | 737 | | size1-- +------+ size1++ | | 738 | pty | | socket | 739 | | rdidx2++ +------+ wridx2++ | | 740 | | --------------> | buf2 | --------------> | | 741 +-------+ size2++ +------+ size2-- +----------+ 742 743 size1: "how many bytes are buffered for pty between rdidx1 and wridx1?" 744 size2: "how many bytes are buffered for socket between rdidx2 and wridx2?" 745 746 Each session has got two buffers. Buffers are circular. If sizeN == 0, 747 buffer is empty. If sizeN == BUFSIZE, buffer is full. In both these cases 748 rdidxN == wridxN. 749*/ 750 again: 751 FD_ZERO(&rdfdset); 752 FD_ZERO(&wrfdset); 753 754 /* Select on the master socket, all telnet sockets and their 755 * ptys if there is room in their session buffers. 756 * NB: scalability problem: we recalculate entire bitmap 757 * before each select. Can be a problem with 500+ connections. */ 758 ts = G.sessions; 759 while (ts) { 760 struct tsession *next = ts->next; /* in case we free ts */ 761 if (ts->shell_pid == -1) { 762 /* Child died and we detected that */ 763 free_session(ts); 764 } else { 765 if (ts->size1 > 0) /* can write to pty */ 766 FD_SET(ts->ptyfd, &wrfdset); 767 if (ts->size1 < BUFSIZE) /* can read from socket */ 768 FD_SET(ts->sockfd_read, &rdfdset); 769 if (ts->size2 > 0) /* can write to socket */ 770 FD_SET(ts->sockfd_write, &wrfdset); 771 if (ts->size2 < BUFSIZE) /* can read from pty */ 772 FD_SET(ts->ptyfd, &rdfdset); 773 } 774 ts = next; 775 } 776 if (!IS_INETD) { 777 FD_SET(master_fd, &rdfdset); 778 /* This is needed because free_session() does not 779 * take master_fd into account when it finds new 780 * maxfd among remaining fd's */ 781 if (master_fd > G.maxfd) 782 G.maxfd = master_fd; 783 } 784 785 { 786 struct timeval *tv_ptr = NULL; 787#if ENABLE_FEATURE_TELNETD_INETD_WAIT 788 struct timeval tv; 789 if ((opt & OPT_WAIT) && !G.sessions) { 790 tv.tv_sec = sec_linger; 791 tv.tv_usec = 0; 792 tv_ptr = &tv; 793 } 794#endif 795 count = select(G.maxfd + 1, &rdfdset, &wrfdset, NULL, tv_ptr); 796 } 797 if (count == 0) /* "telnetd -w SEC" timed out */ 798 return 0; 799 if (count < 0) 800 goto again; /* EINTR or ENOMEM */ 801 802#if ENABLE_FEATURE_TELNETD_STANDALONE 803 /* Check for and accept new sessions */ 804 if (!IS_INETD && FD_ISSET(master_fd, &rdfdset)) { 805 int fd; 806 struct tsession *new_ts; 807 808 fd = accept(master_fd, NULL, NULL); 809 if (fd < 0) 810 goto again; 811 close_on_exec_on(fd); 812 813 /* Create a new session and link it into active list */ 814 new_ts = make_new_session(fd); 815 if (new_ts) { 816 new_ts->next = G.sessions; 817 G.sessions = new_ts; 818 } else { 819 close(fd); 820 } 821 } 822#endif 823 824 /* Then check for data tunneling */ 825 ts = G.sessions; 826 while (ts) { /* For all sessions... */ 827 struct tsession *next = ts->next; /* in case we free ts */ 828 829 if (/*ts->size1 &&*/ FD_ISSET(ts->ptyfd, &wrfdset)) { 830 /* Write to pty from buffer 1 */ 831 count = safe_write_to_pty_decode_iac(ts); 832 if (count < 0) { 833 if (errno == EAGAIN) 834 goto skip1; 835 goto kill_session; 836 } 837 } 838 skip1: 839 if (/*ts->size2 &&*/ FD_ISSET(ts->sockfd_write, &wrfdset)) { 840 /* Write to socket from buffer 2 */ 841 count = MIN(BUFSIZE - ts->wridx2, ts->size2); 842 count = safe_write_double_iac(ts->sockfd_write, (void*)(TS_BUF2(ts) + ts->wridx2), count); 843 if (count < 0) { 844 if (errno == EAGAIN) 845 goto skip2; 846 goto kill_session; 847 } 848 ts->wridx2 += count; 849 if (ts->wridx2 >= BUFSIZE) /* actually == BUFSIZE */ 850 ts->wridx2 = 0; 851 ts->size2 -= count; 852 if (ts->size2 == 0) { 853 ts->rdidx2 = 0; 854 ts->wridx2 = 0; 855 } 856 } 857 skip2: 858 859 if (/*ts->size1 < BUFSIZE &&*/ FD_ISSET(ts->sockfd_read, &rdfdset)) { 860 /* Read from socket to buffer 1 */ 861 count = MIN(BUFSIZE - ts->rdidx1, BUFSIZE - ts->size1); 862 count = safe_read(ts->sockfd_read, TS_BUF1(ts) + ts->rdidx1, count); 863 if (count <= 0) { 864 if (count < 0 && errno == EAGAIN) 865 goto skip3; 866 goto kill_session; 867 } 868 /* Ignore trailing NUL if it is there */ 869 if (!TS_BUF1(ts)[ts->rdidx1 + count - 1]) { 870 --count; 871 } 872 ts->size1 += count; 873 ts->rdidx1 += count; 874 if (ts->rdidx1 >= BUFSIZE) /* actually == BUFSIZE */ 875 ts->rdidx1 = 0; 876 } 877 skip3: 878 if (/*ts->size2 < BUFSIZE &&*/ FD_ISSET(ts->ptyfd, &rdfdset)) { 879 /* Read from pty to buffer 2 */ 880 int eio = 0; 881 read_pty: 882 count = MIN(BUFSIZE - ts->rdidx2, BUFSIZE - ts->size2); 883 count = safe_read(ts->ptyfd, TS_BUF2(ts) + ts->rdidx2, count); 884 if (count <= 0) { 885 if (count < 0) { 886 if (errno == EAGAIN) 887 goto skip4; 888 /* login process might call vhangup(), 889 * which causes intermittent EIOs on read above 890 * (observed on kernel 4.12.0). Try up to 10 ms. 891 */ 892 if (errno == EIO && eio < 10) { 893 eio++; 894 //bb_error_msg("EIO pty %u", eio); 895 usleep(1000); 896 goto read_pty; 897 } 898 } 899 goto kill_session; 900 } 901 ts->size2 += count; 902 ts->rdidx2 += count; 903 if (ts->rdidx2 >= BUFSIZE) /* actually == BUFSIZE */ 904 ts->rdidx2 = 0; 905 } 906 skip4: 907 ts = next; 908 continue; 909 kill_session: 910 if (ts->shell_pid > 0) 911 update_utmp_DEAD_PROCESS(ts->shell_pid); 912 free_session(ts); 913 ts = next; 914 } 915 916 goto again; 917} 918