rlogind.c revision 296109
11592Srgrimes/*- 21592Srgrimes * Copyright (c) 1983, 1988, 1989, 1993 31592Srgrimes * The Regents of the University of California. All rights reserved. 496196Sdes * Copyright (c) 2002 Networks Associates Technology, Inc. 596196Sdes * All rights reserved. 61592Srgrimes * 796196Sdes * Portions of this software were developed for the FreeBSD Project by 896196Sdes * ThinkSec AS and NAI Labs, the Security Research Division of Network 996196Sdes * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 1096196Sdes * ("CBOSS"), as part of the DARPA CHATS research program. 1196196Sdes * 121592Srgrimes * Redistribution and use in source and binary forms, with or without 131592Srgrimes * modification, are permitted provided that the following conditions 141592Srgrimes * are met: 151592Srgrimes * 1. Redistributions of source code must retain the above copyright 161592Srgrimes * notice, this list of conditions and the following disclaimer. 171592Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 181592Srgrimes * notice, this list of conditions and the following disclaimer in the 191592Srgrimes * documentation and/or other materials provided with the distribution. 20262136Sbrueffer * 3. Neither the name of the University nor the names of its contributors 211592Srgrimes * may be used to endorse or promote products derived from this software 221592Srgrimes * without specific prior written permission. 231592Srgrimes * 241592Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 251592Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 261592Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 271592Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 281592Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 291592Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 301592Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 311592Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 321592Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 331592Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 341592Srgrimes * SUCH DAMAGE. 351592Srgrimes */ 361592Srgrimes 37114624Sobrien#if 0 381592Srgrimes#ifndef lint 3929916Smarkmstatic const char copyright[] = 401592Srgrimes"@(#) Copyright (c) 1983, 1988, 1989, 1993\n\ 411592Srgrimes The Regents of the University of California. All rights reserved.\n"; 421592Srgrimes#endif /* not lint */ 431592Srgrimes 441592Srgrimes#ifndef lint 4529916Smarkmstatic const char sccsid[] = "@(#)rlogind.c 8.1 (Berkeley) 6/4/93"; 46114624Sobrien#endif /* not lint */ 4731405Scharnier#endif 48114624Sobrien#include <sys/cdefs.h> 49114624Sobrien__FBSDID("$FreeBSD: head/libexec/rlogind/rlogind.c 296109 2016-02-26 20:02:01Z pfg $"); 501592Srgrimes 511592Srgrimes/* 521592Srgrimes * remote login server: 531592Srgrimes * \0 541592Srgrimes * remuser\0 551592Srgrimes * locuser\0 561592Srgrimes * terminal_type/speed\0 571592Srgrimes * data 581592Srgrimes */ 591592Srgrimes 601592Srgrimes#define FD_SETSIZE 16 /* don't need many bits for select */ 6129916Smarkm#include <sys/types.h> 621592Srgrimes#include <sys/param.h> 631592Srgrimes#include <sys/stat.h> 641592Srgrimes#include <sys/ioctl.h> 651592Srgrimes#include <signal.h> 661592Srgrimes#include <termios.h> 671592Srgrimes 681592Srgrimes#include <sys/socket.h> 691592Srgrimes#include <netinet/in.h> 701592Srgrimes#include <netinet/in_systm.h> 711592Srgrimes#include <netinet/ip.h> 7211486Sdg#include <netinet/tcp.h> 731592Srgrimes#include <arpa/inet.h> 741592Srgrimes#include <netdb.h> 751592Srgrimes 7631405Scharnier#include <errno.h> 7731405Scharnier#include <libutil.h> 7896196Sdes#include <paths.h> 79296109Spfg#include <poll.h> 801592Srgrimes#include <pwd.h> 811592Srgrimes#include <syslog.h> 821592Srgrimes#include <stdio.h> 831592Srgrimes#include <stdlib.h> 841592Srgrimes#include <string.h> 8531405Scharnier#include <unistd.h> 861592Srgrimes 8751433Smarkm 881592Srgrimes#ifndef TIOCPKT_WINDOW 891592Srgrimes#define TIOCPKT_WINDOW 0x80 901592Srgrimes#endif 911592Srgrimes 92141588Sru#define ARGSTR "Daln" 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 10556590Sshinunion sockunion { 10656590Sshin struct sockinet { 10756590Sshin u_char si_len; 10856590Sshin u_char si_family; 10956590Sshin u_short si_port; 11056590Sshin } su_si; 11156590Sshin struct sockaddr_in su_sin; 11256590Sshin struct sockaddr_in6 su_sin6; 11356590Sshin}; 11456590Sshin#define su_len su_si.si_len 11556590Sshin#define su_family su_si.si_family 11656590Sshin#define su_port su_si.si_port 11756590Sshin 11890377Simpvoid doit(int, union sockunion *); 11990377Simpint control(int, char *, int); 12090377Simpvoid protocol(int, int); 12190377Simpvoid cleanup(int); 12290377Simpvoid fatal(int, char *, int); 12390377Simpint do_rlogin(union sockunion *); 12490377Simpvoid getstr(char *, int, char *); 12590377Simpvoid setup_term(int); 12690377Simpint do_krb_login(struct sockaddr_in *); 12790377Simpvoid usage(void); 1281592Srgrimes 12951433Smarkm 1301592Srgrimesint 13190377Simpmain(int argc, char *argv[]) 1321592Srgrimes{ 1331592Srgrimes extern int __check_rhosts_file; 13456590Sshin union sockunion from; 135141918Sstefanf socklen_t fromlen; 136141918Sstefanf int ch, on; 1371592Srgrimes 1381592Srgrimes openlog("rlogind", LOG_PID | LOG_CONS, LOG_AUTH); 1391592Srgrimes 1401592Srgrimes opterr = 0; 14124349Simp while ((ch = getopt(argc, argv, ARGSTR)) != -1) 1421592Srgrimes switch (ch) { 14311486Sdg case 'D': 14411486Sdg no_delay = 1; 14511486Sdg break; 1461592Srgrimes case 'a': 1471592Srgrimes check_all = 1; 1481592Srgrimes break; 1491592Srgrimes case 'l': 1501592Srgrimes __check_rhosts_file = 0; 1511592Srgrimes break; 1521592Srgrimes case 'n': 1531592Srgrimes keepalive = 0; 1541592Srgrimes break; 1551592Srgrimes case '?': 1561592Srgrimes default: 1571592Srgrimes usage(); 1581592Srgrimes break; 1591592Srgrimes } 1601592Srgrimes argc -= optind; 1611592Srgrimes argv += optind; 1621592Srgrimes 1631592Srgrimes fromlen = sizeof (from); 1641592Srgrimes if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { 1651592Srgrimes syslog(LOG_ERR,"Can't get peer name of remote host: %m"); 1661592Srgrimes fatal(STDERR_FILENO, "Can't get peer name of remote host", 1); 1671592Srgrimes } 1681592Srgrimes on = 1; 1691592Srgrimes if (keepalive && 1701592Srgrimes setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) 1711592Srgrimes syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); 17211486Sdg if (no_delay && 17311486Sdg setsockopt(0, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0) 17411486Sdg syslog(LOG_WARNING, "setsockopt (TCP_NODELAY): %m"); 17596196Sdes if (from.su_family == AF_INET) 17656590Sshin { 1771592Srgrimes on = IPTOS_LOWDELAY; 1781592Srgrimes if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) 1791592Srgrimes syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); 18056590Sshin } 18111486Sdg 1821592Srgrimes doit(0, &from); 18329916Smarkm return 0; 1841592Srgrimes} 1851592Srgrimes 1861592Srgrimesint child; 1871592Srgrimesint netf; 1881592Srgrimeschar line[MAXPATHLEN]; 1891592Srgrimesint confirmed; 1901592Srgrimes 1911592Srgrimesstruct winsize win = { 0, 0, 0, 0 }; 1921592Srgrimes 1931592Srgrimes 1941592Srgrimesvoid 19590377Simpdoit(int f, union sockunion *fromp) 1961592Srgrimes{ 1971592Srgrimes int master, pid, on = 1; 1981592Srgrimes int authenticated = 0; 19956590Sshin char hostname[2 * MAXHOSTNAMELEN + 1]; 20056590Sshin char nameinfo[2 * INET6_ADDRSTRLEN + 1]; 2011592Srgrimes char c; 2021592Srgrimes 2031592Srgrimes alarm(60); 2041592Srgrimes read(f, &c, 1); 2051592Srgrimes 2061592Srgrimes if (c != 0) 2071592Srgrimes exit(1); 2081592Srgrimes 2091592Srgrimes alarm(0); 21056590Sshin 21156590Sshin realhostname_sa(hostname, sizeof(hostname) - 1, 21256590Sshin (struct sockaddr *)fromp, fromp->su_len); 21356590Sshin /* error check ? */ 21456590Sshin fromp->su_port = ntohs((u_short)fromp->su_port); 21524191Simp hostname[sizeof(hostname) - 1] = '\0'; 2161592Srgrimes 2171592Srgrimes { 21863959Sume if ((fromp->su_family != AF_INET 21956590Sshin#ifdef INET6 22063959Sume && fromp->su_family != AF_INET6 22156590Sshin#endif 22256590Sshin ) || 22356590Sshin fromp->su_port >= IPPORT_RESERVED || 22456590Sshin fromp->su_port < IPPORT_RESERVED/2) { 22556590Sshin getnameinfo((struct sockaddr *)fromp, 22656590Sshin fromp->su_len, 22756590Sshin nameinfo, sizeof(nameinfo), NULL, 0, 228146187Sume NI_NUMERICHOST); 22956590Sshin /* error check ? */ 2301592Srgrimes syslog(LOG_NOTICE, "Connection from %s on illegal port", 23156590Sshin nameinfo); 2321592Srgrimes fatal(f, "Permission denied", 0); 2331592Srgrimes } 2341592Srgrimes#ifdef IP_OPTIONS 23556590Sshin if (fromp->su_family == AF_INET) 23696196Sdes { 23722455Simp u_char optbuf[BUFSIZ/3]; 238141918Sstefanf socklen_t optsize = sizeof(optbuf); 239141918Sstefanf int ipproto, i; 2401592Srgrimes struct protoent *ip; 2411592Srgrimes 2421592Srgrimes if ((ip = getprotobyname("ip")) != NULL) 2431592Srgrimes ipproto = ip->p_proto; 2441592Srgrimes else 2451592Srgrimes ipproto = IPPROTO_IP; 2461592Srgrimes if (getsockopt(0, ipproto, IP_OPTIONS, (char *)optbuf, 2471592Srgrimes &optsize) == 0 && optsize != 0) { 24822455Simp for (i = 0; i < optsize; ) { 24922455Simp u_char c = optbuf[i]; 25022455Simp if (c == IPOPT_LSRR || c == IPOPT_SSRR) { 25122455Simp syslog(LOG_NOTICE, 25222455Simp "Connection refused from %s with IP option %s", 25356590Sshin inet_ntoa(fromp->su_sin.sin_addr), 25422455Simp c == IPOPT_LSRR ? "LSRR" : "SSRR"); 25522455Simp exit(1); 25622455Simp } 25722455Simp if (c == IPOPT_EOL) 25822455Simp break; 25922455Simp i += (c == IPOPT_NOP) ? 1 : optbuf[i+1]; 2601592Srgrimes } 2611592Srgrimes } 26256590Sshin } 2631592Srgrimes#endif 2641592Srgrimes if (do_rlogin(fromp) == 0) 2651592Srgrimes authenticated++; 2661592Srgrimes } 2671592Srgrimes if (confirmed == 0) { 2681592Srgrimes write(f, "", 1); 2691592Srgrimes confirmed = 1; /* we sent the null! */ 2701592Srgrimes } 2711592Srgrimes netf = f; 2721592Srgrimes 2731592Srgrimes pid = forkpty(&master, line, NULL, &win); 2741592Srgrimes if (pid < 0) { 2751592Srgrimes if (errno == ENOENT) 2761592Srgrimes fatal(f, "Out of ptys", 0); 2771592Srgrimes else 2781592Srgrimes fatal(f, "Forkpty", 1); 2791592Srgrimes } 2801592Srgrimes if (pid == 0) { 2811592Srgrimes if (f > 2) /* f should always be 0, but... */ 2821592Srgrimes (void) close(f); 2831592Srgrimes setup_term(0); 28412575Snate if (*lusername=='-') { 2852076Sguido syslog(LOG_ERR, "tried to pass user \"%s\" to login", 2862076Sguido lusername); 2872076Sguido fatal(STDERR_FILENO, "invalid user", 0); 2882076Sguido } 2891592Srgrimes if (authenticated) { 2901592Srgrimes execl(_PATH_LOGIN, "login", "-p", 2911592Srgrimes "-h", hostname, "-f", lusername, (char *)NULL); 2921592Srgrimes } else 2931592Srgrimes execl(_PATH_LOGIN, "login", "-p", 2941592Srgrimes "-h", hostname, lusername, (char *)NULL); 2951592Srgrimes fatal(STDERR_FILENO, _PATH_LOGIN, 1); 2961592Srgrimes /*NOTREACHED*/ 2971592Srgrimes } 298141588Sru ioctl(f, FIONBIO, &on); 2991592Srgrimes ioctl(master, FIONBIO, &on); 3001592Srgrimes ioctl(master, TIOCPKT, &on); 3011592Srgrimes signal(SIGCHLD, cleanup); 3021592Srgrimes protocol(f, master); 3031592Srgrimes signal(SIGCHLD, SIG_IGN); 3041592Srgrimes cleanup(0); 3051592Srgrimes} 3061592Srgrimes 3071592Srgrimeschar magic[2] = { 0377, 0377 }; 3081592Srgrimeschar oobdata[] = {TIOCPKT_WINDOW}; 3091592Srgrimes 3101592Srgrimes/* 3111592Srgrimes * Handle a "control" request (signaled by magic being present) 3121592Srgrimes * in the data stream. For now, we are only willing to handle 3131592Srgrimes * window size changes. 3141592Srgrimes */ 3151592Srgrimesint 31690377Simpcontrol(int pty, char *cp, int n) 3171592Srgrimes{ 3181592Srgrimes struct winsize w; 3191592Srgrimes 320114624Sobrien if (n < 4 + (int)sizeof(w) || cp[2] != 's' || cp[3] != 's') 3211592Srgrimes return (0); 3221592Srgrimes oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */ 3231592Srgrimes bcopy(cp+4, (char *)&w, sizeof(w)); 3241592Srgrimes w.ws_row = ntohs(w.ws_row); 3251592Srgrimes w.ws_col = ntohs(w.ws_col); 3261592Srgrimes w.ws_xpixel = ntohs(w.ws_xpixel); 3271592Srgrimes w.ws_ypixel = ntohs(w.ws_ypixel); 3281592Srgrimes (void)ioctl(pty, TIOCSWINSZ, &w); 3291592Srgrimes return (4+sizeof (w)); 3301592Srgrimes} 3311592Srgrimes 3321592Srgrimes/* 3331592Srgrimes * rlogin "protocol" machine. 3341592Srgrimes */ 3351592Srgrimesvoid 33690377Simpprotocol(int f, int p) 3371592Srgrimes{ 33869705Sru char pibuf[1024+1], fibuf[1024], *pbp = NULL, *fbp = NULL; 33946078Simp int pcc = 0, fcc = 0; 3401592Srgrimes int cc, nfd, n; 3411592Srgrimes char cntl; 3421592Srgrimes 3431592Srgrimes /* 3441592Srgrimes * Must ignore SIGTTOU, otherwise we'll stop 3451592Srgrimes * when we try and set slave pty's window shape 3461592Srgrimes * (our controlling tty is the master pty). 3471592Srgrimes */ 3481592Srgrimes (void) signal(SIGTTOU, SIG_IGN); 3491592Srgrimes send(f, oobdata, 1, MSG_OOB); /* indicate new rlogin */ 3501592Srgrimes if (f > p) 3511592Srgrimes nfd = f + 1; 3521592Srgrimes else 3531592Srgrimes nfd = p + 1; 3541592Srgrimes for (;;) { 355296109Spfg struct pollfd set[2]; 3561592Srgrimes 357296109Spfg set[0].fd = p; 358296109Spfg set[0].events = POLLPRI; 359296109Spfg set[1].fd = f; 360296109Spfg set[1].events = 0; 361296109Spfg if (fcc) 362296109Spfg set[0].events |= POLLOUT; 363296109Spfg else 364296109Spfg set[1].events |= POLLIN; 36546078Simp if (pcc >= 0) { 366296109Spfg if (pcc) 367296109Spfg set[1].events |= POLLOUT; 368296109Spfg else 369296109Spfg set[0].events |= POLLIN; 37046078Simp } 371296109Spfg if ((n = poll(set, 2, INFTIM)) < 0) { 3721592Srgrimes if (errno == EINTR) 3731592Srgrimes continue; 374296109Spfg fatal(f, "poll", 1); 3751592Srgrimes } 3761592Srgrimes if (n == 0) { 3771592Srgrimes /* shouldn't happen... */ 3781592Srgrimes sleep(5); 3791592Srgrimes continue; 3801592Srgrimes } 3811592Srgrimes#define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP)) 382296109Spfg if (set[0].revents & POLLPRI) { 3831592Srgrimes cc = read(p, &cntl, 1); 3841592Srgrimes if (cc == 1 && pkcontrol(cntl)) { 3851592Srgrimes cntl |= oobdata[0]; 3861592Srgrimes send(f, &cntl, 1, MSG_OOB); 387296109Spfg if (cntl & TIOCPKT_FLUSHWRITE) 3881592Srgrimes pcc = 0; 3891592Srgrimes } 3901592Srgrimes } 391296109Spfg if (set[1].revents & POLLIN) { 392141588Sru fcc = read(f, fibuf, sizeof(fibuf)); 3931592Srgrimes if (fcc < 0 && errno == EWOULDBLOCK) 3941592Srgrimes fcc = 0; 3951592Srgrimes else { 39690377Simp char *cp; 3971592Srgrimes int left, n; 3981592Srgrimes 3991592Srgrimes if (fcc <= 0) 4001592Srgrimes break; 4011592Srgrimes fbp = fibuf; 4021592Srgrimes 4031592Srgrimes top: 4041592Srgrimes for (cp = fibuf; cp < fibuf+fcc-1; cp++) 4051592Srgrimes if (cp[0] == magic[0] && 4061592Srgrimes cp[1] == magic[1]) { 4071592Srgrimes left = fcc - (cp-fibuf); 4081592Srgrimes n = control(p, cp, left); 4091592Srgrimes if (n) { 4101592Srgrimes left -= n; 4111592Srgrimes if (left > 0) 4121592Srgrimes bcopy(cp+n, cp, left); 4131592Srgrimes fcc -= n; 4141592Srgrimes goto top; /* n^2 */ 4151592Srgrimes } 4161592Srgrimes } 4171592Srgrimes } 4181592Srgrimes } 4191592Srgrimes 420296109Spfg if (set[0].revents & POLLOUT && fcc > 0) { 4211592Srgrimes cc = write(p, fbp, fcc); 4221592Srgrimes if (cc > 0) { 4231592Srgrimes fcc -= cc; 4241592Srgrimes fbp += cc; 4251592Srgrimes } 4261592Srgrimes } 4271592Srgrimes 428296109Spfg if (set[0].revents & POLLIN) { 4291592Srgrimes pcc = read(p, pibuf, sizeof (pibuf)); 4301592Srgrimes pbp = pibuf; 4311592Srgrimes if (pcc < 0 && errno == EWOULDBLOCK) 4321592Srgrimes pcc = 0; 4331592Srgrimes else if (pcc <= 0) 4341592Srgrimes break; 4351592Srgrimes else if (pibuf[0] == 0) { 4361592Srgrimes pbp++, pcc--; 4371592Srgrimes } else { 4381592Srgrimes if (pkcontrol(pibuf[0])) { 4391592Srgrimes pibuf[0] |= oobdata[0]; 4401592Srgrimes send(f, &pibuf[0], 1, MSG_OOB); 4411592Srgrimes } 4421592Srgrimes pcc = 0; 4431592Srgrimes } 4441592Srgrimes } 445296109Spfg if (set[1].revents & POLLOUT && pcc > 0) { 446141588Sru cc = write(f, pbp, pcc); 4471592Srgrimes if (cc > 0) { 4481592Srgrimes pcc -= cc; 4491592Srgrimes pbp += cc; 4501592Srgrimes } 4511592Srgrimes } 4521592Srgrimes } 4531592Srgrimes} 4541592Srgrimes 4551592Srgrimesvoid 456216584Scharniercleanup(int signo __unused) 4571592Srgrimes{ 4581592Srgrimes 459146075Sjmallett shutdown(netf, SHUT_RDWR); 4601592Srgrimes exit(1); 4611592Srgrimes} 4621592Srgrimes 4631592Srgrimesvoid 46490377Simpfatal(int f, char *msg, int syserr) 4651592Srgrimes{ 4661592Srgrimes int len; 4671592Srgrimes char buf[BUFSIZ], *bp = buf; 4681592Srgrimes 4691592Srgrimes /* 4701592Srgrimes * Prepend binary one to message if we haven't sent 4711592Srgrimes * the magic null as confirmation. 4721592Srgrimes */ 4731592Srgrimes if (!confirmed) 4741592Srgrimes *bp++ = '\01'; /* error indicator */ 4751592Srgrimes if (syserr) 47664238Skris len = snprintf(bp, sizeof(buf), "rlogind: %s: %s.\r\n", 4771592Srgrimes msg, strerror(errno)); 4781592Srgrimes else 47964238Skris len = snprintf(bp, sizeof(buf), "rlogind: %s.\r\n", msg); 48081991Sbrian if (len < 0) 48181972Sbrian len = 0; 4821592Srgrimes (void) write(f, buf, bp + len - buf); 4831592Srgrimes exit(1); 4841592Srgrimes} 4851592Srgrimes 4861592Srgrimesint 48790377Simpdo_rlogin(union sockunion *dest) 4881592Srgrimes{ 48966755Sru 4901592Srgrimes getstr(rusername, sizeof(rusername), "remuser too long"); 4911592Srgrimes getstr(lusername, sizeof(lusername), "locuser too long"); 4921592Srgrimes getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type too long"); 4931592Srgrimes 4941592Srgrimes pwd = getpwnam(lusername); 4951592Srgrimes if (pwd == NULL) 4961592Srgrimes return (-1); 4971592Srgrimes /* XXX why don't we syslog() failure? */ 49856590Sshin 49956939Sshin return (iruserok_sa(dest, dest->su_len, pwd->pw_uid == 0, rusername, 50056939Sshin lusername)); 5011592Srgrimes} 5021592Srgrimes 5031592Srgrimesvoid 50490377Simpgetstr(char *buf, int cnt, char *errmsg) 5051592Srgrimes{ 5061592Srgrimes char c; 5071592Srgrimes 5081592Srgrimes do { 50980381Ssheldonh if (read(STDIN_FILENO, &c, 1) != 1) 5101592Srgrimes exit(1); 5111592Srgrimes if (--cnt < 0) 5121592Srgrimes fatal(STDOUT_FILENO, errmsg, 0); 5131592Srgrimes *buf++ = c; 5141592Srgrimes } while (c != 0); 5151592Srgrimes} 5161592Srgrimes 5171592Srgrimesextern char **environ; 5181592Srgrimes 5191592Srgrimesvoid 52090377Simpsetup_term(int fd) 5211592Srgrimes{ 522229403Sed char *cp; 5231592Srgrimes char *speed; 524214680Sed struct termios tt, def; 5251592Srgrimes 526229403Sed cp = strchr(term + ENVSIZE, '/'); 5271592Srgrimes#ifndef notyet 5281592Srgrimes tcgetattr(fd, &tt); 5291592Srgrimes if (cp) { 5301592Srgrimes *cp++ = '\0'; 5311592Srgrimes speed = cp; 532229403Sed cp = strchr(speed, '/'); 5331592Srgrimes if (cp) 5341592Srgrimes *cp++ = '\0'; 5351592Srgrimes cfsetspeed(&tt, atoi(speed)); 5361592Srgrimes } 5371592Srgrimes 538214680Sed cfmakesane(&def); 539214680Sed tt.c_iflag = def.c_iflag; 540214680Sed tt.c_oflag = def.c_oflag; 541214680Sed tt.c_lflag = def.c_lflag; 5421592Srgrimes tcsetattr(fd, TCSAFLUSH, &tt); 5431592Srgrimes#else 5441592Srgrimes if (cp) { 5451592Srgrimes *cp++ = '\0'; 5461592Srgrimes speed = cp; 547229403Sed cp = strchr(speed, '/'); 5481592Srgrimes if (cp) 5491592Srgrimes *cp++ = '\0'; 5501592Srgrimes tcgetattr(fd, &tt); 5511592Srgrimes cfsetspeed(&tt, atoi(speed)); 5521592Srgrimes tcsetattr(fd, TCSAFLUSH, &tt); 5531592Srgrimes } 5541592Srgrimes#endif 5551592Srgrimes 5561592Srgrimes env[0] = term; 5571592Srgrimes env[1] = 0; 5581592Srgrimes environ = env; 5591592Srgrimes} 5601592Srgrimes 5611592Srgrimesvoid 56290377Simpusage(void) 5631592Srgrimes{ 56451433Smarkm syslog(LOG_ERR, "usage: rlogind [-" ARGSTR "]"); 5651592Srgrimes} 566