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)"
47 #include "common_bufsiz.h"
54 #include <arpa/telnet.h>
58 struct tsession
*next
;
64 /* two circular buffers */
65 /*char *buf1, *buf2;*/
66 /*#define TS_BUF1(ts) ts->buf1*/
67 /*#define TS_BUF2(ts) TS_BUF2(ts)*/
68 #define TS_BUF1(ts) ((unsigned char*)(ts + 1))
69 #define TS_BUF2(ts) (((unsigned char*)(ts + 1)) + BUFSIZE)
70 int rdidx1
, wridx1
, size1
;
71 int rdidx2
, wridx2
, size2
;
74 /* Two buffers are directly after tsession in malloced memory.
75 * Make whole thing fit in 4k */
76 enum { BUFSIZE
= (4 * 1024 - sizeof(struct tsession
)) / 2 };
81 struct tsession
*sessions
;
82 const char *loginpath
;
83 const char *issuefile
;
86 #define G (*(struct globals*)bb_common_bufsiz1)
87 #define INIT_G() do { \
88 setup_common_bufsiz(); \
89 G.loginpath = "/bin/login"; \
90 G.issuefile = "/etc/issue.net"; \
95 Remove all IAC's from buf1 (received IACs are ignored and must be removed
96 so as to not be interpreted by the terminal). Make an uninterrupted
97 string of characters fit for the terminal. Do this by packing
98 all characters meant for the terminal sequentially towards the end of buf.
100 Return a pointer to the beginning of the characters meant for the terminal
101 and make *num_totty the number of characters that should be sent to
104 Note - if an IAC (3 byte quantity) starts before (bf + len) but extends
105 past (bf + len) then that IAC will be left unprocessed and *processed
106 will be less than len.
108 CR-LF ->'s CR mapping is also done here, for convenience.
110 NB: may fail to remove iacs which wrap around buffer!
112 static unsigned char *
113 remove_iacs(struct tsession
*ts
, int *pnum_totty
)
115 unsigned char *ptr0
= TS_BUF1(ts
) + ts
->wridx1
;
116 unsigned char *ptr
= ptr0
;
117 unsigned char *totty
= ptr
;
118 unsigned char *end
= ptr
+ MIN(BUFSIZE
- ts
->wridx1
, ts
->size1
);
127 /* We map \r\n ==> \r for pragmatic reasons.
128 * Many client implementations send \r\n when
129 * the user hits the CarriageReturn key.
130 * See RFC 1123 3.3.1 Telnet End-of-Line Convention.
132 if (c
== '\r' && ptr
< end
&& (*ptr
== '\n' || *ptr
== '\0'))
139 if (ptr
[1] == NOP
) { /* Ignore? (putty keepalive, etc.) */
143 if (ptr
[1] == IAC
) { /* Literal IAC? (emacs M-DEL) */
150 * TELOPT_NAWS support!
152 if ((ptr
+2) >= end
) {
153 /* Only the beginning of the IAC is in the
154 buffer we were asked to process, we can't
159 * IAC -> SB -> TELOPT_NAWS -> 4-byte -> IAC -> SE
161 if (ptr
[1] == SB
&& ptr
[2] == TELOPT_NAWS
) {
164 break; /* incomplete, can't process */
165 ws
.ws_col
= (ptr
[3] << 8) | ptr
[4];
166 ws
.ws_row
= (ptr
[5] << 8) | ptr
[6];
167 ioctl(ts
->ptyfd
, TIOCSWINSZ
, (char *)&ws
);
171 /* skip 3-byte IAC non-SB cmd */
173 fprintf(stderr
, "Ignoring IAC %s,%s\n",
174 TELCMD(ptr
[1]), TELOPT(ptr
[2]));
179 num_totty
= totty
- ptr0
;
180 *pnum_totty
= num_totty
;
181 /* The difference between ptr and totty is number of iacs
182 we removed from the stream. Adjust buf1 accordingly */
183 if ((ptr
- totty
) == 0) /* 99.999% of cases */
185 ts
->wridx1
+= ptr
- totty
;
186 ts
->size1
-= ptr
- totty
;
187 /* Move chars meant for the terminal towards the end of the buffer */
188 return memmove(ptr
- num_totty
, ptr0
, num_totty
);
192 * Converting single IAC into double on output
194 static size_t iac_safe_write(int fd
, const char *buf
, size_t count
)
197 size_t wr
, rc
, total
;
203 if (*buf
== (char)IAC
) {
204 static const char IACIAC
[] ALIGN1
= { IAC
, IAC
};
205 rc
= safe_write(fd
, IACIAC
, 2);
213 /* count != 0, *buf != IAC */
214 IACptr
= memchr(buf
, IAC
, count
);
218 rc
= safe_write(fd
, buf
, wr
);
225 /* here: rc - result of last short write */
226 if ((ssize_t
)rc
< 0) { /* error? */
234 /* Must match getopt32 string */
236 OPT_WATCHCHILD
= (1 << 2), /* -K */
237 OPT_INETD
= (1 << 3) * ENABLE_FEATURE_TELNETD_STANDALONE
, /* -i */
238 OPT_PORT
= (1 << 4) * ENABLE_FEATURE_TELNETD_STANDALONE
, /* -p PORT */
239 OPT_FOREGROUND
= (1 << 6) * ENABLE_FEATURE_TELNETD_STANDALONE
, /* -F */
240 OPT_SYSLOG
= (1 << 7) * ENABLE_FEATURE_TELNETD_INETD_WAIT
, /* -S */
241 OPT_WAIT
= (1 << 8) * ENABLE_FEATURE_TELNETD_INETD_WAIT
, /* -w SEC */
244 static struct tsession
*
246 IF_FEATURE_TELNETD_STANDALONE(int sock
)
247 IF_NOT_FEATURE_TELNETD_STANDALONE(void)
249 #if !ENABLE_FEATURE_TELNETD_STANDALONE
252 const char *login_argv
[2];
253 struct termios termbuf
;
255 char tty_name
[GETPTY_BUFSIZE
];
256 struct tsession
*ts
= xzalloc(sizeof(struct tsession
) + BUFSIZE
* 2);
258 /*ts->buf1 = (char *)(ts + 1);*/
259 /*ts->buf2 = ts->buf1 + BUFSIZE;*/
261 /* Got a new connection, set up a tty */
262 fd
= xgetpty(tty_name
);
267 close_on_exec_on(fd
);
269 /* SO_KEEPALIVE by popular demand */
270 setsockopt_keepalive(sock
);
271 #if ENABLE_FEATURE_TELNETD_STANDALONE
272 ts
->sockfd_read
= sock
;
274 if (sock
== 0) { /* We are called with fd 0 - we are in inetd mode */
275 sock
++; /* so use fd 1 for output */
278 ts
->sockfd_write
= sock
;
282 /* ts->sockfd_read = 0; - done by xzalloc */
283 ts
->sockfd_write
= 1;
288 /* Make the telnet client understand we will echo characters so it
289 * should not do it locally. We don't tell the client to run linemode,
290 * because we want to handle line editing and tab completion and other
291 * stuff that requires char-by-char support. */
293 static const char iacs_to_send
[] ALIGN1
= {
294 IAC
, DO
, TELOPT_ECHO
,
295 IAC
, DO
, TELOPT_NAWS
,
296 /* This requires telnetd.ctrlSQ.patch (incomplete) */
297 /*IAC, DO, TELOPT_LFLOW,*/
298 IAC
, WILL
, TELOPT_ECHO
,
299 IAC
, WILL
, TELOPT_SGA
301 /* This confuses iac_safe_write(), it will try to duplicate
303 //memcpy(TS_BUF2(ts), iacs_to_send, sizeof(iacs_to_send));
304 //ts->rdidx2 = sizeof(iacs_to_send);
305 //ts->size2 = sizeof(iacs_to_send);
306 /* So just stuff it into TCP stream! (no error check...) */
307 #if ENABLE_FEATURE_TELNETD_STANDALONE
308 safe_write(sock
, iacs_to_send
, sizeof(iacs_to_send
));
310 safe_write(1, iacs_to_send
, sizeof(iacs_to_send
));
312 /*ts->rdidx2 = 0; - xzalloc did it */
317 pid
= vfork(); /* NOMMU-friendly */
321 /* sock will be closed by caller */
322 bb_perror_msg("vfork");
332 /* Careful - we are after vfork! */
334 /* Restore default signal handling ASAP */
335 bb_signals((1 << SIGCHLD
) + (1 << SIGPIPE
), SIG_DFL
);
336 signal(SIGINT
, SIG_DFL
);
340 if (ENABLE_FEATURE_UTMP
) {
341 len_and_sockaddr
*lsa
= get_peer_lsa(sock
);
342 char *hostname
= NULL
;
344 hostname
= xmalloc_sockaddr2dotted(&lsa
->u
.sa
);
347 write_new_utmp(pid
, LOGIN_PROCESS
, tty_name
, /*username:*/ "LOGIN", hostname
);
351 /* Make new session and process group */
354 /* Open the child's side of the tty */
355 /* NB: setsid() disconnects from any previous ctty's. Therefore
356 * we must open child's side of the tty AFTER setsid! */
358 xopen(tty_name
, O_RDWR
); /* becomes our ctty */
361 tcsetpgrp(0, pid
); /* switch this tty's process group to us */
363 /* The pseudo-terminal allocated to the client is configured to operate
364 * in cooked mode, and with XTABS CRMOD enabled (see tty(4)) */
365 tcgetattr(0, &termbuf
);
366 termbuf
.c_lflag
|= ECHO
; /* if we use readline we dont want this */
367 termbuf
.c_oflag
|= ONLCR
| XTABS
;
368 termbuf
.c_iflag
|= ICRNL
;
369 termbuf
.c_iflag
&= ~IXOFF
;
370 /*termbuf.c_lflag &= ~ICANON;*/
371 tcsetattr_stdin_TCSANOW(&termbuf
);
373 /* Uses FILE-based I/O to stdout, but does fflush_all(),
374 * so should be safe with vfork.
375 * I fear, though, that some users will have ridiculously big
376 * issue files, and they may block writing to fd 1,
377 * (parent is supposed to read it, but parent waits
378 * for vforked child to exec!) */
379 print_login_issue(G
.issuefile
, tty_name
);
381 /* Exec shell / login / whatever */
382 login_argv
[0] = G
.loginpath
;
383 login_argv
[1] = NULL
;
384 /* exec busybox applet (if PREFER_APPLETS=y), if that fails,
385 * exec external program.
386 * NB: sock is either 0 or has CLOEXEC set on it.
387 * fd has CLOEXEC set on it too. These two fds will be closed here.
389 BB_EXECVP(G
.loginpath
, (char **)login_argv
);
390 /* _exit is safer with vfork, and we shouldn't send message
391 * to remote clients anyway */
392 _exit(EXIT_FAILURE
); /*bb_perror_msg_and_die("execv %s", G.loginpath);*/
395 #if ENABLE_FEATURE_TELNETD_STANDALONE
398 free_session(struct tsession
*ts
)
402 if (option_mask32
& OPT_INETD
)
405 /* Unlink this telnet session from the session list */
408 G
.sessions
= ts
->next
;
410 while (t
->next
!= ts
)
416 /* It was said that "normal" telnetd just closes ptyfd,
417 * doesn't send SIGKILL. When we close ptyfd,
418 * kernel sends SIGHUP to processes having slave side opened. */
419 kill(ts
->shell_pid
, SIGKILL
);
420 waitpid(ts
->shell_pid
, NULL
, 0);
423 close(ts
->sockfd_read
);
424 /* We do not need to close(ts->sockfd_write), it's the same
425 * as sockfd_read unless we are in inetd mode. But in inetd mode
426 * we do not reach this */
429 /* Scan all sessions and find new maxfd */
433 if (G
.maxfd
< ts
->ptyfd
)
435 if (G
.maxfd
< ts
->sockfd_read
)
436 G
.maxfd
= ts
->sockfd_read
;
438 /* Again, sockfd_write == sockfd_read here */
439 if (G
.maxfd
< ts
->sockfd_write
)
440 G
.maxfd
= ts
->sockfd_write
;
446 #else /* !FEATURE_TELNETD_STANDALONE */
448 /* Used in main() only, thus "return 0" actually is exit(EXIT_SUCCESS). */
449 #define free_session(ts) return 0
453 static void handle_sigchld(int sig UNUSED_PARAM
)
457 int save_errno
= errno
;
459 /* Looping: more than one child may have exited */
461 pid
= wait_any_nohang(NULL
);
466 if (ts
->shell_pid
== pid
) {
468 update_utmp_DEAD_PROCESS(pid
);
478 int telnetd_main(int argc
, char **argv
) MAIN_EXTERNALLY_VISIBLE
;
479 int telnetd_main(int argc UNUSED_PARAM
, char **argv
)
481 fd_set rdfdset
, wrfdset
;
485 #if ENABLE_FEATURE_TELNETD_STANDALONE
486 #define IS_INETD (opt & OPT_INETD)
487 int master_fd
= master_fd
; /* for compiler */
488 int sec_linger
= sec_linger
;
489 char *opt_bindaddr
= NULL
;
499 /* -w NUM, and implies -F. -w and -i don't mix */
500 IF_FEATURE_TELNETD_INETD_WAIT(opt_complementary
= "wF:w+:i--w:w--i";)
501 /* Even if !STANDALONE, we accept (and ignore) -i, thus people
502 * don't need to guess whether it's ok to pass -i to us */
503 opt
= getopt32(argv
, "f:l:Ki"
504 IF_FEATURE_TELNETD_STANDALONE("p:b:F")
505 IF_FEATURE_TELNETD_INETD_WAIT("Sw:"),
506 &G
.issuefile
, &G
.loginpath
507 IF_FEATURE_TELNETD_STANDALONE(, &opt_portnbr
, &opt_bindaddr
)
508 IF_FEATURE_TELNETD_INETD_WAIT(, &sec_linger
)
510 if (!IS_INETD
/*&& !re_execed*/) {
511 /* inform that we start in standalone mode?
512 * May be useful when people forget to give -i */
513 /*bb_error_msg("listening for connections");*/
514 if (!(opt
& OPT_FOREGROUND
)) {
515 /* DAEMON_CHDIR_ROOT was giving inconsistent
516 * behavior with/without -F, -i */
517 bb_daemonize_or_rexec(0 /*was DAEMON_CHDIR_ROOT*/, argv
);
520 /* Redirect log to syslog early, if needed */
521 if (IS_INETD
|| (opt
& OPT_SYSLOG
) || !(opt
& OPT_FOREGROUND
)) {
522 openlog(applet_name
, LOG_PID
, LOG_DAEMON
);
523 logmode
= LOGMODE_SYSLOG
;
525 #if ENABLE_FEATURE_TELNETD_STANDALONE
527 G
.sessions
= make_new_session(0);
528 if (!G
.sessions
) /* pty opening or vfork problem, exit */
529 return 1; /* make_new_session printed error message */
532 if (!(opt
& OPT_WAIT
)) {
533 unsigned portnbr
= 23;
535 portnbr
= xatou16(opt_portnbr
);
536 master_fd
= create_and_bind_stream_or_die(opt_bindaddr
, portnbr
);
537 xlisten(master_fd
, 1);
539 close_on_exec_on(master_fd
);
542 G
.sessions
= make_new_session();
543 if (!G
.sessions
) /* pty opening or vfork problem, exit */
544 return 1; /* make_new_session printed error message */
547 /* We don't want to die if just one session is broken */
548 signal(SIGPIPE
, SIG_IGN
);
550 if (opt
& OPT_WATCHCHILD
)
551 signal(SIGCHLD
, handle_sigchld
);
552 else /* prevent dead children from becoming zombies */
553 signal(SIGCHLD
, SIG_IGN
);
556 This is how the buffers are used. The arrows indicate data flow.
558 +-------+ wridx1++ +------+ rdidx1++ +----------+
559 | | <-------------- | buf1 | <-------------- | |
560 | | size1-- +------+ size1++ | |
562 | | rdidx2++ +------+ wridx2++ | |
563 | | --------------> | buf2 | --------------> | |
564 +-------+ size2++ +------+ size2-- +----------+
566 size1: "how many bytes are buffered for pty between rdidx1 and wridx1?"
567 size2: "how many bytes are buffered for socket between rdidx2 and wridx2?"
569 Each session has got two buffers. Buffers are circular. If sizeN == 0,
570 buffer is empty. If sizeN == BUFSIZE, buffer is full. In both these cases
577 /* Select on the master socket, all telnet sockets and their
578 * ptys if there is room in their session buffers.
579 * NB: scalability problem: we recalculate entire bitmap
580 * before each select. Can be a problem with 500+ connections. */
583 struct tsession
*next
= ts
->next
; /* in case we free ts */
584 if (ts
->shell_pid
== -1) {
585 /* Child died and we detected that */
588 if (ts
->size1
> 0) /* can write to pty */
589 FD_SET(ts
->ptyfd
, &wrfdset
);
590 if (ts
->size1
< BUFSIZE
) /* can read from socket */
591 FD_SET(ts
->sockfd_read
, &rdfdset
);
592 if (ts
->size2
> 0) /* can write to socket */
593 FD_SET(ts
->sockfd_write
, &wrfdset
);
594 if (ts
->size2
< BUFSIZE
) /* can read from pty */
595 FD_SET(ts
->ptyfd
, &rdfdset
);
600 FD_SET(master_fd
, &rdfdset
);
601 /* This is needed because free_session() does not
602 * take master_fd into account when it finds new
603 * maxfd among remaining fd's */
604 if (master_fd
> G
.maxfd
)
609 struct timeval
*tv_ptr
= NULL
;
610 #if ENABLE_FEATURE_TELNETD_INETD_WAIT
612 if ((opt
& OPT_WAIT
) && !G
.sessions
) {
613 tv
.tv_sec
= sec_linger
;
618 count
= select(G
.maxfd
+ 1, &rdfdset
, &wrfdset
, NULL
, tv_ptr
);
620 if (count
== 0) /* "telnetd -w SEC" timed out */
623 goto again
; /* EINTR or ENOMEM */
625 #if ENABLE_FEATURE_TELNETD_STANDALONE
626 /* Check for and accept new sessions */
627 if (!IS_INETD
&& FD_ISSET(master_fd
, &rdfdset
)) {
629 struct tsession
*new_ts
;
631 fd
= accept(master_fd
, NULL
, NULL
);
634 close_on_exec_on(fd
);
636 /* Create a new session and link it into active list */
637 new_ts
= make_new_session(fd
);
639 new_ts
->next
= G
.sessions
;
647 /* Then check for data tunneling */
649 while (ts
) { /* For all sessions... */
650 struct tsession
*next
= ts
->next
; /* in case we free ts */
652 if (/*ts->size1 &&*/ FD_ISSET(ts
->ptyfd
, &wrfdset
)) {
655 /* Write to pty from buffer 1 */
656 ptr
= remove_iacs(ts
, &num_totty
);
657 count
= safe_write(ts
->ptyfd
, ptr
, num_totty
);
665 if (ts
->wridx1
>= BUFSIZE
) /* actually == BUFSIZE */
669 if (/*ts->size2 &&*/ FD_ISSET(ts
->sockfd_write
, &wrfdset
)) {
670 /* Write to socket from buffer 2 */
671 count
= MIN(BUFSIZE
- ts
->wridx2
, ts
->size2
);
672 count
= iac_safe_write(ts
->sockfd_write
, (void*)(TS_BUF2(ts
) + ts
->wridx2
), count
);
680 if (ts
->wridx2
>= BUFSIZE
) /* actually == BUFSIZE */
684 /* Should not be needed, but... remove_iacs is actually buggy
685 * (it cannot process iacs which wrap around buffer's end)!
686 * Since properly fixing it requires writing bigger code,
687 * we rely instead on this code making it virtually impossible
688 * to have wrapped iac (people don't type at 2k/second).
689 * It also allows for bigger reads in common case. */
690 if (ts
->size1
== 0) {
694 if (ts
->size2
== 0) {
699 if (/*ts->size1 < BUFSIZE &&*/ FD_ISSET(ts
->sockfd_read
, &rdfdset
)) {
700 /* Read from socket to buffer 1 */
701 count
= MIN(BUFSIZE
- ts
->rdidx1
, BUFSIZE
- ts
->size1
);
702 count
= safe_read(ts
->sockfd_read
, TS_BUF1(ts
) + ts
->rdidx1
, count
);
704 if (count
< 0 && errno
== EAGAIN
)
708 /* Ignore trailing NUL if it is there */
709 if (!TS_BUF1(ts
)[ts
->rdidx1
+ count
- 1]) {
714 if (ts
->rdidx1
>= BUFSIZE
) /* actually == BUFSIZE */
718 if (/*ts->size2 < BUFSIZE &&*/ FD_ISSET(ts
->ptyfd
, &rdfdset
)) {
719 /* Read from pty to buffer 2 */
720 count
= MIN(BUFSIZE
- ts
->rdidx2
, BUFSIZE
- ts
->size2
);
721 count
= safe_read(ts
->ptyfd
, TS_BUF2(ts
) + ts
->rdidx2
, count
);
723 if (count
< 0 && errno
== EAGAIN
)
729 if (ts
->rdidx2
>= BUFSIZE
) /* actually == BUFSIZE */
736 if (ts
->shell_pid
> 0)
737 update_utmp_DEAD_PROCESS(ts
->shell_pid
);