1 /* vi: set sw=4 ts=4: */
4 * Bjorn Wesen, Axis Communications AB (bjornw@axis.com)
6 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 * ---------------------------------------------------------------------------
9 * (C) Copyright 2000, Axis Communications AB, LUND, SWEDEN
10 ****************************************************************************
12 * The telnetd manpage says it all:
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.
20 * Vladimir Oleynik <dzo@simtreas.ru> 2001
21 * Set process group corrections, initial busybox port
24 //usage:#define telnetd_trivial_usage
26 //usage:#define telnetd_full_usage "\n\n"
27 //usage: "Handle incoming telnet connections"
28 //usage: IF_NOT_FEATURE_TELNETD_STANDALONE(" via inetd") "\n"
29 //usage: "\n -l LOGIN Exec LOGIN on connect"
30 //usage: "\n -f ISSUE_FILE Display ISSUE_FILE instead of /etc/issue"
31 //usage: "\n -K Close connection as soon as login exits"
32 //usage: "\n (normally wait until all programs close slave pty)"
33 //usage: IF_FEATURE_TELNETD_STANDALONE(
34 //usage: "\n -p PORT Port to listen on"
35 //usage: "\n -b ADDR[:PORT] Address to bind to"
36 //usage: "\n -F Run in foreground"
37 //usage: "\n -i Inetd mode"
38 //usage: IF_FEATURE_TELNETD_INETD_WAIT(
39 //usage: "\n -w SEC Inetd 'wait' mode, linger time SEC"
40 //usage: "\n -S Log to syslog (implied by -i or without -F and -w)"
53 #include <arpa/telnet.h>
57 struct tsession *next;
63 /* two circular buffers */
64 /*char *buf1, *buf2;*/
65 /*#define TS_BUF1(ts) ts->buf1*/
66 /*#define TS_BUF2(ts) TS_BUF2(ts)*/
67 #define TS_BUF1(ts) ((unsigned char*)(ts + 1))
68 #define TS_BUF2(ts) (((unsigned char*)(ts + 1)) + BUFSIZE)
69 int rdidx1, wridx1, size1;
70 int rdidx2, wridx2, size2;
73 /* Two buffers are directly after tsession in malloced memory.
74 * Make whole thing fit in 4k */
75 enum { BUFSIZE = (4 * 1024 - sizeof(struct tsession)) / 2 };
80 struct tsession *sessions;
81 const char *loginpath;
82 const char *issuefile;
85 #define G (*(struct globals*)&bb_common_bufsiz1)
86 #define INIT_G() do { \
87 G.loginpath = "/bin/login"; \
88 G.issuefile = "/etc/issue.net"; \
93 Remove all IAC's from buf1 (received IACs are ignored and must be removed
94 so as to not be interpreted by the terminal). Make an uninterrupted
95 string of characters fit for the terminal. Do this by packing
96 all characters meant for the terminal sequentially towards the end of buf.
98 Return a pointer to the beginning of the characters meant for the terminal
99 and make *num_totty the number of characters that should be sent to
102 Note - if an IAC (3 byte quantity) starts before (bf + len) but extends
103 past (bf + len) then that IAC will be left unprocessed and *processed
104 will be less than len.
106 CR-LF ->'s CR mapping is also done here, for convenience.
108 NB: may fail to remove iacs which wrap around buffer!
110 static unsigned char *
111 remove_iacs(struct tsession *ts, int *pnum_totty)
113 unsigned char *ptr0 = TS_BUF1(ts) + ts->wridx1;
114 unsigned char *ptr = ptr0;
115 unsigned char *totty = ptr;
116 unsigned char *end = ptr + MIN(BUFSIZE - ts->wridx1, ts->size1);
125 /* We map \r\n ==> \r for pragmatic reasons.
126 * Many client implementations send \r\n when
127 * the user hits the CarriageReturn key.
128 * See RFC 1123 3.3.1 Telnet End-of-Line Convention.
130 if (c == '\r' && ptr < end && (*ptr == '\n' || *ptr == '\0'))
137 if (ptr[1] == NOP) { /* Ignore? (putty keepalive, etc.) */
141 if (ptr[1] == IAC) { /* Literal IAC? (emacs M-DEL) */
148 * TELOPT_NAWS support!
150 if ((ptr+2) >= end) {
151 /* Only the beginning of the IAC is in the
152 buffer we were asked to process, we can't
157 * IAC -> SB -> TELOPT_NAWS -> 4-byte -> IAC -> SE
159 if (ptr[1] == SB && ptr[2] == TELOPT_NAWS) {
162 break; /* incomplete, can't process */
163 ws.ws_col = (ptr[3] << 8) | ptr[4];
164 ws.ws_row = (ptr[5] << 8) | ptr[6];
165 ioctl(ts->ptyfd, TIOCSWINSZ, (char *)&ws);
169 /* skip 3-byte IAC non-SB cmd */
171 fprintf(stderr, "Ignoring IAC %s,%s\n",
172 TELCMD(ptr[1]), TELOPT(ptr[2]));
177 num_totty = totty - ptr0;
178 *pnum_totty = num_totty;
179 /* The difference between ptr and totty is number of iacs
180 we removed from the stream. Adjust buf1 accordingly */
181 if ((ptr - totty) == 0) /* 99.999% of cases */
183 ts->wridx1 += ptr - totty;
184 ts->size1 -= ptr - totty;
185 /* Move chars meant for the terminal towards the end of the buffer */
186 return memmove(ptr - num_totty, ptr0, num_totty);
190 * Converting single IAC into double on output
192 static size_t iac_safe_write(int fd, const char *buf, size_t count)
195 size_t wr, rc, total;
201 if (*buf == (char)IAC) {
202 static const char IACIAC[] ALIGN1 = { IAC, IAC };
203 rc = safe_write(fd, IACIAC, 2);
211 /* count != 0, *buf != IAC */
212 IACptr = memchr(buf, IAC, count);
216 rc = safe_write(fd, buf, wr);
223 /* here: rc - result of last short write */
224 if ((ssize_t)rc < 0) { /* error? */
232 /* Must match getopt32 string */
234 OPT_WATCHCHILD = (1 << 2), /* -K */
235 OPT_INETD = (1 << 3) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -i */
236 OPT_PORT = (1 << 4) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -p PORT */
237 OPT_FOREGROUND = (1 << 6) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -F */
238 OPT_SYSLOG = (1 << 7) * ENABLE_FEATURE_TELNETD_INETD_WAIT, /* -S */
239 OPT_WAIT = (1 << 8) * ENABLE_FEATURE_TELNETD_INETD_WAIT, /* -w SEC */
242 static struct tsession *
244 IF_FEATURE_TELNETD_STANDALONE(int sock)
245 IF_NOT_FEATURE_TELNETD_STANDALONE(void)
247 #if !ENABLE_FEATURE_TELNETD_STANDALONE
250 const char *login_argv[2];
251 struct termios termbuf;
253 char tty_name[GETPTY_BUFSIZE];
254 struct tsession *ts = xzalloc(sizeof(struct tsession) + BUFSIZE * 2);
256 /*ts->buf1 = (char *)(ts + 1);*/
257 /*ts->buf2 = ts->buf1 + BUFSIZE;*/
259 /* Got a new connection, set up a tty */
260 fd = xgetpty(tty_name);
265 close_on_exec_on(fd);
267 /* SO_KEEPALIVE by popular demand */
268 setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1));
269 #if ENABLE_FEATURE_TELNETD_STANDALONE
270 ts->sockfd_read = sock;
272 if (sock == 0) { /* We are called with fd 0 - we are in inetd mode */
273 sock++; /* so use fd 1 for output */
276 ts->sockfd_write = sock;
280 /* ts->sockfd_read = 0; - done by xzalloc */
281 ts->sockfd_write = 1;
286 /* Make the telnet client understand we will echo characters so it
287 * should not do it locally. We don't tell the client to run linemode,
288 * because we want to handle line editing and tab completion and other
289 * stuff that requires char-by-char support. */
291 static const char iacs_to_send[] ALIGN1 = {
292 IAC, DO, TELOPT_ECHO,
293 IAC, DO, TELOPT_NAWS,
294 /* This requires telnetd.ctrlSQ.patch (incomplete) */
295 /*IAC, DO, TELOPT_LFLOW,*/
296 IAC, WILL, TELOPT_ECHO,
297 IAC, WILL, TELOPT_SGA
299 /* This confuses iac_safe_write(), it will try to duplicate
301 //memcpy(TS_BUF2(ts), iacs_to_send, sizeof(iacs_to_send));
302 //ts->rdidx2 = sizeof(iacs_to_send);
303 //ts->size2 = sizeof(iacs_to_send);
304 /* So just stuff it into TCP stream! (no error check...) */
305 #if ENABLE_FEATURE_TELNETD_STANDALONE
306 safe_write(sock, iacs_to_send, sizeof(iacs_to_send));
308 safe_write(1, iacs_to_send, sizeof(iacs_to_send));
310 /*ts->rdidx2 = 0; - xzalloc did it */
315 pid = vfork(); /* NOMMU-friendly */
319 /* sock will be closed by caller */
320 bb_perror_msg("vfork");
330 /* Careful - we are after vfork! */
332 /* Restore default signal handling ASAP */
333 bb_signals((1 << SIGCHLD) + (1 << SIGPIPE), SIG_DFL);
337 if (ENABLE_FEATURE_UTMP) {
338 len_and_sockaddr *lsa = get_peer_lsa(sock);
339 char *hostname = NULL;
341 hostname = xmalloc_sockaddr2dotted(&lsa->u.sa);
344 write_new_utmp(pid, LOGIN_PROCESS, tty_name, /*username:*/ "LOGIN", hostname);
348 /* Make new session and process group */
351 /* Open the child's side of the tty */
352 /* NB: setsid() disconnects from any previous ctty's. Therefore
353 * we must open child's side of the tty AFTER setsid! */
355 xopen(tty_name, O_RDWR); /* becomes our ctty */
358 tcsetpgrp(0, pid); /* switch this tty's process group to us */
360 /* The pseudo-terminal allocated to the client is configured to operate
361 * in cooked mode, and with XTABS CRMOD enabled (see tty(4)) */
362 tcgetattr(0, &termbuf);
363 termbuf.c_lflag |= ECHO; /* if we use readline we dont want this */
364 termbuf.c_oflag |= ONLCR | XTABS;
365 termbuf.c_iflag |= ICRNL;
366 termbuf.c_iflag &= ~IXOFF;
367 /*termbuf.c_lflag &= ~ICANON;*/
368 tcsetattr_stdin_TCSANOW(&termbuf);
370 /* Uses FILE-based I/O to stdout, but does fflush_all(),
371 * so should be safe with vfork.
372 * I fear, though, that some users will have ridiculously big
373 * issue files, and they may block writing to fd 1,
374 * (parent is supposed to read it, but parent waits
375 * for vforked child to exec!) */
376 print_login_issue(G.issuefile, tty_name);
378 /* Exec shell / login / whatever */
379 login_argv[0] = G.loginpath;
380 login_argv[1] = NULL;
381 /* exec busybox applet (if PREFER_APPLETS=y), if that fails,
382 * exec external program.
383 * NB: sock is either 0 or has CLOEXEC set on it.
384 * fd has CLOEXEC set on it too. These two fds will be closed here.
386 BB_EXECVP(G.loginpath, (char **)login_argv);
387 /* _exit is safer with vfork, and we shouldn't send message
388 * to remote clients anyway */
389 _exit(EXIT_FAILURE); /*bb_perror_msg_and_die("execv %s", G.loginpath);*/
392 #if ENABLE_FEATURE_TELNETD_STANDALONE
395 free_session(struct tsession *ts)
399 if (option_mask32 & OPT_INETD)
402 /* Unlink this telnet session from the session list */
405 G.sessions = ts->next;
407 while (t->next != ts)
413 /* It was said that "normal" telnetd just closes ptyfd,
414 * doesn't send SIGKILL. When we close ptyfd,
415 * kernel sends SIGHUP to processes having slave side opened. */
416 kill(ts->shell_pid, SIGKILL);
417 waitpid(ts->shell_pid, NULL, 0);
420 close(ts->sockfd_read);
421 /* We do not need to close(ts->sockfd_write), it's the same
422 * as sockfd_read unless we are in inetd mode. But in inetd mode
423 * we do not reach this */
426 /* Scan all sessions and find new maxfd */
430 if (G.maxfd < ts->ptyfd)
432 if (G.maxfd < ts->sockfd_read)
433 G.maxfd = ts->sockfd_read;
435 /* Again, sockfd_write == sockfd_read here */
436 if (G.maxfd < ts->sockfd_write)
437 G.maxfd = ts->sockfd_write;
443 #else /* !FEATURE_TELNETD_STANDALONE */
445 /* Used in main() only, thus "return 0" actually is exit(EXIT_SUCCESS). */
446 #define free_session(ts) return 0
450 static void handle_sigchld(int sig UNUSED_PARAM)
454 int save_errno = errno;
456 /* Looping: more than one child may have exited */
458 pid = wait_any_nohang(NULL);
463 if (ts->shell_pid == pid) {
465 update_utmp_DEAD_PROCESS(pid);
475 int telnetd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
476 int telnetd_main(int argc UNUSED_PARAM, char **argv)
478 fd_set rdfdset, wrfdset;
482 #if ENABLE_FEATURE_TELNETD_STANDALONE
483 #define IS_INETD (opt & OPT_INETD)
484 int master_fd = master_fd; /* for compiler */
485 int sec_linger = sec_linger;
486 char *opt_bindaddr = NULL;
496 /* -w NUM, and implies -F. -w and -i don't mix */
497 IF_FEATURE_TELNETD_INETD_WAIT(opt_complementary = "wF:w+:i--w:w--i";)
498 /* Even if !STANDALONE, we accept (and ignore) -i, thus people
499 * don't need to guess whether it's ok to pass -i to us */
500 opt = getopt32(argv, "f:l:Ki"
501 IF_FEATURE_TELNETD_STANDALONE("p:b:F")
502 IF_FEATURE_TELNETD_INETD_WAIT("Sw:"),
503 &G.issuefile, &G.loginpath
504 IF_FEATURE_TELNETD_STANDALONE(, &opt_portnbr, &opt_bindaddr)
505 IF_FEATURE_TELNETD_INETD_WAIT(, &sec_linger)
507 if (!IS_INETD /*&& !re_execed*/) {
508 /* inform that we start in standalone mode?
509 * May be useful when people forget to give -i */
510 /*bb_error_msg("listening for connections");*/
511 if (!(opt & OPT_FOREGROUND)) {
512 /* DAEMON_CHDIR_ROOT was giving inconsistent
513 * behavior with/without -F, -i */
514 bb_daemonize_or_rexec(0 /*was DAEMON_CHDIR_ROOT*/, argv);
517 /* Redirect log to syslog early, if needed */
518 if (IS_INETD || (opt & OPT_SYSLOG) || !(opt & OPT_FOREGROUND)) {
519 openlog(applet_name, LOG_PID, LOG_DAEMON);
520 logmode = LOGMODE_SYSLOG;
522 #if ENABLE_FEATURE_TELNETD_STANDALONE
524 G.sessions = make_new_session(0);
525 if (!G.sessions) /* pty opening or vfork problem, exit */
526 return 1; /* make_new_session printed error message */
529 if (!(opt & OPT_WAIT)) {
530 unsigned portnbr = 23;
532 portnbr = xatou16(opt_portnbr);
533 master_fd = create_and_bind_stream_or_die(opt_bindaddr, portnbr);
534 xlisten(master_fd, 1);
536 close_on_exec_on(master_fd);
539 G.sessions = make_new_session();
540 if (!G.sessions) /* pty opening or vfork problem, exit */
541 return 1; /* make_new_session printed error message */
544 /* We don't want to die if just one session is broken */
545 signal(SIGPIPE, SIG_IGN);
547 if (opt & OPT_WATCHCHILD)
548 signal(SIGCHLD, handle_sigchld);
549 else /* prevent dead children from becoming zombies */
550 signal(SIGCHLD, SIG_IGN);
553 This is how the buffers are used. The arrows indicate data flow.
555 +-------+ wridx1++ +------+ rdidx1++ +----------+
556 | | <-------------- | buf1 | <-------------- | |
557 | | size1-- +------+ size1++ | |
559 | | rdidx2++ +------+ wridx2++ | |
560 | | --------------> | buf2 | --------------> | |
561 +-------+ size2++ +------+ size2-- +----------+
563 size1: "how many bytes are buffered for pty between rdidx1 and wridx1?"
564 size2: "how many bytes are buffered for socket between rdidx2 and wridx2?"
566 Each session has got two buffers. Buffers are circular. If sizeN == 0,
567 buffer is empty. If sizeN == BUFSIZE, buffer is full. In both these cases
574 /* Select on the master socket, all telnet sockets and their
575 * ptys if there is room in their session buffers.
576 * NB: scalability problem: we recalculate entire bitmap
577 * before each select. Can be a problem with 500+ connections. */
580 struct tsession *next = ts->next; /* in case we free ts */
581 if (ts->shell_pid == -1) {
582 /* Child died and we detected that */
585 if (ts->size1 > 0) /* can write to pty */
586 FD_SET(ts->ptyfd, &wrfdset);
587 if (ts->size1 < BUFSIZE) /* can read from socket */
588 FD_SET(ts->sockfd_read, &rdfdset);
589 if (ts->size2 > 0) /* can write to socket */
590 FD_SET(ts->sockfd_write, &wrfdset);
591 if (ts->size2 < BUFSIZE) /* can read from pty */
592 FD_SET(ts->ptyfd, &rdfdset);
597 FD_SET(master_fd, &rdfdset);
598 /* This is needed because free_session() does not
599 * take master_fd into account when it finds new
600 * maxfd among remaining fd's */
601 if (master_fd > G.maxfd)
606 struct timeval *tv_ptr = NULL;
607 #if ENABLE_FEATURE_TELNETD_INETD_WAIT
609 if ((opt & OPT_WAIT) && !G.sessions) {
610 tv.tv_sec = sec_linger;
615 count = select(G.maxfd + 1, &rdfdset, &wrfdset, NULL, tv_ptr);
617 if (count == 0) /* "telnetd -w SEC" timed out */
620 goto again; /* EINTR or ENOMEM */
622 #if ENABLE_FEATURE_TELNETD_STANDALONE
623 /* Check for and accept new sessions */
624 if (!IS_INETD && FD_ISSET(master_fd, &rdfdset)) {
626 struct tsession *new_ts;
628 fd = accept(master_fd, NULL, NULL);
631 close_on_exec_on(fd);
633 /* Create a new session and link it into active list */
634 new_ts = make_new_session(fd);
636 new_ts->next = G.sessions;
644 /* Then check for data tunneling */
646 while (ts) { /* For all sessions... */
647 struct tsession *next = ts->next; /* in case we free ts */
649 if (/*ts->size1 &&*/ FD_ISSET(ts->ptyfd, &wrfdset)) {
652 /* Write to pty from buffer 1 */
653 ptr = remove_iacs(ts, &num_totty);
654 count = safe_write(ts->ptyfd, ptr, num_totty);
662 if (ts->wridx1 >= BUFSIZE) /* actually == BUFSIZE */
666 if (/*ts->size2 &&*/ FD_ISSET(ts->sockfd_write, &wrfdset)) {
667 /* Write to socket from buffer 2 */
668 count = MIN(BUFSIZE - ts->wridx2, ts->size2);
669 count = iac_safe_write(ts->sockfd_write, (void*)(TS_BUF2(ts) + ts->wridx2), count);
677 if (ts->wridx2 >= BUFSIZE) /* actually == BUFSIZE */
681 /* Should not be needed, but... remove_iacs is actually buggy
682 * (it cannot process iacs which wrap around buffer's end)!
683 * Since properly fixing it requires writing bigger code,
684 * we rely instead on this code making it virtually impossible
685 * to have wrapped iac (people don't type at 2k/second).
686 * It also allows for bigger reads in common case. */
687 if (ts->size1 == 0) {
691 if (ts->size2 == 0) {
696 if (/*ts->size1 < BUFSIZE &&*/ FD_ISSET(ts->sockfd_read, &rdfdset)) {
697 /* Read from socket to buffer 1 */
698 count = MIN(BUFSIZE - ts->rdidx1, BUFSIZE - ts->size1);
699 count = safe_read(ts->sockfd_read, TS_BUF1(ts) + ts->rdidx1, count);
701 if (count < 0 && errno == EAGAIN)
705 /* Ignore trailing NUL if it is there */
706 if (!TS_BUF1(ts)[ts->rdidx1 + count - 1]) {
711 if (ts->rdidx1 >= BUFSIZE) /* actually == BUFSIZE */
715 if (/*ts->size2 < BUFSIZE &&*/ FD_ISSET(ts->ptyfd, &rdfdset)) {
716 /* Read from pty to buffer 2 */
717 count = MIN(BUFSIZE - ts->rdidx2, BUFSIZE - ts->size2);
718 count = safe_read(ts->ptyfd, TS_BUF2(ts) + ts->rdidx2, count);
720 if (count < 0 && errno == EAGAIN)
726 if (ts->rdidx2 >= BUFSIZE) /* actually == BUFSIZE */
733 if (ts->shell_pid > 0)
734 update_utmp_DEAD_PROCESS(ts->shell_pid);