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" 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. Send back evidence that AYT was seen. TODO (send NOP back)? 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] >= 240 && buf[1] <= 249) { 281 /* NOP (241). Ignore (putty keepalive, etc) */ 282 /* All other 2-byte commands also treated as NOPs here */ 283 rc = 2; 284 goto update_and_return; 285 } 286 287 if (wr <= 2) { 288/* BUG: only 2 bytes of the IAC is in the buffer, we just eat them. 289 * This is not a practical problem since >2 byte IACs are seen only 290 * in initial negotiation, when buffer is empty 291 */ 292 rc = 2; 293 goto update_and_return; 294 } 295 296 if (buf[1] == SB) { 297 if (buf[2] == TELOPT_NAWS) { 298 /* IAC SB, TELOPT_NAWS, 4-byte, IAC SE */ 299 struct winsize ws; 300 if (wr <= 6) { 301/* BUG: incomplete, can't process */ 302 rc = wr; 303 goto update_and_return; 304 } 305 memset(&ws, 0, sizeof(ws)); /* pixel sizes are set to 0 */ 306 ws.ws_col = (buf[3] << 8) | buf[4]; 307 ws.ws_row = (buf[5] << 8) | buf[6]; 308 ioctl(ts->ptyfd, TIOCSWINSZ, (char *)&ws); 309 rc = 7; 310 /* trailing IAC SE will be eaten separately, as 2-byte NOP */ 311 goto update_and_return; 312 } 313 /* else: other subnegs not supported yet */ 314 } 315 316 /* Assume it is a 3-byte WILL/WONT/DO/DONT 251..254 command and skip it */ 317#if DEBUG 318 fprintf(stderr, "Ignoring IAC %s,%s\n", 319 TELCMD(buf[1]), TELOPT(buf[2])); 320#endif 321 rc = 3; 322 323 update_and_return: 324 ts->wridx1 += rc; 325 if (ts->wridx1 >= BUFSIZE) /* actually == BUFSIZE */ 326 ts->wridx1 = 0; 327 ts->size1 -= rc; 328 /* 329 * Hack. We cannot process IACs which wrap around buffer's end. 330 * Since properly fixing it requires writing bigger code, 331 * we rely instead on this code making it virtually impossible 332 * to have wrapped IAC (people don't type at 2k/second). 333 * It also allows for bigger reads in common case. 334 */ 335 if (ts->size1 == 0) { /* very typical */ 336 //bb_error_msg("zero size1"); 337 ts->rdidx1 = 0; 338 ts->wridx1 = 0; 339 return rc; 340 } 341 wr = ts->wridx1; 342 if (wr != 0 && wr < ts->rdidx1) { 343 /* Buffer is not wrapped yet. 344 * We can easily move it to the beginning. 345 */ 346 //bb_error_msg("moved %d", wr); 347 memmove(TS_BUF1(ts), TS_BUF1(ts) + wr, ts->size1); 348 ts->rdidx1 -= wr; 349 ts->wridx1 = 0; 350 } 351 return rc; 352} 353 354/* 355 * Converting single IAC into double on output 356 */ 357static size_t safe_write_double_iac(int fd, const char *buf, size_t count) 358{ 359 const char *IACptr; 360 size_t wr, rc, total; 361 362 total = 0; 363 while (1) { 364 if (count == 0) 365 return total; 366 if (*buf == (char)IAC) { 367 static const char IACIAC[] ALIGN1 = { IAC, IAC }; 368 rc = safe_write(fd, IACIAC, 2); 369/* BUG: if partial write was only 1 byte long, we end up emitting just one IAC */ 370 if (rc != 2) 371 break; 372 buf++; 373 total++; 374 count--; 375 continue; 376 } 377 /* count != 0, *buf != IAC */ 378 IACptr = memchr(buf, IAC, count); 379 wr = count; 380 if (IACptr) 381 wr = IACptr - buf; 382 rc = safe_write(fd, buf, wr); 383 if (rc != wr) 384 break; 385 buf += rc; 386 total += rc; 387 count -= rc; 388 } 389 /* here: rc - result of last short write */ 390 if ((ssize_t)rc < 0) { /* error? */ 391 if (total == 0) 392 return rc; 393 rc = 0; 394 } 395 return total + rc; 396} 397 398/* Must match getopt32 string */ 399enum { 400 OPT_WATCHCHILD = (1 << 2), /* -K */ 401 OPT_INETD = (1 << 3) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -i */ 402 OPT_PORT = (1 << 4) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -p PORT */ 403 OPT_FOREGROUND = (1 << 6) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -F */ 404 OPT_SYSLOG = (1 << 7) * ENABLE_FEATURE_TELNETD_INETD_WAIT, /* -S */ 405 OPT_WAIT = (1 << 8) * ENABLE_FEATURE_TELNETD_INETD_WAIT, /* -w SEC */ 406}; 407 408static struct tsession * 409make_new_session( 410 IF_FEATURE_TELNETD_STANDALONE(int sock) 411 IF_NOT_FEATURE_TELNETD_STANDALONE(void) 412) { 413#if !ENABLE_FEATURE_TELNETD_STANDALONE 414 enum { sock = 0 }; 415#endif 416 const char *login_argv[2]; 417 struct termios termbuf; 418 int fd, pid; 419 char tty_name[GETPTY_BUFSIZE]; 420 struct tsession *ts = xzalloc(sizeof(struct tsession) + BUFSIZE * 2); 421 422 /*ts->buf1 = (char *)(ts + 1);*/ 423 /*ts->buf2 = ts->buf1 + BUFSIZE;*/ 424 425 /* Got a new connection, set up a tty */ 426 fd = xgetpty(tty_name); 427 if (fd > G.maxfd) 428 G.maxfd = fd; 429 ts->ptyfd = fd; 430 ndelay_on(fd); 431 close_on_exec_on(fd); 432 433 /* SO_KEEPALIVE by popular demand */ 434 setsockopt_keepalive(sock); 435#if ENABLE_FEATURE_TELNETD_STANDALONE 436 ts->sockfd_read = sock; 437 ndelay_on(sock); 438 if (sock == 0) { /* We are called with fd 0 - we are in inetd mode */ 439 sock++; /* so use fd 1 for output */ 440 ndelay_on(sock); 441 } 442 ts->sockfd_write = sock; 443 if (sock > G.maxfd) 444 G.maxfd = sock; 445#else 446 /* ts->sockfd_read = 0; - done by xzalloc */ 447 ts->sockfd_write = 1; 448 ndelay_on(0); 449 ndelay_on(1); 450#endif 451 452 /* Make the telnet client understand we will echo characters so it 453 * should not do it locally. We don't tell the client to run linemode, 454 * because we want to handle line editing and tab completion and other 455 * stuff that requires char-by-char support. */ 456 { 457 static const char iacs_to_send[] ALIGN1 = { 458 IAC, DO, TELOPT_ECHO, 459 IAC, DO, TELOPT_NAWS, 460 /* This requires telnetd.ctrlSQ.patch (incomplete) */ 461 /*IAC, DO, TELOPT_LFLOW,*/ 462 IAC, WILL, TELOPT_ECHO, 463 IAC, WILL, TELOPT_SGA 464 }; 465 /* This confuses safe_write_double_iac(), it will try to duplicate 466 * each IAC... */ 467 //memcpy(TS_BUF2(ts), iacs_to_send, sizeof(iacs_to_send)); 468 //ts->rdidx2 = sizeof(iacs_to_send); 469 //ts->size2 = sizeof(iacs_to_send); 470 /* So just stuff it into TCP stream! (no error check...) */ 471#if ENABLE_FEATURE_TELNETD_STANDALONE 472 safe_write(sock, iacs_to_send, sizeof(iacs_to_send)); 473#else 474 safe_write(1, iacs_to_send, sizeof(iacs_to_send)); 475#endif 476 /*ts->rdidx2 = 0; - xzalloc did it */ 477 /*ts->size2 = 0;*/ 478 } 479 480 fflush_all(); 481 pid = vfork(); /* NOMMU-friendly */ 482 if (pid < 0) { 483 free(ts); 484 close(fd); 485 /* sock will be closed by caller */ 486 bb_perror_msg("vfork"); 487 return NULL; 488 } 489 if (pid > 0) { 490 /* Parent */ 491 ts->shell_pid = pid; 492 return ts; 493 } 494 495 /* Child */ 496 /* Careful - we are after vfork! */ 497 498 /* Restore default signal handling ASAP */ 499 bb_signals((1 << SIGCHLD) + (1 << SIGPIPE), SIG_DFL); 500 501 pid = getpid(); 502 503 if (ENABLE_FEATURE_UTMP) { 504 len_and_sockaddr *lsa = get_peer_lsa(sock); 505 char *hostname = NULL; 506 if (lsa) { 507 hostname = xmalloc_sockaddr2dotted(&lsa->u.sa); 508 free(lsa); 509 } 510 write_new_utmp(pid, LOGIN_PROCESS, tty_name, /*username:*/ "LOGIN", hostname); 511 free(hostname); 512 } 513 514 /* Make new session and process group */ 515 setsid(); 516 517 /* Open the child's side of the tty */ 518 /* NB: setsid() disconnects from any previous ctty's. Therefore 519 * we must open child's side of the tty AFTER setsid! */ 520 close(0); 521 xopen(tty_name, O_RDWR); /* becomes our ctty */ 522 xdup2(0, 1); 523 xdup2(0, 2); 524 tcsetpgrp(0, pid); /* switch this tty's process group to us */ 525 526 /* The pseudo-terminal allocated to the client is configured to operate 527 * in cooked mode, and with XTABS CRMOD enabled (see tty(4)) */ 528 tcgetattr(0, &termbuf); 529 termbuf.c_lflag |= ECHO; /* if we use readline we dont want this */ 530 termbuf.c_oflag |= ONLCR | XTABS; 531 termbuf.c_iflag |= ICRNL; 532 termbuf.c_iflag &= ~IXOFF; 533 /*termbuf.c_lflag &= ~ICANON;*/ 534 tcsetattr_stdin_TCSANOW(&termbuf); 535 536 /* Uses FILE-based I/O to stdout, but does fflush_all(), 537 * so should be safe with vfork. 538 * I fear, though, that some users will have ridiculously big 539 * issue files, and they may block writing to fd 1, 540 * (parent is supposed to read it, but parent waits 541 * for vforked child to exec!) */ 542 print_login_issue(G.issuefile, tty_name); 543 544 /* Exec shell / login / whatever */ 545 login_argv[0] = G.loginpath; 546 login_argv[1] = NULL; 547 /* exec busybox applet (if PREFER_APPLETS=y), if that fails, 548 * exec external program. 549 * NB: sock is either 0 or has CLOEXEC set on it. 550 * fd has CLOEXEC set on it too. These two fds will be closed here. 551 */ 552 BB_EXECVP(G.loginpath, (char **)login_argv); 553 /* _exit is safer with vfork, and we shouldn't send message 554 * to remote clients anyway */ 555 _exit(EXIT_FAILURE); /*bb_perror_msg_and_die("execv %s", G.loginpath);*/ 556} 557 558#if ENABLE_FEATURE_TELNETD_STANDALONE 559 560static void 561free_session(struct tsession *ts) 562{ 563 struct tsession *t; 564 565 if (option_mask32 & OPT_INETD) 566 exit(EXIT_SUCCESS); 567 568 /* Unlink this telnet session from the session list */ 569 t = G.sessions; 570 if (t == ts) 571 G.sessions = ts->next; 572 else { 573 while (t->next != ts) 574 t = t->next; 575 t->next = ts->next; 576 } 577 578#if 0 579 /* It was said that "normal" telnetd just closes ptyfd, 580 * doesn't send SIGKILL. When we close ptyfd, 581 * kernel sends SIGHUP to processes having slave side opened. */ 582 kill(ts->shell_pid, SIGKILL); 583 waitpid(ts->shell_pid, NULL, 0); 584#endif 585 close(ts->ptyfd); 586 close(ts->sockfd_read); 587 /* We do not need to close(ts->sockfd_write), it's the same 588 * as sockfd_read unless we are in inetd mode. But in inetd mode 589 * we do not reach this */ 590 free(ts); 591 592 /* Scan all sessions and find new maxfd */ 593 G.maxfd = 0; 594 ts = G.sessions; 595 while (ts) { 596 if (G.maxfd < ts->ptyfd) 597 G.maxfd = ts->ptyfd; 598 if (G.maxfd < ts->sockfd_read) 599 G.maxfd = ts->sockfd_read; 600#if 0 601 /* Again, sockfd_write == sockfd_read here */ 602 if (G.maxfd < ts->sockfd_write) 603 G.maxfd = ts->sockfd_write; 604#endif 605 ts = ts->next; 606 } 607} 608 609#else /* !FEATURE_TELNETD_STANDALONE */ 610 611/* Used in main() only, thus "return 0" actually is exit(EXIT_SUCCESS). */ 612#define free_session(ts) return 0 613 614#endif 615 616static void handle_sigchld(int sig UNUSED_PARAM) 617{ 618 pid_t pid; 619 struct tsession *ts; 620 int save_errno = errno; 621 622 /* Looping: more than one child may have exited */ 623 while (1) { 624 pid = wait_any_nohang(NULL); 625 if (pid <= 0) 626 break; 627 ts = G.sessions; 628 while (ts) { 629 if (ts->shell_pid == pid) { 630 ts->shell_pid = -1; 631 update_utmp_DEAD_PROCESS(pid); 632 break; 633 } 634 ts = ts->next; 635 } 636 } 637 638 errno = save_errno; 639} 640 641int telnetd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 642int telnetd_main(int argc UNUSED_PARAM, char **argv) 643{ 644 fd_set rdfdset, wrfdset; 645 unsigned opt; 646 int count; 647 struct tsession *ts; 648#if ENABLE_FEATURE_TELNETD_STANDALONE 649#define IS_INETD (opt & OPT_INETD) 650 int master_fd = master_fd; /* for compiler */ 651 int sec_linger = sec_linger; 652 char *opt_bindaddr = NULL; 653 char *opt_portnbr; 654#else 655 enum { 656 IS_INETD = 1, 657 master_fd = -1, 658 }; 659#endif 660 INIT_G(); 661 662 /* -w NUM, and implies -F. -w and -i don't mix */ 663 IF_FEATURE_TELNETD_INETD_WAIT(opt_complementary = "wF:i--w:w--i";) 664 /* Even if !STANDALONE, we accept (and ignore) -i, thus people 665 * don't need to guess whether it's ok to pass -i to us */ 666 opt = getopt32(argv, "f:l:Ki" 667 IF_FEATURE_TELNETD_STANDALONE("p:b:F") 668 IF_FEATURE_TELNETD_INETD_WAIT("Sw:+"), 669 &G.issuefile, &G.loginpath 670 IF_FEATURE_TELNETD_STANDALONE(, &opt_portnbr, &opt_bindaddr) 671 IF_FEATURE_TELNETD_INETD_WAIT(, &sec_linger) 672 ); 673 if (!IS_INETD /*&& !re_execed*/) { 674 /* inform that we start in standalone mode? 675 * May be useful when people forget to give -i */ 676 /*bb_error_msg("listening for connections");*/ 677 if (!(opt & OPT_FOREGROUND)) { 678 /* DAEMON_CHDIR_ROOT was giving inconsistent 679 * behavior with/without -F, -i */ 680 bb_daemonize_or_rexec(0 /*was DAEMON_CHDIR_ROOT*/, argv); 681 } 682 } 683 /* Redirect log to syslog early, if needed */ 684 if (IS_INETD || (opt & OPT_SYSLOG) || !(opt & OPT_FOREGROUND)) { 685 openlog(applet_name, LOG_PID, LOG_DAEMON); 686 logmode = LOGMODE_SYSLOG; 687 } 688#if ENABLE_FEATURE_TELNETD_STANDALONE 689 if (IS_INETD) { 690 G.sessions = make_new_session(0); 691 if (!G.sessions) /* pty opening or vfork problem, exit */ 692 return 1; /* make_new_session printed error message */ 693 } else { 694 master_fd = 0; 695 if (!(opt & OPT_WAIT)) { 696 unsigned portnbr = 23; 697 if (opt & OPT_PORT) 698 portnbr = xatou16(opt_portnbr); 699 master_fd = create_and_bind_stream_or_die(opt_bindaddr, portnbr); 700 xlisten(master_fd, 1); 701 } 702 close_on_exec_on(master_fd); 703 } 704#else 705 G.sessions = make_new_session(); 706 if (!G.sessions) /* pty opening or vfork problem, exit */ 707 return 1; /* make_new_session printed error message */ 708#endif 709 710 /* We don't want to die if just one session is broken */ 711 signal(SIGPIPE, SIG_IGN); 712 713 if (opt & OPT_WATCHCHILD) 714 signal(SIGCHLD, handle_sigchld); 715 else /* prevent dead children from becoming zombies */ 716 signal(SIGCHLD, SIG_IGN); 717 718/* 719 This is how the buffers are used. The arrows indicate data flow. 720 721 +-------+ wridx1++ +------+ rdidx1++ +----------+ 722 | | <-------------- | buf1 | <-------------- | | 723 | | size1-- +------+ size1++ | | 724 | pty | | socket | 725 | | rdidx2++ +------+ wridx2++ | | 726 | | --------------> | buf2 | --------------> | | 727 +-------+ size2++ +------+ size2-- +----------+ 728 729 size1: "how many bytes are buffered for pty between rdidx1 and wridx1?" 730 size2: "how many bytes are buffered for socket between rdidx2 and wridx2?" 731 732 Each session has got two buffers. Buffers are circular. If sizeN == 0, 733 buffer is empty. If sizeN == BUFSIZE, buffer is full. In both these cases 734 rdidxN == wridxN. 735*/ 736 again: 737 FD_ZERO(&rdfdset); 738 FD_ZERO(&wrfdset); 739 740 /* Select on the master socket, all telnet sockets and their 741 * ptys if there is room in their session buffers. 742 * NB: scalability problem: we recalculate entire bitmap 743 * before each select. Can be a problem with 500+ connections. */ 744 ts = G.sessions; 745 while (ts) { 746 struct tsession *next = ts->next; /* in case we free ts */ 747 if (ts->shell_pid == -1) { 748 /* Child died and we detected that */ 749 free_session(ts); 750 } else { 751 if (ts->size1 > 0) /* can write to pty */ 752 FD_SET(ts->ptyfd, &wrfdset); 753 if (ts->size1 < BUFSIZE) /* can read from socket */ 754 FD_SET(ts->sockfd_read, &rdfdset); 755 if (ts->size2 > 0) /* can write to socket */ 756 FD_SET(ts->sockfd_write, &wrfdset); 757 if (ts->size2 < BUFSIZE) /* can read from pty */ 758 FD_SET(ts->ptyfd, &rdfdset); 759 } 760 ts = next; 761 } 762 if (!IS_INETD) { 763 FD_SET(master_fd, &rdfdset); 764 /* This is needed because free_session() does not 765 * take master_fd into account when it finds new 766 * maxfd among remaining fd's */ 767 if (master_fd > G.maxfd) 768 G.maxfd = master_fd; 769 } 770 771 { 772 struct timeval *tv_ptr = NULL; 773#if ENABLE_FEATURE_TELNETD_INETD_WAIT 774 struct timeval tv; 775 if ((opt & OPT_WAIT) && !G.sessions) { 776 tv.tv_sec = sec_linger; 777 tv.tv_usec = 0; 778 tv_ptr = &tv; 779 } 780#endif 781 count = select(G.maxfd + 1, &rdfdset, &wrfdset, NULL, tv_ptr); 782 } 783 if (count == 0) /* "telnetd -w SEC" timed out */ 784 return 0; 785 if (count < 0) 786 goto again; /* EINTR or ENOMEM */ 787 788#if ENABLE_FEATURE_TELNETD_STANDALONE 789 /* Check for and accept new sessions */ 790 if (!IS_INETD && FD_ISSET(master_fd, &rdfdset)) { 791 int fd; 792 struct tsession *new_ts; 793 794 fd = accept(master_fd, NULL, NULL); 795 if (fd < 0) 796 goto again; 797 close_on_exec_on(fd); 798 799 /* Create a new session and link it into active list */ 800 new_ts = make_new_session(fd); 801 if (new_ts) { 802 new_ts->next = G.sessions; 803 G.sessions = new_ts; 804 } else { 805 close(fd); 806 } 807 } 808#endif 809 810 /* Then check for data tunneling */ 811 ts = G.sessions; 812 while (ts) { /* For all sessions... */ 813 struct tsession *next = ts->next; /* in case we free ts */ 814 815 if (/*ts->size1 &&*/ FD_ISSET(ts->ptyfd, &wrfdset)) { 816 /* Write to pty from buffer 1 */ 817 count = safe_write_to_pty_decode_iac(ts); 818 if (count < 0) { 819 if (errno == EAGAIN) 820 goto skip1; 821 goto kill_session; 822 } 823 } 824 skip1: 825 if (/*ts->size2 &&*/ FD_ISSET(ts->sockfd_write, &wrfdset)) { 826 /* Write to socket from buffer 2 */ 827 count = MIN(BUFSIZE - ts->wridx2, ts->size2); 828 count = safe_write_double_iac(ts->sockfd_write, (void*)(TS_BUF2(ts) + ts->wridx2), count); 829 if (count < 0) { 830 if (errno == EAGAIN) 831 goto skip2; 832 goto kill_session; 833 } 834 ts->wridx2 += count; 835 if (ts->wridx2 >= BUFSIZE) /* actually == BUFSIZE */ 836 ts->wridx2 = 0; 837 ts->size2 -= count; 838 if (ts->size2 == 0) { 839 ts->rdidx2 = 0; 840 ts->wridx2 = 0; 841 } 842 } 843 skip2: 844 845 if (/*ts->size1 < BUFSIZE &&*/ FD_ISSET(ts->sockfd_read, &rdfdset)) { 846 /* Read from socket to buffer 1 */ 847 count = MIN(BUFSIZE - ts->rdidx1, BUFSIZE - ts->size1); 848 count = safe_read(ts->sockfd_read, TS_BUF1(ts) + ts->rdidx1, count); 849 if (count <= 0) { 850 if (count < 0 && errno == EAGAIN) 851 goto skip3; 852 goto kill_session; 853 } 854 /* Ignore trailing NUL if it is there */ 855 if (!TS_BUF1(ts)[ts->rdidx1 + count - 1]) { 856 --count; 857 } 858 ts->size1 += count; 859 ts->rdidx1 += count; 860 if (ts->rdidx1 >= BUFSIZE) /* actually == BUFSIZE */ 861 ts->rdidx1 = 0; 862 } 863 skip3: 864 if (/*ts->size2 < BUFSIZE &&*/ FD_ISSET(ts->ptyfd, &rdfdset)) { 865 /* Read from pty to buffer 2 */ 866 count = MIN(BUFSIZE - ts->rdidx2, BUFSIZE - ts->size2); 867 count = safe_read(ts->ptyfd, TS_BUF2(ts) + ts->rdidx2, count); 868 if (count <= 0) { 869 if (count < 0 && errno == EAGAIN) 870 goto skip4; 871 goto kill_session; 872 } 873 ts->size2 += count; 874 ts->rdidx2 += count; 875 if (ts->rdidx2 >= BUFSIZE) /* actually == BUFSIZE */ 876 ts->rdidx2 = 0; 877 } 878 skip4: 879 ts = next; 880 continue; 881 kill_session: 882 if (ts->shell_pid > 0) 883 update_utmp_DEAD_PROCESS(ts->shell_pid); 884 free_session(ts); 885 ts = next; 886 } 887 888 goto again; 889} 890