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
32 #include <arpa/telnet.h>
34 #if ENABLE_FEATURE_UTMP
35 # include <utmp.h> /* LOGIN_PROCESS */
40 struct tsession *next;
46 /* two circular buffers */
47 /*char *buf1, *buf2;*/
48 /*#define TS_BUF1(ts) ts->buf1*/
49 /*#define TS_BUF2(ts) TS_BUF2(ts)*/
50 #define TS_BUF1(ts) ((unsigned char*)(ts + 1))
51 #define TS_BUF2(ts) (((unsigned char*)(ts + 1)) + BUFSIZE)
52 int rdidx1, wridx1, size1;
53 int rdidx2, wridx2, size2;
56 /* Two buffers are directly after tsession in malloced memory.
57 * Make whole thing fit in 4k */
58 enum { BUFSIZE = (4 * 1024 - sizeof(struct tsession)) / 2 };
63 struct tsession *sessions;
64 const char *loginpath;
65 const char *issuefile;
68 #define G (*(struct globals*)&bb_common_bufsiz1)
69 #define INIT_G() do { \
70 G.loginpath = "/bin/login"; \
71 G.issuefile = "/etc/issue.net"; \
76 Remove all IAC's from buf1 (received IACs are ignored and must be removed
77 so as to not be interpreted by the terminal). Make an uninterrupted
78 string of characters fit for the terminal. Do this by packing
79 all characters meant for the terminal sequentially towards the end of buf.
81 Return a pointer to the beginning of the characters meant for the terminal
82 and make *num_totty the number of characters that should be sent to
85 Note - if an IAC (3 byte quantity) starts before (bf + len) but extends
86 past (bf + len) then that IAC will be left unprocessed and *processed
87 will be less than len.
89 CR-LF ->'s CR mapping is also done here, for convenience.
91 NB: may fail to remove iacs which wrap around buffer!
93 static unsigned char *
94 remove_iacs(struct tsession *ts, int *pnum_totty)
96 unsigned char *ptr0 = TS_BUF1(ts) + ts->wridx1;
97 unsigned char *ptr = ptr0;
98 unsigned char *totty = ptr;
99 unsigned char *end = ptr + MIN(BUFSIZE - ts->wridx1, ts->size1);
108 /* We map \r\n ==> \r for pragmatic reasons.
109 * Many client implementations send \r\n when
110 * the user hits the CarriageReturn key.
112 if (c == '\r' && ptr < end && (*ptr == '\n' || *ptr == '\0'))
119 if (ptr[1] == NOP) { /* Ignore? (putty keepalive, etc.) */
123 if (ptr[1] == IAC) { /* Literal IAC? (emacs M-DEL) */
130 * TELOPT_NAWS support!
132 if ((ptr+2) >= end) {
133 /* Only the beginning of the IAC is in the
134 buffer we were asked to process, we can't
139 * IAC -> SB -> TELOPT_NAWS -> 4-byte -> IAC -> SE
141 if (ptr[1] == SB && ptr[2] == TELOPT_NAWS) {
144 break; /* incomplete, can't process */
145 ws.ws_col = (ptr[3] << 8) | ptr[4];
146 ws.ws_row = (ptr[5] << 8) | ptr[6];
147 ioctl(ts->ptyfd, TIOCSWINSZ, (char *)&ws);
151 /* skip 3-byte IAC non-SB cmd */
153 fprintf(stderr, "Ignoring IAC %s,%s\n",
154 TELCMD(ptr[1]), TELOPT(ptr[2]));
159 num_totty = totty - ptr0;
160 *pnum_totty = num_totty;
161 /* The difference between ptr and totty is number of iacs
162 we removed from the stream. Adjust buf1 accordingly */
163 if ((ptr - totty) == 0) /* 99.999% of cases */
165 ts->wridx1 += ptr - totty;
166 ts->size1 -= ptr - totty;
167 /* Move chars meant for the terminal towards the end of the buffer */
168 return memmove(ptr - num_totty, ptr0, num_totty);
172 * Converting single IAC into double on output
174 static size_t iac_safe_write(int fd, const char *buf, size_t count)
177 size_t wr, rc, total;
183 if (*buf == (char)IAC) {
184 static const char IACIAC[] ALIGN1 = { IAC, IAC };
185 rc = safe_write(fd, IACIAC, 2);
193 /* count != 0, *buf != IAC */
194 IACptr = memchr(buf, IAC, count);
198 rc = safe_write(fd, buf, wr);
205 /* here: rc - result of last short write */
206 if ((ssize_t)rc < 0) { /* error? */
214 /* Must match getopt32 string */
216 OPT_WATCHCHILD = (1 << 2), /* -K */
217 OPT_INETD = (1 << 3) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -i */
218 OPT_PORT = (1 << 4) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -p PORT */
219 OPT_FOREGROUND = (1 << 6) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -F */
220 OPT_SYSLOG = (1 << 7) * ENABLE_FEATURE_TELNETD_INETD_WAIT, /* -S */
221 OPT_WAIT = (1 << 8) * ENABLE_FEATURE_TELNETD_INETD_WAIT, /* -w SEC */
224 static struct tsession *
226 IF_FEATURE_TELNETD_STANDALONE(int sock)
227 IF_NOT_FEATURE_TELNETD_STANDALONE(void)
229 #if !ENABLE_FEATURE_TELNETD_STANDALONE
232 const char *login_argv[2];
233 struct termios termbuf;
235 char tty_name[GETPTY_BUFSIZE];
236 struct tsession *ts = xzalloc(sizeof(struct tsession) + BUFSIZE * 2);
238 /*ts->buf1 = (char *)(ts + 1);*/
239 /*ts->buf2 = ts->buf1 + BUFSIZE;*/
241 /* Got a new connection, set up a tty */
242 fd = xgetpty(tty_name);
247 close_on_exec_on(fd);
249 /* SO_KEEPALIVE by popular demand */
250 setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1));
251 #if ENABLE_FEATURE_TELNETD_STANDALONE
252 ts->sockfd_read = sock;
254 if (sock == 0) { /* We are called with fd 0 - we are in inetd mode */
255 sock++; /* so use fd 1 for output */
258 ts->sockfd_write = sock;
262 /* ts->sockfd_read = 0; - done by xzalloc */
263 ts->sockfd_write = 1;
268 /* Make the telnet client understand we will echo characters so it
269 * should not do it locally. We don't tell the client to run linemode,
270 * because we want to handle line editing and tab completion and other
271 * stuff that requires char-by-char support. */
273 static const char iacs_to_send[] ALIGN1 = {
274 IAC, DO, TELOPT_ECHO,
275 IAC, DO, TELOPT_NAWS,
276 /* This requires telnetd.ctrlSQ.patch (incomplete) */
277 /*IAC, DO, TELOPT_LFLOW,*/
278 IAC, WILL, TELOPT_ECHO,
279 IAC, WILL, TELOPT_SGA
281 /* This confuses iac_safe_write(), it will try to duplicate
283 //memcpy(TS_BUF2(ts), iacs_to_send, sizeof(iacs_to_send));
284 //ts->rdidx2 = sizeof(iacs_to_send);
285 //ts->size2 = sizeof(iacs_to_send);
286 /* So just stuff it into TCP stream! (no error check...) */
287 #if ENABLE_FEATURE_TELNETD_STANDALONE
288 safe_write(sock, iacs_to_send, sizeof(iacs_to_send));
290 safe_write(1, iacs_to_send, sizeof(iacs_to_send));
292 /*ts->rdidx2 = 0; - xzalloc did it */
297 pid = vfork(); /* NOMMU-friendly */
301 /* sock will be closed by caller */
302 bb_perror_msg("vfork");
312 /* Careful - we are after vfork! */
314 /* Restore default signal handling ASAP */
315 bb_signals((1 << SIGCHLD) + (1 << SIGPIPE), SIG_DFL);
319 if (ENABLE_FEATURE_UTMP) {
320 len_and_sockaddr *lsa = get_peer_lsa(sock);
321 char *hostname = NULL;
323 hostname = xmalloc_sockaddr2dotted(&lsa->u.sa);
326 write_new_utmp(pid, LOGIN_PROCESS, tty_name, /*username:*/ "LOGIN", hostname);
330 /* Make new session and process group */
333 /* Open the child's side of the tty */
334 /* NB: setsid() disconnects from any previous ctty's. Therefore
335 * we must open child's side of the tty AFTER setsid! */
337 xopen(tty_name, O_RDWR); /* becomes our ctty */
340 tcsetpgrp(0, pid); /* switch this tty's process group to us */
342 /* The pseudo-terminal allocated to the client is configured to operate
343 * in cooked mode, and with XTABS CRMOD enabled (see tty(4)) */
344 tcgetattr(0, &termbuf);
345 termbuf.c_lflag |= ECHO; /* if we use readline we dont want this */
346 termbuf.c_oflag |= ONLCR | XTABS;
347 termbuf.c_iflag |= ICRNL;
348 termbuf.c_iflag &= ~IXOFF;
349 /*termbuf.c_lflag &= ~ICANON;*/
350 tcsetattr_stdin_TCSANOW(&termbuf);
352 /* Uses FILE-based I/O to stdout, but does fflush_all(),
353 * so should be safe with vfork.
354 * I fear, though, that some users will have ridiculously big
355 * issue files, and they may block writing to fd 1,
356 * (parent is supposed to read it, but parent waits
357 * for vforked child to exec!) */
358 print_login_issue(G.issuefile, tty_name);
360 /* Exec shell / login / whatever */
361 login_argv[0] = G.loginpath;
362 login_argv[1] = NULL;
363 /* exec busybox applet (if PREFER_APPLETS=y), if that fails,
364 * exec external program.
365 * NB: sock is either 0 or has CLOEXEC set on it.
366 * fd has CLOEXEC set on it too. These two fds will be closed here.
368 BB_EXECVP(G.loginpath, (char **)login_argv);
369 /* _exit is safer with vfork, and we shouldn't send message
370 * to remote clients anyway */
371 _exit(EXIT_FAILURE); /*bb_perror_msg_and_die("execv %s", G.loginpath);*/
374 #if ENABLE_FEATURE_TELNETD_STANDALONE
377 free_session(struct tsession *ts)
381 if (option_mask32 & OPT_INETD)
384 /* Unlink this telnet session from the session list */
387 G.sessions = ts->next;
389 while (t->next != ts)
395 /* It was said that "normal" telnetd just closes ptyfd,
396 * doesn't send SIGKILL. When we close ptyfd,
397 * kernel sends SIGHUP to processes having slave side opened. */
398 kill(ts->shell_pid, SIGKILL);
399 waitpid(ts->shell_pid, NULL, 0);
402 close(ts->sockfd_read);
403 /* We do not need to close(ts->sockfd_write), it's the same
404 * as sockfd_read unless we are in inetd mode. But in inetd mode
405 * we do not reach this */
408 /* Scan all sessions and find new maxfd */
412 if (G.maxfd < ts->ptyfd)
414 if (G.maxfd < ts->sockfd_read)
415 G.maxfd = ts->sockfd_read;
417 /* Again, sockfd_write == sockfd_read here */
418 if (G.maxfd < ts->sockfd_write)
419 G.maxfd = ts->sockfd_write;
425 #else /* !FEATURE_TELNETD_STANDALONE */
427 /* Used in main() only, thus "return 0" actually is exit(EXIT_SUCCESS). */
428 #define free_session(ts) return 0
432 static void handle_sigchld(int sig UNUSED_PARAM)
436 int save_errno = errno;
438 /* Looping: more than one child may have exited */
440 pid = wait_any_nohang(NULL);
445 if (ts->shell_pid == pid) {
448 // When init(8) finds that a process has exited, it locates its utmp entry
449 // by ut_pid, sets ut_type to DEAD_PROCESS, and clears ut_user, ut_host
450 // and ut_time with null bytes.
451 // [same applies to other processes which maintain utmp entries, like telnetd]
453 // We do not bother actually clearing fields:
454 // it might be interesting to know who was logged in and from where
455 update_utmp(pid, DEAD_PROCESS, /*tty_name:*/ NULL, /*username:*/ NULL, /*hostname:*/ NULL);
465 int telnetd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
466 int telnetd_main(int argc UNUSED_PARAM, char **argv)
468 fd_set rdfdset, wrfdset;
472 #if ENABLE_FEATURE_TELNETD_STANDALONE
473 #define IS_INETD (opt & OPT_INETD)
474 int master_fd = master_fd; /* for compiler */
475 int sec_linger = sec_linger;
476 char *opt_bindaddr = NULL;
486 /* -w NUM, and implies -F. -w and -i don't mix */
487 IF_FEATURE_TELNETD_INETD_WAIT(opt_complementary = "wF:w+:i--w:w--i";)
488 /* Even if !STANDALONE, we accept (and ignore) -i, thus people
489 * don't need to guess whether it's ok to pass -i to us */
490 opt = getopt32(argv, "f:l:Ki"
491 IF_FEATURE_TELNETD_STANDALONE("p:b:F")
492 IF_FEATURE_TELNETD_INETD_WAIT("Sw:"),
493 &G.issuefile, &G.loginpath
494 IF_FEATURE_TELNETD_STANDALONE(, &opt_portnbr, &opt_bindaddr)
495 IF_FEATURE_TELNETD_INETD_WAIT(, &sec_linger)
497 if (!IS_INETD /*&& !re_execed*/) {
498 /* inform that we start in standalone mode?
499 * May be useful when people forget to give -i */
500 /*bb_error_msg("listening for connections");*/
501 if (!(opt & OPT_FOREGROUND)) {
502 /* DAEMON_CHDIR_ROOT was giving inconsistent
503 * behavior with/without -F, -i */
504 bb_daemonize_or_rexec(0 /*was DAEMON_CHDIR_ROOT*/, argv);
507 /* Redirect log to syslog early, if needed */
508 if (IS_INETD || (opt & OPT_SYSLOG) || !(opt & OPT_FOREGROUND)) {
509 openlog(applet_name, LOG_PID, LOG_DAEMON);
510 logmode = LOGMODE_SYSLOG;
512 #if ENABLE_FEATURE_TELNETD_STANDALONE
514 G.sessions = make_new_session(0);
515 if (!G.sessions) /* pty opening or vfork problem, exit */
516 return 1; /* make_new_session printed error message */
519 if (!(opt & OPT_WAIT)) {
520 unsigned portnbr = 23;
522 portnbr = xatou16(opt_portnbr);
523 master_fd = create_and_bind_stream_or_die(opt_bindaddr, portnbr);
524 xlisten(master_fd, 1);
526 close_on_exec_on(master_fd);
529 G.sessions = make_new_session();
530 if (!G.sessions) /* pty opening or vfork problem, exit */
531 return 1; /* make_new_session printed error message */
534 /* We don't want to die if just one session is broken */
535 signal(SIGPIPE, SIG_IGN);
537 if (opt & OPT_WATCHCHILD)
538 signal(SIGCHLD, handle_sigchld);
539 else /* prevent dead children from becoming zombies */
540 signal(SIGCHLD, SIG_IGN);
543 This is how the buffers are used. The arrows indicate data flow.
545 +-------+ wridx1++ +------+ rdidx1++ +----------+
546 | | <-------------- | buf1 | <-------------- | |
547 | | size1-- +------+ size1++ | |
549 | | rdidx2++ +------+ wridx2++ | |
550 | | --------------> | buf2 | --------------> | |
551 +-------+ size2++ +------+ size2-- +----------+
553 size1: "how many bytes are buffered for pty between rdidx1 and wridx1?"
554 size2: "how many bytes are buffered for socket between rdidx2 and wridx2?"
556 Each session has got two buffers. Buffers are circular. If sizeN == 0,
557 buffer is empty. If sizeN == BUFSIZE, buffer is full. In both these cases
564 /* Select on the master socket, all telnet sockets and their
565 * ptys if there is room in their session buffers.
566 * NB: scalability problem: we recalculate entire bitmap
567 * before each select. Can be a problem with 500+ connections. */
570 struct tsession *next = ts->next; /* in case we free ts */
571 if (ts->shell_pid == -1) {
572 /* Child died and we detected that */
575 if (ts->size1 > 0) /* can write to pty */
576 FD_SET(ts->ptyfd, &wrfdset);
577 if (ts->size1 < BUFSIZE) /* can read from socket */
578 FD_SET(ts->sockfd_read, &rdfdset);
579 if (ts->size2 > 0) /* can write to socket */
580 FD_SET(ts->sockfd_write, &wrfdset);
581 if (ts->size2 < BUFSIZE) /* can read from pty */
582 FD_SET(ts->ptyfd, &rdfdset);
587 FD_SET(master_fd, &rdfdset);
588 /* This is needed because free_session() does not
589 * take master_fd into account when it finds new
590 * maxfd among remaining fd's */
591 if (master_fd > G.maxfd)
596 struct timeval *tv_ptr = NULL;
597 #if ENABLE_FEATURE_TELNETD_INETD_WAIT
599 if ((opt & OPT_WAIT) && !G.sessions) {
600 tv.tv_sec = sec_linger;
605 count = select(G.maxfd + 1, &rdfdset, &wrfdset, NULL, tv_ptr);
607 if (count == 0) /* "telnetd -w SEC" timed out */
610 goto again; /* EINTR or ENOMEM */
612 #if ENABLE_FEATURE_TELNETD_STANDALONE
613 /* Check for and accept new sessions */
614 if (!IS_INETD && FD_ISSET(master_fd, &rdfdset)) {
616 struct tsession *new_ts;
618 fd = accept(master_fd, NULL, NULL);
621 close_on_exec_on(fd);
623 /* Create a new session and link it into active list */
624 new_ts = make_new_session(fd);
626 new_ts->next = G.sessions;
634 /* Then check for data tunneling */
636 while (ts) { /* For all sessions... */
637 struct tsession *next = ts->next; /* in case we free ts */
639 if (/*ts->size1 &&*/ FD_ISSET(ts->ptyfd, &wrfdset)) {
642 /* Write to pty from buffer 1 */
643 ptr = remove_iacs(ts, &num_totty);
644 count = safe_write(ts->ptyfd, ptr, num_totty);
652 if (ts->wridx1 >= BUFSIZE) /* actually == BUFSIZE */
656 if (/*ts->size2 &&*/ FD_ISSET(ts->sockfd_write, &wrfdset)) {
657 /* Write to socket from buffer 2 */
658 count = MIN(BUFSIZE - ts->wridx2, ts->size2);
659 count = iac_safe_write(ts->sockfd_write, (void*)(TS_BUF2(ts) + ts->wridx2), count);
667 if (ts->wridx2 >= BUFSIZE) /* actually == BUFSIZE */
671 /* Should not be needed, but... remove_iacs is actually buggy
672 * (it cannot process iacs which wrap around buffer's end)!
673 * Since properly fixing it requires writing bigger code,
674 * we rely instead on this code making it virtually impossible
675 * to have wrapped iac (people don't type at 2k/second).
676 * It also allows for bigger reads in common case. */
677 if (ts->size1 == 0) {
681 if (ts->size2 == 0) {
686 if (/*ts->size1 < BUFSIZE &&*/ FD_ISSET(ts->sockfd_read, &rdfdset)) {
687 /* Read from socket to buffer 1 */
688 count = MIN(BUFSIZE - ts->rdidx1, BUFSIZE - ts->size1);
689 count = safe_read(ts->sockfd_read, TS_BUF1(ts) + ts->rdidx1, count);
691 if (count < 0 && errno == EAGAIN)
695 /* Ignore trailing NUL if it is there */
696 if (!TS_BUF1(ts)[ts->rdidx1 + count - 1]) {
701 if (ts->rdidx1 >= BUFSIZE) /* actually == BUFSIZE */
705 if (/*ts->size2 < BUFSIZE &&*/ FD_ISSET(ts->ptyfd, &rdfdset)) {
706 /* Read from pty to buffer 2 */
707 count = MIN(BUFSIZE - ts->rdidx2, BUFSIZE - ts->size2);
708 count = safe_read(ts->ptyfd, TS_BUF2(ts) + ts->rdidx2, count);
710 if (count < 0 && errno == EAGAIN)
716 if (ts->rdidx2 >= BUFSIZE) /* actually == BUFSIZE */
723 if (ts->shell_pid > 0)
724 update_utmp(ts->shell_pid, DEAD_PROCESS, /*tty_name:*/ NULL, /*username:*/ NULL, /*hostname:*/ NULL);