2 * Copyright (c) 1983, 1988, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * remote login server:
39 * terminal_type/speed\0
45 RCSID("$Id: rlogind.c,v 1.109 1999/11/25 05:27:38 assar Exp $");
47 extern int __check_rhosts_file;
49 char *INSECURE_MESSAGE =
50 "\r\n*** Connection not encrypted! Communication may be eavesdropped. ***"
51 "\r\n*** Use telnet or rlogin -x instead! ***\r\n";
54 char *SECURE_MESSAGE =
55 "This rlogin session is using DES encryption for all transmissions.\r\n";
57 #define SECURE_MESSAGE INSECURE_MESSAGE
62 u_char auth_buf[sizeof(AUTH_DAT)];
63 u_char tick_buf[sizeof(KTEXT_ST)];
64 Key_schedule schedule;
65 int doencrypt, retval, use_kerberos, vacuous;
67 #define ARGSTR "Daip:lnkvxL:"
71 char lusername[NMAX+1], rusername[NMAX+1];
72 static char term[64] = "TERM=";
73 #define ENVSIZE (sizeof("TERM=")-1) /* skip null for concatenation */
80 static const char *new_login = _PATH_LOGIN;
82 static void doit (int, struct sockaddr_in *);
83 static int control (int, char *, int);
84 static void protocol (int, int);
85 static RETSIGTYPE cleanup (int);
86 void fatal (int, const char *, int);
87 static int do_rlogin (struct sockaddr_in *);
88 static void setup_term (int);
89 static int do_krb_login (struct sockaddr_in *);
90 static void usage (void);
93 readstream(int p, char *ibuf, int bufsize)
96 return read(p, ibuf, bufsize);
98 static int flowison = -1; /* current state of flow: -1 is unknown */
99 static struct strbuf strbufc, strbufd;
100 static unsigned char ctlbuf[BUFSIZ];
101 static int use_read = 1;
114 ret = read(p, ibuf, bufsize);
115 if (ret < 0 && errno == EBADMSG)
121 strbufc.maxlen = BUFSIZ;
122 strbufc.buf = (char *)ctlbuf;
123 strbufd.maxlen = bufsize-1;
125 strbufd.buf = ibuf+1;
128 ret = getmsg(p, &strbufc, &strbufd, &flags);
129 if (ret < 0) /* error of some sort -- probably EAGAIN */
132 if (strbufc.len <= 0 || ctlbuf[0] == M_DATA) {
134 if (strbufd.len > 0) { /* real data */
135 return(strbufd.len + 1); /* count header char */
144 * It's a control message. Return 1, to look at the flag we set
149 if (ibuf[1] & FLUSHW)
150 ibuf[0] = TIOCPKT_FLUSHWRITE;
154 memcpy(&ip, (ibuf+1), sizeof(ip));
156 switch (ip.ioc_cmd) {
162 (ibuf+1 + sizeof(struct iocblk)),
164 vstop = tsp.c_cc[VSTOP];
165 vstart = tsp.c_cc[VSTART];
166 ixon = tsp.c_iflag & IXON;
174 newflow = (ixon && (vstart == 021) && (vstop == 023)) ? 1 : 0;
175 if (newflow != flowison) { /* it's a change */
177 ibuf[0] = newflow ? TIOCPKT_DOSTOP : TIOCPKT_NOSTOP;
182 /* nothing worth doing anything about */
190 rlogind_logout(const char *line)
192 struct utmpx utmpx, *utxp;
196 memset(&utmpx, 0, sizeof(utmpx));
197 utmpx.ut_type = USER_PROCESS;
198 strncpy(utmpx.ut_line, line, sizeof(utmpx.ut_line));
199 utxp = getutxline(&utmpx);
201 utxp->ut_user[0] = '\0';
202 utxp->ut_type = DEAD_PROCESS;
203 #ifdef HAVE_STRUCT_UTMPX_UT_EXIT
204 #ifdef _STRUCT___EXIT_STATUS
205 utxp->ut_exit.__e_termination = 0;
206 utxp->ut_exit.__e_exit = 0;
207 #elif defined(__osf__) /* XXX */
208 utxp->ut_exit.ut_termination = 0;
209 utxp->ut_exit.ut_exit = 0;
211 utxp->ut_exit.e_termination = 0;
212 utxp->ut_exit.e_exit = 0;
215 gettimeofday(&utxp->ut_tv, NULL);
218 updwtmpx(WTMPX_FILE, utxp);
228 rlogind_logout(const char *line)
234 if (!(fp = fopen(_PATH_UTMP, "r+")))
237 while (fread(&ut, sizeof(struct utmp), 1, fp) == 1) {
238 if (!ut.ut_name[0] ||
239 strncmp(ut.ut_line, line, sizeof(ut.ut_line)))
241 memset(ut.ut_name, 0, sizeof(ut.ut_name));
242 #ifdef HAVE_STRUCT_UTMP_UT_HOST
243 memset(ut.ut_host, 0, sizeof(ut.ut_host));
245 #ifdef HAVE_STRUCT_UTMP_UT_TYPE
246 ut.ut_type = DEAD_PROCESS;
248 #ifdef HAVE_STRUCT_UTMP_UT_EXIT
249 #ifdef _STRUCT___EXIT_STATUS
250 ut.ut_exit.__e_termination = 0;
251 ut.ut_exit.__e_exit = 0;
252 #elif defined(__osf__) /* XXX */
253 ut.ut_exit.ut_termination = 0;
254 ut.ut_exit.ut_exit = 0;
256 ut.ut_exit.e_termination = 0;
257 ut.ut_exit.e_exit = 0;
261 fseek(fp, (long)-sizeof(struct utmp), SEEK_CUR);
262 fwrite(&ut, sizeof(struct utmp), 1, fp);
263 fseek(fp, (long)0, SEEK_CUR);
273 logwtmp(const char *line, const char *name, const char *host)
279 memset (&ut, 0, sizeof(ut));
280 if ((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0)) < 0)
282 if (!fstat(fd, &buf)) {
283 strncpy(ut.ut_line, line, sizeof(ut.ut_line));
284 strncpy(ut.ut_name, name, sizeof(ut.ut_name));
285 #ifdef HAVE_STRUCT_UTMP_UT_ID
286 strncpy(ut.ut_id, make_id((char *)line), sizeof(ut.ut_id));
288 #ifdef HAVE_STRUCT_UTMP_UT_HOST
289 strncpy(ut.ut_host, host, sizeof(ut.ut_host));
291 #ifdef HAVE_STRUCT_UTMP_UT_PID
292 ut.ut_pid = getpid();
294 #ifdef HAVE_STRUCT_UTMP_UT_TYPE
296 ut.ut_type = USER_PROCESS;
298 ut.ut_type = DEAD_PROCESS;
301 if (write(fd, &ut, sizeof(struct utmp)) !=
303 ftruncate(fd, buf.st_size);
310 main(int argc, char **argv)
312 struct sockaddr_in from;
317 set_progname(argv[0]);
319 openlog("rlogind", LOG_PID | LOG_CONS, LOG_AUTH);
322 while ((ch = getopt(argc, argv, ARGSTR)) != -1)
333 portnum = htons(atoi(optarg));
336 __check_rhosts_file = 0;
361 if (use_kerberos && vacuous) {
363 fatal(STDERR_FILENO, "only one of -k and -v allowed", 0);
367 portnum = get_login_port (use_kerberos, doencrypt);
368 mini_inetd (portnum);
371 fromlen = sizeof (from);
372 if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
373 syslog(LOG_ERR,"Can't get peer name of remote host: %m");
374 fatal(STDERR_FILENO, "Can't get peer name of remote host", 1);
377 #ifdef HAVE_SETSOCKOPT
380 setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (void *)&on,
382 syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
386 setsockopt(0, IPPROTO_TCP, TCP_NODELAY, (void *)&on,
388 syslog(LOG_WARNING, "setsockopt (TCP_NODELAY): %m");
393 if (setsockopt(0, IPPROTO_IP, IP_TOS, (void *)&on, sizeof(int)) < 0)
394 syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
396 #endif /* HAVE_SETSOCKOPT */
403 char line[MaxPathLen];
406 struct winsize win = { 0, 0, 0, 0 };
410 doit(int f, struct sockaddr_in *fromp)
412 int master, pid, on = 1;
413 int authenticated = 0;
414 char hostname[2 * MaxHostNameLen + 1];
423 fatal(f, "Remote host requires Kerberos authentication", 0);
426 inaddr2str (fromp->sin_addr, hostname, sizeof(hostname));
429 retval = do_krb_login(fromp);
433 fatal(f, krb_get_err_text(retval), 0);
435 confirmed = 1; /* we sent the null! */
437 fromp->sin_port = ntohs((u_short)fromp->sin_port);
438 if (fromp->sin_family != AF_INET ||
439 fromp->sin_port >= IPPORT_RESERVED ||
440 fromp->sin_port < IPPORT_RESERVED/2) {
441 syslog(LOG_NOTICE, "Connection from %s on illegal port",
442 inet_ntoa(fromp->sin_addr));
443 fatal(f, "Permission denied", 0);
445 ip_options_and_die (0, fromp);
446 if (do_rlogin(fromp) == 0)
449 if (confirmed == 0) {
451 confirmed = 1; /* we sent the null! */
455 des_enc_write(f, SECURE_MESSAGE,
456 strlen(SECURE_MESSAGE),
457 schedule, &kdata->session);
460 write(f, INSECURE_MESSAGE, strlen(INSECURE_MESSAGE));
464 pid = forkpty(&master, line, NULL, NULL);
466 pid = forkpty_truncate(&master, line, sizeof(line), NULL, NULL);
470 fatal(f, "Out of ptys", 0);
472 fatal(f, "Forkpty", 1);
475 if (f > 2) /* f should always be 0, but... */
478 if (lusername[0] == '-'){
479 syslog(LOG_ERR, "tried to pass user \"%s\" to login",
481 fatal(STDERR_FILENO, "invalid user", 0);
484 if (use_kerberos && (pwd->pw_uid == 0))
485 syslog(LOG_INFO|LOG_AUTH,
486 "ROOT Kerberos login from %s on %s\n",
487 krb_unparse_name_long(kdata->pname,
492 execl(new_login, "login", "-p",
493 "-h", hostname, "-f", "--", lusername, 0);
495 execl(new_login, "login", "-p",
496 "-h", hostname, "--", lusername, 0);
497 fatal(STDERR_FILENO, new_login, 1);
501 * If encrypted, don't turn on NBIO or the des read/write
502 * routines will croak.
506 ioctl(f, FIONBIO, &on);
507 ioctl(master, FIONBIO, &on);
508 ioctl(master, TIOCPKT, &on);
510 signal(SIGTSTP, SIG_IGN);
512 signal(SIGCHLD, cleanup);
515 signal(SIGCHLD, SIG_IGN);
519 const char magic[2] = { 0377, 0377 };
522 * Handle a "control" request (signaled by magic being present)
523 * in the data stream. For now, we are only willing to handle
524 * window size changes.
527 control(int master, char *cp, int n)
533 if (n < 4 + 4 * sizeof (u_int16_t) || cp[2] != 's' || cp[3] != 's')
537 p += krb_get_int(p, &tmp, 2, 0);
539 p += krb_get_int(p, &tmp, 2, 0);
542 p += krb_get_int(p, &tmp, 2, 0);
543 #ifdef HAVE_WS_XPIXEL
546 p += krb_get_int(p, &tmp, 2, 0);
547 #ifdef HAVE_WS_YPIXEL
550 ioctl(master, TIOCSWINSZ, &w);
557 send_oob(int fd, char c)
559 static char last_oob = 0xFF;
561 #if (SunOS >= 50) || defined(__hpux)
563 * PSoriasis and HP-UX always send TIOCPKT_DOSTOP at startup so we
564 * can avoid sending OOB data and thus not break on Linux by merging
565 * TIOCPKT_DOSTOP into the first TIOCPKT_WINDOW.
567 static int oob_kludge = 2;
570 oob_kludge--; /* First time send nothing */
573 else if (oob_kludge == 1)
575 oob_kludge--; /* Second time merge TIOCPKT_WINDOW */
580 #define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))
582 /* Multiple OOB data breaks on Linux, avoid it when possible. */
584 send(fd, &c, 1, MSG_OOB);
589 * rlogin "protocol" machine.
592 protocol(int f, int master)
594 char pibuf[1024+1], fibuf[1024], *pbp, *fbp;
595 int pcc = 0, fcc = 0;
598 unsigned char oob_queue = 0;
602 * Must ignore SIGTTOU, otherwise we'll stop
603 * when we try and set slave pty's window shape
604 * (our controlling tty is the master pty).
606 signal(SIGTTOU, SIG_IGN);
609 send_oob(f, TIOCPKT_WINDOW); /* indicate new rlogin */
615 if (nfd > FD_SETSIZE) {
616 syslog(LOG_ERR, "select mask too small, increase FD_SETSIZE");
617 fatal(f, "internal error (select mask too small)", 0);
620 fd_set ibits, obits, ebits, *omask;
625 omask = (fd_set *)NULL;
627 FD_SET(master, &obits);
636 FD_SET(master, &ibits);
638 FD_SET(master, &ebits);
639 if ((n = select(nfd, &ibits, omask, &ebits, 0)) < 0) {
642 fatal(f, "select", 1);
645 /* shouldn't happen... */
649 if (FD_ISSET(master, &ebits)) {
650 cc = readstream(master, &cntl, 1);
651 if (cc == 1 && pkcontrol(cntl)) {
652 #if 0 /* Kludge around */
656 if (cntl & TIOCPKT_FLUSHWRITE) {
658 FD_CLR(master, &ibits);
662 if (FD_ISSET(f, &ibits)) {
665 fcc = des_enc_read(f, fibuf,
667 schedule, &kdata->session);
670 fcc = read(f, fibuf, sizeof(fibuf));
671 if (fcc < 0 && errno == EWOULDBLOCK)
682 for (cp = fibuf; cp < fibuf+fcc-1; cp++)
683 if (cp[0] == magic[0] &&
685 left = fcc - (cp-fibuf);
686 n = control(master, cp, left);
690 memmove(cp, cp+n, left);
695 FD_SET(master, &obits); /* try write */
699 if (FD_ISSET(master, &obits) && fcc > 0) {
700 cc = write(master, fbp, fcc);
707 if (FD_ISSET(master, &ibits)) {
708 pcc = readstream(master, pibuf, sizeof (pibuf));
710 if (pcc < 0 && errno == EWOULDBLOCK)
714 else if (pibuf[0] == 0) {
717 FD_SET(f, &obits); /* try write */
719 if (pkcontrol(pibuf[0])) {
720 oob_queue = pibuf[0];
721 #if 0 /* Kludge around */
722 send_oob(f, pibuf[0]);
728 if ((FD_ISSET(f, &obits)) && pcc > 0) {
731 cc = des_enc_write(f, pbp, pcc, schedule, &kdata->session);
734 cc = write(f, pbp, pcc);
735 if (cc < 0 && errno == EWOULDBLOCK) {
737 * This happens when we try write after read
738 * from p, but some old kernels balk at large
739 * writes even when select returns true.
741 if (!FD_ISSET(master, &ibits))
748 /* Only send urg data when normal data
749 * has just been sent.
750 * Linux has deep problems with more
751 * than one byte of OOB data.
754 send_oob (f, oob_queue);
765 char *p = clean_ttyname (line);
767 if (rlogind_logout(p) == 0)
775 signal(SIGHUP, SIG_IGN);
778 #endif /* HAVE_VHANGUP */
783 fatal(int f, const char *msg, int syserr)
786 char buf[BUFSIZ], *bp = buf;
789 * Prepend binary one to message if we haven't sent
790 * the magic null as confirmation.
793 *bp++ = '\01'; /* error indicator */
795 snprintf(bp, sizeof(buf) - (bp - buf),
796 "rlogind: %s: %s.\r\n",
797 msg, strerror(errno));
799 snprintf(bp, sizeof(buf) - (bp - buf),
800 "rlogind: %s.\r\n", msg);
804 des_enc_write(f, buf, bp + len - buf, schedule, &kdata->session);
807 write(f, buf, bp + len - buf);
812 xgetstr(char *buf, int cnt, char *errmsg)
817 if (read(0, &c, 1) != 1)
820 fatal(STDOUT_FILENO, errmsg, 0);
826 do_rlogin(struct sockaddr_in *dest)
828 xgetstr(rusername, sizeof(rusername), "remuser too long");
829 xgetstr(lusername, sizeof(lusername), "locuser too long");
830 xgetstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type too long");
832 pwd = k_getpwnam(lusername);
835 if (pwd->pw_uid == 0 && strcmp("root", lusername) != 0)
837 syslog(LOG_ALERT, "NIS attack, user %s has uid 0", lusername);
840 return (iruserok(dest->sin_addr.s_addr,
849 char *cp = strchr(term+ENVSIZE, '/');
859 cp = strchr(speed, '/');
862 s = int2speed_t (atoi (speed));
864 cfsetospeed (&tt, s);
865 cfsetispeed (&tt, s);
869 tt.c_iflag &= ~INPCK;
870 tt.c_iflag |= ICRNL|IXON;
871 tt.c_oflag |= OPOST|ONLCR;
876 tt.c_oflag &= ~ONLRET;
878 tt.c_lflag |= (ECHO|ECHOE|ECHOK|ISIG|ICANON);
879 tt.c_cflag &= ~PARENB;
883 tt.c_cc[VEOF] = CEOF;
884 tcsetattr(fd, TCSAFLUSH, &tt);
891 #define VERSION_SIZE 9
894 * Do the remote kerberos login to the named host with the
897 * Return 0 on valid authorization
898 * Return -1 on valid authentication, no authorization
899 * Return >0 for error conditions
902 do_krb_login(struct sockaddr_in *dest)
905 char instance[INST_SZ], version[VERSION_SIZE];
906 long authopts = 0L; /* !mutual */
907 struct sockaddr_in faddr;
909 kdata = (AUTH_DAT *) auth_buf;
910 ticket = (KTEXT) tick_buf;
912 k_getsockinst(0, instance, sizeof(instance));
916 if (getsockname(0, (struct sockaddr *)&faddr, &rc))
918 authopts = KOPT_DO_MUTUAL;
922 instance, dest, &faddr,
923 kdata, "", schedule, version);
924 des_set_key(&kdata->session, schedule);
930 instance, dest, (struct sockaddr_in *) 0,
931 kdata, "", 0, version);
936 xgetstr(lusername, sizeof(lusername), "locuser");
937 /* get the "cmd" in the rcmd protocol */
938 xgetstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type");
940 pwd = k_getpwnam(lusername);
943 if (pwd->pw_uid == 0 && strcmp("root", lusername) != 0)
945 syslog(LOG_ALERT, "NIS attack, user %s has uid 0", lusername);
949 /* returns nonzero for no access */
950 if (kuserok(kdata, lusername) != 0)
961 "usage: rlogind [-Dailn] [-p port] [-x] [-L login] [-k | -v]");