rlogind.c revision 51433
11592Srgrimes/*- 21592Srgrimes * Copyright (c) 1983, 1988, 1989, 1993 31592Srgrimes * The Regents of the University of California. All rights reserved. 41592Srgrimes * 51592Srgrimes * Redistribution and use in source and binary forms, with or without 61592Srgrimes * modification, are permitted provided that the following conditions 71592Srgrimes * are met: 81592Srgrimes * 1. Redistributions of source code must retain the above copyright 91592Srgrimes * notice, this list of conditions and the following disclaimer. 101592Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111592Srgrimes * notice, this list of conditions and the following disclaimer in the 121592Srgrimes * documentation and/or other materials provided with the distribution. 131592Srgrimes * 3. All advertising materials mentioning features or use of this software 141592Srgrimes * must display the following acknowledgement: 151592Srgrimes * This product includes software developed by the University of 161592Srgrimes * California, Berkeley and its contributors. 171592Srgrimes * 4. Neither the name of the University nor the names of its contributors 181592Srgrimes * may be used to endorse or promote products derived from this software 191592Srgrimes * without specific prior written permission. 201592Srgrimes * 211592Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221592Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231592Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241592Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251592Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261592Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271592Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281592Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291592Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301592Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311592Srgrimes * SUCH DAMAGE. 321592Srgrimes */ 331592Srgrimes 341592Srgrimes#ifndef lint 3529916Smarkmstatic const char copyright[] = 361592Srgrimes"@(#) Copyright (c) 1983, 1988, 1989, 1993\n\ 371592Srgrimes The Regents of the University of California. All rights reserved.\n"; 381592Srgrimes#endif /* not lint */ 391592Srgrimes 401592Srgrimes#ifndef lint 4131405Scharnier#if 0 4229916Smarkmstatic const char sccsid[] = "@(#)rlogind.c 8.1 (Berkeley) 6/4/93"; 4331405Scharnier#endif 4431405Scharnierstatic const char rcsid[] = 4550476Speter "$FreeBSD: head/libexec/rlogind/rlogind.c 51433 1999-09-19 22:05:32Z markm $"; 461592Srgrimes#endif /* not lint */ 471592Srgrimes 481592Srgrimes/* 491592Srgrimes * remote login server: 501592Srgrimes * \0 511592Srgrimes * remuser\0 521592Srgrimes * locuser\0 531592Srgrimes * terminal_type/speed\0 541592Srgrimes * data 551592Srgrimes */ 561592Srgrimes 571592Srgrimes#define FD_SETSIZE 16 /* don't need many bits for select */ 5829916Smarkm#include <sys/types.h> 591592Srgrimes#include <sys/param.h> 601592Srgrimes#include <sys/stat.h> 611592Srgrimes#include <sys/ioctl.h> 621592Srgrimes#include <signal.h> 631592Srgrimes#include <termios.h> 641592Srgrimes 651592Srgrimes#include <sys/socket.h> 661592Srgrimes#include <netinet/in.h> 671592Srgrimes#include <netinet/in_systm.h> 681592Srgrimes#include <netinet/ip.h> 6911486Sdg#include <netinet/tcp.h> 701592Srgrimes#include <arpa/inet.h> 711592Srgrimes#include <netdb.h> 721592Srgrimes 7331405Scharnier#include <errno.h> 7431405Scharnier#include <libutil.h> 751592Srgrimes#include <pwd.h> 761592Srgrimes#include <syslog.h> 771592Srgrimes#include <stdio.h> 781592Srgrimes#include <stdlib.h> 791592Srgrimes#include <string.h> 8031405Scharnier#include <unistd.h> 811592Srgrimes#include "pathnames.h" 821592Srgrimes 8351433Smarkm#ifndef NO_PAM 8451433Smarkm#include <security/pam_appl.h> 8551433Smarkm#include <security/pam_misc.h> 8651433Smarkm#endif 8751433Smarkm 881592Srgrimes#ifndef TIOCPKT_WINDOW 891592Srgrimes#define TIOCPKT_WINDOW 0x80 901592Srgrimes#endif 911592Srgrimes 9251433Smarkm#define ARGSTR "Dalnx" 931592Srgrimes 941592Srgrimeschar *env[2]; 951592Srgrimes#define NMAX 30 961592Srgrimeschar lusername[NMAX+1], rusername[NMAX+1]; 971592Srgrimesstatic char term[64] = "TERM="; 981592Srgrimes#define ENVSIZE (sizeof("TERM=")-1) /* skip null for concatenation */ 991592Srgrimesint keepalive = 1; 1001592Srgrimesint check_all = 0; 10111486Sdgint no_delay; 1021592Srgrimes 1031592Srgrimesstruct passwd *pwd; 1041592Srgrimes 1051592Srgrimesvoid doit __P((int, struct sockaddr_in *)); 1061592Srgrimesint control __P((int, char *, int)); 1071592Srgrimesvoid protocol __P((int, int)); 1081592Srgrimesvoid cleanup __P((int)); 1091592Srgrimesvoid fatal __P((int, char *, int)); 1101592Srgrimesint do_rlogin __P((struct sockaddr_in *)); 1111592Srgrimesvoid getstr __P((char *, int, char *)); 1121592Srgrimesvoid setup_term __P((int)); 1131592Srgrimesint do_krb_login __P((struct sockaddr_in *)); 1141592Srgrimesvoid usage __P((void)); 1151592Srgrimes 11651433Smarkm#ifndef NO_PAM 11751433Smarkmextern int auth_pam __P((char *)); 11851433Smarkm#endif 11951433Smarkm 1201592Srgrimesint 1211592Srgrimesmain(argc, argv) 1221592Srgrimes int argc; 1231592Srgrimes char *argv[]; 1241592Srgrimes{ 1251592Srgrimes extern int __check_rhosts_file; 1261592Srgrimes struct sockaddr_in from; 1271592Srgrimes int ch, fromlen, on; 1281592Srgrimes 1291592Srgrimes openlog("rlogind", LOG_PID | LOG_CONS, LOG_AUTH); 1301592Srgrimes 1311592Srgrimes opterr = 0; 13224349Simp while ((ch = getopt(argc, argv, ARGSTR)) != -1) 1331592Srgrimes switch (ch) { 13411486Sdg case 'D': 13511486Sdg no_delay = 1; 13611486Sdg break; 1371592Srgrimes case 'a': 1381592Srgrimes check_all = 1; 1391592Srgrimes break; 1401592Srgrimes case 'l': 1411592Srgrimes __check_rhosts_file = 0; 1421592Srgrimes break; 1431592Srgrimes case 'n': 1441592Srgrimes keepalive = 0; 1451592Srgrimes break; 1461592Srgrimes#ifdef CRYPT 1471592Srgrimes case 'x': 1481592Srgrimes doencrypt = 1; 1491592Srgrimes break; 1501592Srgrimes#endif 1511592Srgrimes case '?': 1521592Srgrimes default: 1531592Srgrimes usage(); 1541592Srgrimes break; 1551592Srgrimes } 1561592Srgrimes argc -= optind; 1571592Srgrimes argv += optind; 1581592Srgrimes 1591592Srgrimes fromlen = sizeof (from); 1601592Srgrimes if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { 1611592Srgrimes syslog(LOG_ERR,"Can't get peer name of remote host: %m"); 1621592Srgrimes fatal(STDERR_FILENO, "Can't get peer name of remote host", 1); 1631592Srgrimes } 1641592Srgrimes on = 1; 1651592Srgrimes if (keepalive && 1661592Srgrimes setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) 1671592Srgrimes syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); 16811486Sdg if (no_delay && 16911486Sdg setsockopt(0, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0) 17011486Sdg syslog(LOG_WARNING, "setsockopt (TCP_NODELAY): %m"); 1711592Srgrimes on = IPTOS_LOWDELAY; 1721592Srgrimes if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) 1731592Srgrimes syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); 17411486Sdg 1751592Srgrimes doit(0, &from); 17629916Smarkm return 0; 1771592Srgrimes} 1781592Srgrimes 1791592Srgrimesint child; 1801592Srgrimesint netf; 1811592Srgrimeschar line[MAXPATHLEN]; 1821592Srgrimesint confirmed; 1831592Srgrimes 1841592Srgrimesstruct winsize win = { 0, 0, 0, 0 }; 1851592Srgrimes 1861592Srgrimes 1871592Srgrimesvoid 1881592Srgrimesdoit(f, fromp) 1891592Srgrimes int f; 1901592Srgrimes struct sockaddr_in *fromp; 1911592Srgrimes{ 1921592Srgrimes int master, pid, on = 1; 1931592Srgrimes int authenticated = 0; 19445422Sbrian char hostname[MAXHOSTNAMELEN]; 1951592Srgrimes char c; 1961592Srgrimes 1971592Srgrimes alarm(60); 1981592Srgrimes read(f, &c, 1); 1991592Srgrimes 2001592Srgrimes if (c != 0) 2011592Srgrimes exit(1); 2021592Srgrimes 2031592Srgrimes alarm(0); 2041592Srgrimes fromp->sin_port = ntohs((u_short)fromp->sin_port); 20545422Sbrian realhostname(hostname, sizeof(hostname) - 1, &fromp->sin_addr); 20624191Simp hostname[sizeof(hostname) - 1] = '\0'; 2071592Srgrimes 2081592Srgrimes { 2091592Srgrimes if (fromp->sin_family != AF_INET || 2101592Srgrimes fromp->sin_port >= IPPORT_RESERVED || 2111592Srgrimes fromp->sin_port < IPPORT_RESERVED/2) { 2121592Srgrimes syslog(LOG_NOTICE, "Connection from %s on illegal port", 2131592Srgrimes inet_ntoa(fromp->sin_addr)); 2141592Srgrimes fatal(f, "Permission denied", 0); 2151592Srgrimes } 2161592Srgrimes#ifdef IP_OPTIONS 2171592Srgrimes { 21822455Simp u_char optbuf[BUFSIZ/3]; 21922455Simp int optsize = sizeof(optbuf), ipproto, i; 2201592Srgrimes struct protoent *ip; 2211592Srgrimes 2221592Srgrimes if ((ip = getprotobyname("ip")) != NULL) 2231592Srgrimes ipproto = ip->p_proto; 2241592Srgrimes else 2251592Srgrimes ipproto = IPPROTO_IP; 2261592Srgrimes if (getsockopt(0, ipproto, IP_OPTIONS, (char *)optbuf, 2271592Srgrimes &optsize) == 0 && optsize != 0) { 22822455Simp for (i = 0; i < optsize; ) { 22922455Simp u_char c = optbuf[i]; 23022455Simp if (c == IPOPT_LSRR || c == IPOPT_SSRR) { 23122455Simp syslog(LOG_NOTICE, 23222455Simp "Connection refused from %s with IP option %s", 23322455Simp inet_ntoa(fromp->sin_addr), 23422455Simp c == IPOPT_LSRR ? "LSRR" : "SSRR"); 23522455Simp exit(1); 23622455Simp } 23722455Simp if (c == IPOPT_EOL) 23822455Simp break; 23922455Simp i += (c == IPOPT_NOP) ? 1 : optbuf[i+1]; 2401592Srgrimes } 2411592Srgrimes } 2421592Srgrimes } 2431592Srgrimes#endif 2441592Srgrimes if (do_rlogin(fromp) == 0) 2451592Srgrimes authenticated++; 2461592Srgrimes } 2471592Srgrimes if (confirmed == 0) { 2481592Srgrimes write(f, "", 1); 2491592Srgrimes confirmed = 1; /* we sent the null! */ 2501592Srgrimes } 2511592Srgrimes#ifdef CRYPT 2521592Srgrimes if (doencrypt) 25329916Smarkm (void) des_enc_write(f, 25429916Smarkm SECURE_MESSAGE, 25529916Smarkm strlen(SECURE_MESSAGE), 25629916Smarkm schedule, &kdata->session); 2571592Srgrimes#endif 2581592Srgrimes netf = f; 2591592Srgrimes 2601592Srgrimes pid = forkpty(&master, line, NULL, &win); 2611592Srgrimes if (pid < 0) { 2621592Srgrimes if (errno == ENOENT) 2631592Srgrimes fatal(f, "Out of ptys", 0); 2641592Srgrimes else 2651592Srgrimes fatal(f, "Forkpty", 1); 2661592Srgrimes } 2671592Srgrimes if (pid == 0) { 2681592Srgrimes if (f > 2) /* f should always be 0, but... */ 2691592Srgrimes (void) close(f); 2701592Srgrimes setup_term(0); 27112575Snate if (*lusername=='-') { 2722076Sguido syslog(LOG_ERR, "tried to pass user \"%s\" to login", 2732076Sguido lusername); 2742076Sguido fatal(STDERR_FILENO, "invalid user", 0); 2752076Sguido } 2761592Srgrimes if (authenticated) { 2771592Srgrimes execl(_PATH_LOGIN, "login", "-p", 2781592Srgrimes "-h", hostname, "-f", lusername, (char *)NULL); 2791592Srgrimes } else 2801592Srgrimes execl(_PATH_LOGIN, "login", "-p", 2811592Srgrimes "-h", hostname, lusername, (char *)NULL); 2821592Srgrimes fatal(STDERR_FILENO, _PATH_LOGIN, 1); 2831592Srgrimes /*NOTREACHED*/ 2841592Srgrimes } 2851592Srgrimes#ifdef CRYPT 2861592Srgrimes /* 2871592Srgrimes * If encrypted, don't turn on NBIO or the des read/write 2881592Srgrimes * routines will croak. 2891592Srgrimes */ 2901592Srgrimes 2911592Srgrimes if (!doencrypt) 2921592Srgrimes#endif 2931592Srgrimes ioctl(f, FIONBIO, &on); 2941592Srgrimes ioctl(master, FIONBIO, &on); 2951592Srgrimes ioctl(master, TIOCPKT, &on); 2961592Srgrimes signal(SIGCHLD, cleanup); 2971592Srgrimes protocol(f, master); 2981592Srgrimes signal(SIGCHLD, SIG_IGN); 2991592Srgrimes cleanup(0); 3001592Srgrimes} 3011592Srgrimes 3021592Srgrimeschar magic[2] = { 0377, 0377 }; 3031592Srgrimeschar oobdata[] = {TIOCPKT_WINDOW}; 3041592Srgrimes 3051592Srgrimes/* 3061592Srgrimes * Handle a "control" request (signaled by magic being present) 3071592Srgrimes * in the data stream. For now, we are only willing to handle 3081592Srgrimes * window size changes. 3091592Srgrimes */ 3101592Srgrimesint 3111592Srgrimescontrol(pty, cp, n) 3121592Srgrimes int pty; 3131592Srgrimes char *cp; 3141592Srgrimes int n; 3151592Srgrimes{ 3161592Srgrimes struct winsize w; 3171592Srgrimes 3181592Srgrimes if (n < 4+sizeof (w) || cp[2] != 's' || cp[3] != 's') 3191592Srgrimes return (0); 3201592Srgrimes oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */ 3211592Srgrimes bcopy(cp+4, (char *)&w, sizeof(w)); 3221592Srgrimes w.ws_row = ntohs(w.ws_row); 3231592Srgrimes w.ws_col = ntohs(w.ws_col); 3241592Srgrimes w.ws_xpixel = ntohs(w.ws_xpixel); 3251592Srgrimes w.ws_ypixel = ntohs(w.ws_ypixel); 3261592Srgrimes (void)ioctl(pty, TIOCSWINSZ, &w); 3271592Srgrimes return (4+sizeof (w)); 3281592Srgrimes} 3291592Srgrimes 3301592Srgrimes/* 3311592Srgrimes * rlogin "protocol" machine. 3321592Srgrimes */ 3331592Srgrimesvoid 3341592Srgrimesprotocol(f, p) 3351592Srgrimes register int f, p; 3361592Srgrimes{ 3371592Srgrimes char pibuf[1024+1], fibuf[1024], *pbp, *fbp; 33846078Simp int pcc = 0, fcc = 0; 3391592Srgrimes int cc, nfd, n; 3401592Srgrimes char cntl; 3411592Srgrimes 3421592Srgrimes /* 3431592Srgrimes * Must ignore SIGTTOU, otherwise we'll stop 3441592Srgrimes * when we try and set slave pty's window shape 3451592Srgrimes * (our controlling tty is the master pty). 3461592Srgrimes */ 3471592Srgrimes (void) signal(SIGTTOU, SIG_IGN); 3481592Srgrimes send(f, oobdata, 1, MSG_OOB); /* indicate new rlogin */ 3491592Srgrimes if (f > p) 3501592Srgrimes nfd = f + 1; 3511592Srgrimes else 3521592Srgrimes nfd = p + 1; 3531592Srgrimes if (nfd > FD_SETSIZE) { 3541592Srgrimes syslog(LOG_ERR, "select mask too small, increase FD_SETSIZE"); 3551592Srgrimes fatal(f, "internal error (select mask too small)", 0); 3561592Srgrimes } 3571592Srgrimes for (;;) { 3581592Srgrimes fd_set ibits, obits, ebits, *omask; 3591592Srgrimes 3601592Srgrimes FD_ZERO(&ebits); 3611592Srgrimes FD_ZERO(&ibits); 3621592Srgrimes FD_ZERO(&obits); 3631592Srgrimes omask = (fd_set *)NULL; 3641592Srgrimes if (fcc) { 3651592Srgrimes FD_SET(p, &obits); 3661592Srgrimes omask = &obits; 3671592Srgrimes } else 3681592Srgrimes FD_SET(f, &ibits); 36946078Simp if (pcc >= 0) { 3701592Srgrimes if (pcc) { 3711592Srgrimes FD_SET(f, &obits); 3721592Srgrimes omask = &obits; 3731592Srgrimes } else 3741592Srgrimes FD_SET(p, &ibits); 37546078Simp } 3761592Srgrimes FD_SET(p, &ebits); 3771592Srgrimes if ((n = select(nfd, &ibits, omask, &ebits, 0)) < 0) { 3781592Srgrimes if (errno == EINTR) 3791592Srgrimes continue; 3801592Srgrimes fatal(f, "select", 1); 3811592Srgrimes } 3821592Srgrimes if (n == 0) { 3831592Srgrimes /* shouldn't happen... */ 3841592Srgrimes sleep(5); 3851592Srgrimes continue; 3861592Srgrimes } 3871592Srgrimes#define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP)) 3881592Srgrimes if (FD_ISSET(p, &ebits)) { 3891592Srgrimes cc = read(p, &cntl, 1); 3901592Srgrimes if (cc == 1 && pkcontrol(cntl)) { 3911592Srgrimes cntl |= oobdata[0]; 3921592Srgrimes send(f, &cntl, 1, MSG_OOB); 3931592Srgrimes if (cntl & TIOCPKT_FLUSHWRITE) { 3941592Srgrimes pcc = 0; 3951592Srgrimes FD_CLR(p, &ibits); 3961592Srgrimes } 3971592Srgrimes } 3981592Srgrimes } 3991592Srgrimes if (FD_ISSET(f, &ibits)) { 4001592Srgrimes#ifdef CRYPT 4011592Srgrimes if (doencrypt) 40229916Smarkm fcc = des_enc_read(f, fibuf, sizeof(fibuf), 40329916Smarkm schedule, &kdata->session); 4041592Srgrimes else 4051592Srgrimes#endif 4061592Srgrimes fcc = read(f, fibuf, sizeof(fibuf)); 4071592Srgrimes if (fcc < 0 && errno == EWOULDBLOCK) 4081592Srgrimes fcc = 0; 4091592Srgrimes else { 4101592Srgrimes register char *cp; 4111592Srgrimes int left, n; 4121592Srgrimes 4131592Srgrimes if (fcc <= 0) 4141592Srgrimes break; 4151592Srgrimes fbp = fibuf; 4161592Srgrimes 4171592Srgrimes top: 4181592Srgrimes for (cp = fibuf; cp < fibuf+fcc-1; cp++) 4191592Srgrimes if (cp[0] == magic[0] && 4201592Srgrimes cp[1] == magic[1]) { 4211592Srgrimes left = fcc - (cp-fibuf); 4221592Srgrimes n = control(p, cp, left); 4231592Srgrimes if (n) { 4241592Srgrimes left -= n; 4251592Srgrimes if (left > 0) 4261592Srgrimes bcopy(cp+n, cp, left); 4271592Srgrimes fcc -= n; 4281592Srgrimes goto top; /* n^2 */ 4291592Srgrimes } 4301592Srgrimes } 4311592Srgrimes FD_SET(p, &obits); /* try write */ 4321592Srgrimes } 4331592Srgrimes } 4341592Srgrimes 4351592Srgrimes if (FD_ISSET(p, &obits) && fcc > 0) { 4361592Srgrimes cc = write(p, fbp, fcc); 4371592Srgrimes if (cc > 0) { 4381592Srgrimes fcc -= cc; 4391592Srgrimes fbp += cc; 4401592Srgrimes } 4411592Srgrimes } 4421592Srgrimes 4431592Srgrimes if (FD_ISSET(p, &ibits)) { 4441592Srgrimes pcc = read(p, pibuf, sizeof (pibuf)); 4451592Srgrimes pbp = pibuf; 4461592Srgrimes if (pcc < 0 && errno == EWOULDBLOCK) 4471592Srgrimes pcc = 0; 4481592Srgrimes else if (pcc <= 0) 4491592Srgrimes break; 4501592Srgrimes else if (pibuf[0] == 0) { 4511592Srgrimes pbp++, pcc--; 4521592Srgrimes#ifdef CRYPT 4531592Srgrimes if (!doencrypt) 4541592Srgrimes#endif 4551592Srgrimes FD_SET(f, &obits); /* try write */ 4561592Srgrimes } else { 4571592Srgrimes if (pkcontrol(pibuf[0])) { 4581592Srgrimes pibuf[0] |= oobdata[0]; 4591592Srgrimes send(f, &pibuf[0], 1, MSG_OOB); 4601592Srgrimes } 4611592Srgrimes pcc = 0; 4621592Srgrimes } 4631592Srgrimes } 4641592Srgrimes if ((FD_ISSET(f, &obits)) && pcc > 0) { 4651592Srgrimes#ifdef CRYPT 4661592Srgrimes if (doencrypt) 46729916Smarkm cc = des_enc_write(f, pbp, pcc, 46829916Smarkm schedule, &kdata->session); 4691592Srgrimes else 4701592Srgrimes#endif 4711592Srgrimes cc = write(f, pbp, pcc); 4721592Srgrimes if (cc < 0 && errno == EWOULDBLOCK) { 4731592Srgrimes /* 4741592Srgrimes * This happens when we try write after read 4751592Srgrimes * from p, but some old kernels balk at large 4761592Srgrimes * writes even when select returns true. 4771592Srgrimes */ 4781592Srgrimes if (!FD_ISSET(p, &ibits)) 4791592Srgrimes sleep(5); 4801592Srgrimes continue; 4811592Srgrimes } 4821592Srgrimes if (cc > 0) { 4831592Srgrimes pcc -= cc; 4841592Srgrimes pbp += cc; 4851592Srgrimes } 4861592Srgrimes } 4871592Srgrimes } 4881592Srgrimes} 4891592Srgrimes 4901592Srgrimesvoid 4911592Srgrimescleanup(signo) 4921592Srgrimes int signo; 4931592Srgrimes{ 4941592Srgrimes char *p; 4951592Srgrimes 4961592Srgrimes p = line + sizeof(_PATH_DEV) - 1; 4971592Srgrimes if (logout(p)) 4981592Srgrimes logwtmp(p, "", ""); 49950132Simp (void)chflags(line, 0); 5001592Srgrimes (void)chmod(line, 0666); 5011592Srgrimes (void)chown(line, 0, 0); 5021592Srgrimes *p = 'p'; 50350132Simp (void)chflags(line, 0); 5041592Srgrimes (void)chmod(line, 0666); 5051592Srgrimes (void)chown(line, 0, 0); 5061592Srgrimes shutdown(netf, 2); 5071592Srgrimes exit(1); 5081592Srgrimes} 5091592Srgrimes 5101592Srgrimesvoid 5111592Srgrimesfatal(f, msg, syserr) 5121592Srgrimes int f; 5131592Srgrimes char *msg; 5141592Srgrimes int syserr; 5151592Srgrimes{ 5161592Srgrimes int len; 5171592Srgrimes char buf[BUFSIZ], *bp = buf; 5181592Srgrimes 5191592Srgrimes /* 5201592Srgrimes * Prepend binary one to message if we haven't sent 5211592Srgrimes * the magic null as confirmation. 5221592Srgrimes */ 5231592Srgrimes if (!confirmed) 5241592Srgrimes *bp++ = '\01'; /* error indicator */ 5251592Srgrimes if (syserr) 5261592Srgrimes len = sprintf(bp, "rlogind: %s: %s.\r\n", 5271592Srgrimes msg, strerror(errno)); 5281592Srgrimes else 5291592Srgrimes len = sprintf(bp, "rlogind: %s.\r\n", msg); 5301592Srgrimes (void) write(f, buf, bp + len - buf); 5311592Srgrimes exit(1); 5321592Srgrimes} 5331592Srgrimes 5341592Srgrimesint 5351592Srgrimesdo_rlogin(dest) 5361592Srgrimes struct sockaddr_in *dest; 5371592Srgrimes{ 53851433Smarkm int retval; 53951433Smarkm 5401592Srgrimes getstr(rusername, sizeof(rusername), "remuser too long"); 5411592Srgrimes getstr(lusername, sizeof(lusername), "locuser too long"); 5421592Srgrimes getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type too long"); 5431592Srgrimes 54451433Smarkm#ifndef NO_PAM 54551433Smarkm retval = auth_pam(lusername); 54651433Smarkm 54751433Smarkm if (retval) { 54851433Smarkm if (retval == -1) { 54951433Smarkm syslog(LOG_ERR, "PAM authentication failed"); 55051433Smarkm } 55151433Smarkm else { 55251433Smarkm syslog(LOG_ERR, 55351433Smarkm "User %s failed PAM authentication", lusername); 55451433Smarkm exit(1); 55551433Smarkm } 55651433Smarkm } 55751433Smarkm#endif 5581592Srgrimes pwd = getpwnam(lusername); 5591592Srgrimes if (pwd == NULL) 5601592Srgrimes return (-1); 5611592Srgrimes /* XXX why don't we syslog() failure? */ 56212434Speter return (iruserok(dest->sin_addr.s_addr, pwd->pw_uid == 0, 56312434Speter rusername, lusername)); 5641592Srgrimes} 5651592Srgrimes 5661592Srgrimesvoid 5671592Srgrimesgetstr(buf, cnt, errmsg) 5681592Srgrimes char *buf; 5691592Srgrimes int cnt; 5701592Srgrimes char *errmsg; 5711592Srgrimes{ 5721592Srgrimes char c; 5731592Srgrimes 5741592Srgrimes do { 5751592Srgrimes if (read(0, &c, 1) != 1) 5761592Srgrimes exit(1); 5771592Srgrimes if (--cnt < 0) 5781592Srgrimes fatal(STDOUT_FILENO, errmsg, 0); 5791592Srgrimes *buf++ = c; 5801592Srgrimes } while (c != 0); 5811592Srgrimes} 5821592Srgrimes 5831592Srgrimesextern char **environ; 5841592Srgrimes 5851592Srgrimesvoid 5861592Srgrimessetup_term(fd) 5871592Srgrimes int fd; 5881592Srgrimes{ 5891592Srgrimes register char *cp = index(term+ENVSIZE, '/'); 5901592Srgrimes char *speed; 5911592Srgrimes struct termios tt; 5921592Srgrimes 5931592Srgrimes#ifndef notyet 5941592Srgrimes tcgetattr(fd, &tt); 5951592Srgrimes if (cp) { 5961592Srgrimes *cp++ = '\0'; 5971592Srgrimes speed = cp; 5981592Srgrimes cp = index(speed, '/'); 5991592Srgrimes if (cp) 6001592Srgrimes *cp++ = '\0'; 6011592Srgrimes cfsetspeed(&tt, atoi(speed)); 6021592Srgrimes } 6031592Srgrimes 6041592Srgrimes tt.c_iflag = TTYDEF_IFLAG; 6051592Srgrimes tt.c_oflag = TTYDEF_OFLAG; 6061592Srgrimes tt.c_lflag = TTYDEF_LFLAG; 6071592Srgrimes tcsetattr(fd, TCSAFLUSH, &tt); 6081592Srgrimes#else 6091592Srgrimes if (cp) { 6101592Srgrimes *cp++ = '\0'; 6111592Srgrimes speed = cp; 6121592Srgrimes cp = index(speed, '/'); 6131592Srgrimes if (cp) 6141592Srgrimes *cp++ = '\0'; 6151592Srgrimes tcgetattr(fd, &tt); 6161592Srgrimes cfsetspeed(&tt, atoi(speed)); 6171592Srgrimes tcsetattr(fd, TCSAFLUSH, &tt); 6181592Srgrimes } 6191592Srgrimes#endif 6201592Srgrimes 6211592Srgrimes env[0] = term; 6221592Srgrimes env[1] = 0; 6231592Srgrimes environ = env; 6241592Srgrimes} 6251592Srgrimes 6261592Srgrimesvoid 6271592Srgrimesusage() 6281592Srgrimes{ 62951433Smarkm syslog(LOG_ERR, "usage: rlogind [-" ARGSTR "]"); 6301592Srgrimes} 631