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>
36 struct tsession *next;
42 /* two circular buffers */
43 /*char *buf1, *buf2;*/
44 /*#define TS_BUF1(ts) ts->buf1*/
45 /*#define TS_BUF2(ts) TS_BUF2(ts)*/
46 #define TS_BUF1(ts) ((unsigned char*)(ts + 1))
47 #define TS_BUF2(ts) (((unsigned char*)(ts + 1)) + BUFSIZE)
48 int rdidx1, wridx1, size1;
49 int rdidx2, wridx2, size2;
52 /* Two buffers are directly after tsession in malloced memory.
53 * Make whole thing fit in 4k */
54 enum { BUFSIZE = (4 * 1024 - sizeof(struct tsession)) / 2 };
59 struct tsession *sessions;
60 const char *loginpath;
61 const char *issuefile;
64 #define G (*(struct globals*)&bb_common_bufsiz1)
65 #define INIT_G() do { \
66 G.loginpath = "/bin/login"; \
67 G.issuefile = "/etc/issue.net"; \
72 Remove all IAC's from buf1 (received IACs are ignored and must be removed
73 so as to not be interpreted by the terminal). Make an uninterrupted
74 string of characters fit for the terminal. Do this by packing
75 all characters meant for the terminal sequentially towards the end of buf.
77 Return a pointer to the beginning of the characters meant for the terminal
78 and make *num_totty the number of characters that should be sent to
81 Note - if an IAC (3 byte quantity) starts before (bf + len) but extends
82 past (bf + len) then that IAC will be left unprocessed and *processed
83 will be less than len.
85 CR-LF ->'s CR mapping is also done here, for convenience.
87 NB: may fail to remove iacs which wrap around buffer!
89 static unsigned char *
90 remove_iacs(struct tsession *ts, int *pnum_totty)
92 unsigned char *ptr0 = TS_BUF1(ts) + ts->wridx1;
93 unsigned char *ptr = ptr0;
94 unsigned char *totty = ptr;
95 unsigned char *end = ptr + MIN(BUFSIZE - ts->wridx1, ts->size1);
104 /* We map \r\n ==> \r for pragmatic reasons.
105 * Many client implementations send \r\n when
106 * the user hits the CarriageReturn key.
108 if (c == '\r' && ptr < end && (*ptr == '\n' || *ptr == '\0'))
115 if (ptr[1] == NOP) { /* Ignore? (putty keepalive, etc.) */
119 if (ptr[1] == IAC) { /* Literal IAC? (emacs M-DEL) */
126 * TELOPT_NAWS support!
128 if ((ptr+2) >= end) {
129 /* Only the beginning of the IAC is in the
130 buffer we were asked to process, we can't
135 * IAC -> SB -> TELOPT_NAWS -> 4-byte -> IAC -> SE
137 if (ptr[1] == SB && ptr[2] == TELOPT_NAWS) {
140 break; /* incomplete, can't process */
141 ws.ws_col = (ptr[3] << 8) | ptr[4];
142 ws.ws_row = (ptr[5] << 8) | ptr[6];
143 ioctl(ts->ptyfd, TIOCSWINSZ, (char *)&ws);
147 /* skip 3-byte IAC non-SB cmd */
149 fprintf(stderr, "Ignoring IAC %s,%s\n",
150 TELCMD(ptr[1]), TELOPT(ptr[2]));
155 num_totty = totty - ptr0;
156 *pnum_totty = num_totty;
157 /* The difference between ptr and totty is number of iacs
158 we removed from the stream. Adjust buf1 accordingly */
159 if ((ptr - totty) == 0) /* 99.999% of cases */
161 ts->wridx1 += ptr - totty;
162 ts->size1 -= ptr - totty;
163 /* Move chars meant for the terminal towards the end of the buffer */
164 return memmove(ptr - num_totty, ptr0, num_totty);
168 * Converting single IAC into double on output
170 static size_t iac_safe_write(int fd, const char *buf, size_t count)
173 size_t wr, rc, total;
179 if (*buf == (char)IAC) {
180 static const char IACIAC[] ALIGN1 = { IAC, IAC };
181 rc = safe_write(fd, IACIAC, 2);
189 /* count != 0, *buf != IAC */
190 IACptr = memchr(buf, IAC, count);
194 rc = safe_write(fd, buf, wr);
201 /* here: rc - result of last short write */
202 if ((ssize_t)rc < 0) { /* error? */
210 /* Must match getopt32 string */
212 OPT_WATCHCHILD = (1 << 2), /* -K */
213 OPT_INETD = (1 << 3) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -i */
214 OPT_PORT = (1 << 4) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -p PORT */
215 OPT_FOREGROUND = (1 << 6) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -F */
216 OPT_SYSLOG = (1 << 7) * ENABLE_FEATURE_TELNETD_INETD_WAIT, /* -S */
217 OPT_WAIT = (1 << 8) * ENABLE_FEATURE_TELNETD_INETD_WAIT, /* -w SEC */
220 static struct tsession *
222 IF_FEATURE_TELNETD_STANDALONE(int sock)
223 IF_NOT_FEATURE_TELNETD_STANDALONE(void)
225 #if !ENABLE_FEATURE_TELNETD_STANDALONE
228 const char *login_argv[2];
229 struct termios termbuf;
231 char tty_name[GETPTY_BUFSIZE];
232 struct tsession *ts = xzalloc(sizeof(struct tsession) + BUFSIZE * 2);
234 /*ts->buf1 = (char *)(ts + 1);*/
235 /*ts->buf2 = ts->buf1 + BUFSIZE;*/
237 /* Got a new connection, set up a tty */
238 fd = xgetpty(tty_name);
243 close_on_exec_on(fd);
245 /* SO_KEEPALIVE by popular demand */
246 setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1));
247 #if ENABLE_FEATURE_TELNETD_STANDALONE
248 ts->sockfd_read = sock;
250 if (sock == 0) { /* We are called with fd 0 - we are in inetd mode */
251 sock++; /* so use fd 1 for output */
254 ts->sockfd_write = sock;
258 /* ts->sockfd_read = 0; - done by xzalloc */
259 ts->sockfd_write = 1;
264 /* Make the telnet client understand we will echo characters so it
265 * should not do it locally. We don't tell the client to run linemode,
266 * because we want to handle line editing and tab completion and other
267 * stuff that requires char-by-char support. */
269 static const char iacs_to_send[] ALIGN1 = {
270 IAC, DO, TELOPT_ECHO,
271 IAC, DO, TELOPT_NAWS,
272 /* This requires telnetd.ctrlSQ.patch (incomplete) */
273 /*IAC, DO, TELOPT_LFLOW,*/
274 IAC, WILL, TELOPT_ECHO,
275 IAC, WILL, TELOPT_SGA
277 /* This confuses iac_safe_write(), it will try to duplicate
279 //memcpy(TS_BUF2(ts), iacs_to_send, sizeof(iacs_to_send));
280 //ts->rdidx2 = sizeof(iacs_to_send);
281 //ts->size2 = sizeof(iacs_to_send);
282 /* So just stuff it into TCP stream! (no error check...) */
283 #if ENABLE_FEATURE_TELNETD_STANDALONE
284 safe_write(sock, iacs_to_send, sizeof(iacs_to_send));
286 safe_write(1, iacs_to_send, sizeof(iacs_to_send));
288 /*ts->rdidx2 = 0; - xzalloc did it */
293 pid = vfork(); /* NOMMU-friendly */
297 /* sock will be closed by caller */
298 bb_perror_msg("vfork");
308 /* Careful - we are after vfork! */
310 /* Restore default signal handling ASAP */
311 bb_signals((1 << SIGCHLD) + (1 << SIGPIPE), SIG_DFL);
315 if (ENABLE_FEATURE_UTMP) {
316 len_and_sockaddr *lsa = get_peer_lsa(sock);
317 char *hostname = NULL;
319 hostname = xmalloc_sockaddr2dotted(&lsa->u.sa);
322 write_new_utmp(pid, LOGIN_PROCESS, tty_name, /*username:*/ "LOGIN", hostname);
326 /* Make new session and process group */
329 /* Open the child's side of the tty */
330 /* NB: setsid() disconnects from any previous ctty's. Therefore
331 * we must open child's side of the tty AFTER setsid! */
333 xopen(tty_name, O_RDWR); /* becomes our ctty */
336 tcsetpgrp(0, pid); /* switch this tty's process group to us */
338 /* The pseudo-terminal allocated to the client is configured to operate
339 * in cooked mode, and with XTABS CRMOD enabled (see tty(4)) */
340 tcgetattr(0, &termbuf);
341 termbuf.c_lflag |= ECHO; /* if we use readline we dont want this */
342 termbuf.c_oflag |= ONLCR | XTABS;
343 termbuf.c_iflag |= ICRNL;
344 termbuf.c_iflag &= ~IXOFF;
345 /*termbuf.c_lflag &= ~ICANON;*/
346 tcsetattr_stdin_TCSANOW(&termbuf);
348 /* Uses FILE-based I/O to stdout, but does fflush_all(),
349 * so should be safe with vfork.
350 * I fear, though, that some users will have ridiculously big
351 * issue files, and they may block writing to fd 1,
352 * (parent is supposed to read it, but parent waits
353 * for vforked child to exec!) */
354 print_login_issue(G.issuefile, tty_name);
356 /* Exec shell / login / whatever */
357 login_argv[0] = G.loginpath;
358 login_argv[1] = NULL;
359 /* exec busybox applet (if PREFER_APPLETS=y), if that fails,
360 * exec external program.
361 * NB: sock is either 0 or has CLOEXEC set on it.
362 * fd has CLOEXEC set on it too. These two fds will be closed here.
364 BB_EXECVP(G.loginpath, (char **)login_argv);
365 /* _exit is safer with vfork, and we shouldn't send message
366 * to remote clients anyway */
367 _exit(EXIT_FAILURE); /*bb_perror_msg_and_die("execv %s", G.loginpath);*/
370 #if ENABLE_FEATURE_TELNETD_STANDALONE
373 free_session(struct tsession *ts)
377 if (option_mask32 & OPT_INETD)
380 /* Unlink this telnet session from the session list */
383 G.sessions = ts->next;
385 while (t->next != ts)
391 /* It was said that "normal" telnetd just closes ptyfd,
392 * doesn't send SIGKILL. When we close ptyfd,
393 * kernel sends SIGHUP to processes having slave side opened. */
394 kill(ts->shell_pid, SIGKILL);
395 waitpid(ts->shell_pid, NULL, 0);
398 close(ts->sockfd_read);
399 /* We do not need to close(ts->sockfd_write), it's the same
400 * as sockfd_read unless we are in inetd mode. But in inetd mode
401 * we do not reach this */
404 /* Scan all sessions and find new maxfd */
408 if (G.maxfd < ts->ptyfd)
410 if (G.maxfd < ts->sockfd_read)
411 G.maxfd = ts->sockfd_read;
413 /* Again, sockfd_write == sockfd_read here */
414 if (G.maxfd < ts->sockfd_write)
415 G.maxfd = ts->sockfd_write;
421 #else /* !FEATURE_TELNETD_STANDALONE */
423 /* Used in main() only, thus "return 0" actually is exit(EXIT_SUCCESS). */
424 #define free_session(ts) return 0
428 static void handle_sigchld(int sig UNUSED_PARAM)
432 int save_errno = errno;
434 /* Looping: more than one child may have exited */
436 pid = wait_any_nohang(NULL);
441 if (ts->shell_pid == pid) {
444 // When init(8) finds that a process has exited, it locates its utmp entry
445 // by ut_pid, sets ut_type to DEAD_PROCESS, and clears ut_user, ut_host
446 // and ut_time with null bytes.
447 // [same applies to other processes which maintain utmp entries, like telnetd]
449 // We do not bother actually clearing fields:
450 // it might be interesting to know who was logged in and from where
451 update_utmp(pid, DEAD_PROCESS, /*tty_name:*/ NULL, /*username:*/ NULL, /*hostname:*/ NULL);
461 int telnetd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
462 int telnetd_main(int argc UNUSED_PARAM, char **argv)
464 fd_set rdfdset, wrfdset;
468 #if ENABLE_FEATURE_TELNETD_STANDALONE
469 #define IS_INETD (opt & OPT_INETD)
470 int master_fd = master_fd; /* for compiler */
471 int sec_linger = sec_linger;
472 char *opt_bindaddr = NULL;
482 /* -w NUM, and implies -F. -w and -i don't mix */
483 IF_FEATURE_TELNETD_INETD_WAIT(opt_complementary = "wF:w+:i--w:w--i";)
484 /* Even if !STANDALONE, we accept (and ignore) -i, thus people
485 * don't need to guess whether it's ok to pass -i to us */
486 opt = getopt32(argv, "f:l:Ki"
487 IF_FEATURE_TELNETD_STANDALONE("p:b:F")
488 IF_FEATURE_TELNETD_INETD_WAIT("Sw:"),
489 &G.issuefile, &G.loginpath
490 IF_FEATURE_TELNETD_STANDALONE(, &opt_portnbr, &opt_bindaddr)
491 IF_FEATURE_TELNETD_INETD_WAIT(, &sec_linger)
493 if (!IS_INETD /*&& !re_execed*/) {
494 /* inform that we start in standalone mode?
495 * May be useful when people forget to give -i */
496 /*bb_error_msg("listening for connections");*/
497 if (!(opt & OPT_FOREGROUND)) {
498 /* DAEMON_CHDIR_ROOT was giving inconsistent
499 * behavior with/without -F, -i */
500 bb_daemonize_or_rexec(0 /*was DAEMON_CHDIR_ROOT*/, argv);
503 /* Redirect log to syslog early, if needed */
504 if (IS_INETD || (opt & OPT_SYSLOG) || !(opt & OPT_FOREGROUND)) {
505 openlog(applet_name, LOG_PID, LOG_DAEMON);
506 logmode = LOGMODE_SYSLOG;
508 #if ENABLE_FEATURE_TELNETD_STANDALONE
510 G.sessions = make_new_session(0);
511 if (!G.sessions) /* pty opening or vfork problem, exit */
512 return 1; /* make_new_session printed error message */
515 if (!(opt & OPT_WAIT)) {
516 unsigned portnbr = 23;
518 portnbr = xatou16(opt_portnbr);
519 master_fd = create_and_bind_stream_or_die(opt_bindaddr, portnbr);
520 xlisten(master_fd, 1);
522 close_on_exec_on(master_fd);
525 G.sessions = make_new_session();
526 if (!G.sessions) /* pty opening or vfork problem, exit */
527 return 1; /* make_new_session printed error message */
530 /* We don't want to die if just one session is broken */
531 signal(SIGPIPE, SIG_IGN);
533 if (opt & OPT_WATCHCHILD)
534 signal(SIGCHLD, handle_sigchld);
535 else /* prevent dead children from becoming zombies */
536 signal(SIGCHLD, SIG_IGN);
539 This is how the buffers are used. The arrows indicate data flow.
541 +-------+ wridx1++ +------+ rdidx1++ +----------+
542 | | <-------------- | buf1 | <-------------- | |
543 | | size1-- +------+ size1++ | |
545 | | rdidx2++ +------+ wridx2++ | |
546 | | --------------> | buf2 | --------------> | |
547 +-------+ size2++ +------+ size2-- +----------+
549 size1: "how many bytes are buffered for pty between rdidx1 and wridx1?"
550 size2: "how many bytes are buffered for socket between rdidx2 and wridx2?"
552 Each session has got two buffers. Buffers are circular. If sizeN == 0,
553 buffer is empty. If sizeN == BUFSIZE, buffer is full. In both these cases
560 /* Select on the master socket, all telnet sockets and their
561 * ptys if there is room in their session buffers.
562 * NB: scalability problem: we recalculate entire bitmap
563 * before each select. Can be a problem with 500+ connections. */
566 struct tsession *next = ts->next; /* in case we free ts */
567 if (ts->shell_pid == -1) {
568 /* Child died and we detected that */
571 if (ts->size1 > 0) /* can write to pty */
572 FD_SET(ts->ptyfd, &wrfdset);
573 if (ts->size1 < BUFSIZE) /* can read from socket */
574 FD_SET(ts->sockfd_read, &rdfdset);
575 if (ts->size2 > 0) /* can write to socket */
576 FD_SET(ts->sockfd_write, &wrfdset);
577 if (ts->size2 < BUFSIZE) /* can read from pty */
578 FD_SET(ts->ptyfd, &rdfdset);
583 FD_SET(master_fd, &rdfdset);
584 /* This is needed because free_session() does not
585 * take master_fd into account when it finds new
586 * maxfd among remaining fd's */
587 if (master_fd > G.maxfd)
592 struct timeval *tv_ptr = NULL;
593 #if ENABLE_FEATURE_TELNETD_INETD_WAIT
595 if ((opt & OPT_WAIT) && !G.sessions) {
596 tv.tv_sec = sec_linger;
601 count = select(G.maxfd + 1, &rdfdset, &wrfdset, NULL, tv_ptr);
603 if (count == 0) /* "telnetd -w SEC" timed out */
606 goto again; /* EINTR or ENOMEM */
608 #if ENABLE_FEATURE_TELNETD_STANDALONE
609 /* Check for and accept new sessions */
610 if (!IS_INETD && FD_ISSET(master_fd, &rdfdset)) {
612 struct tsession *new_ts;
614 fd = accept(master_fd, NULL, NULL);
617 close_on_exec_on(fd);
619 /* Create a new session and link it into active list */
620 new_ts = make_new_session(fd);
622 new_ts->next = G.sessions;
630 /* Then check for data tunneling */
632 while (ts) { /* For all sessions... */
633 struct tsession *next = ts->next; /* in case we free ts */
635 if (/*ts->size1 &&*/ FD_ISSET(ts->ptyfd, &wrfdset)) {
638 /* Write to pty from buffer 1 */
639 ptr = remove_iacs(ts, &num_totty);
640 count = safe_write(ts->ptyfd, ptr, num_totty);
648 if (ts->wridx1 >= BUFSIZE) /* actually == BUFSIZE */
652 if (/*ts->size2 &&*/ FD_ISSET(ts->sockfd_write, &wrfdset)) {
653 /* Write to socket from buffer 2 */
654 count = MIN(BUFSIZE - ts->wridx2, ts->size2);
655 count = iac_safe_write(ts->sockfd_write, (void*)(TS_BUF2(ts) + ts->wridx2), count);
663 if (ts->wridx2 >= BUFSIZE) /* actually == BUFSIZE */
667 /* Should not be needed, but... remove_iacs is actually buggy
668 * (it cannot process iacs which wrap around buffer's end)!
669 * Since properly fixing it requires writing bigger code,
670 * we rely instead on this code making it virtually impossible
671 * to have wrapped iac (people don't type at 2k/second).
672 * It also allows for bigger reads in common case. */
673 if (ts->size1 == 0) {
677 if (ts->size2 == 0) {
682 if (/*ts->size1 < BUFSIZE &&*/ FD_ISSET(ts->sockfd_read, &rdfdset)) {
683 /* Read from socket to buffer 1 */
684 count = MIN(BUFSIZE - ts->rdidx1, BUFSIZE - ts->size1);
685 count = safe_read(ts->sockfd_read, TS_BUF1(ts) + ts->rdidx1, count);
687 if (count < 0 && errno == EAGAIN)
691 /* Ignore trailing NUL if it is there */
692 if (!TS_BUF1(ts)[ts->rdidx1 + count - 1]) {
697 if (ts->rdidx1 >= BUFSIZE) /* actually == BUFSIZE */
701 if (/*ts->size2 < BUFSIZE &&*/ FD_ISSET(ts->ptyfd, &rdfdset)) {
702 /* Read from pty to buffer 2 */
703 count = MIN(BUFSIZE - ts->rdidx2, BUFSIZE - ts->size2);
704 count = safe_read(ts->ptyfd, TS_BUF2(ts) + ts->rdidx2, count);
706 if (count < 0 && errno == EAGAIN)
712 if (ts->rdidx2 >= BUFSIZE) /* actually == BUFSIZE */
719 if (ts->shell_pid > 0)
720 update_utmp(ts->shell_pid, DEAD_PROCESS, /*tty_name:*/ NULL, /*username:*/ NULL, /*hostname:*/ NULL);