121174Sdist /* 236517Skarels * Copyright (c) 1983, 1988 The Regents of the University of California. 335441Sbostic * All rights reserved. 435441Sbostic * 535441Sbostic * Redistribution and use in source and binary forms are permitted 635441Sbostic * provided that the above copyright notice and this paragraph are 735441Sbostic * duplicated in all such forms and that any documentation, 835441Sbostic * advertising materials, and other materials related to such 935441Sbostic * distribution and use acknowledge that the software was developed 1035441Sbostic * by the University of California, Berkeley. The name of the 1135441Sbostic * University may not be used to endorse or promote products derived 1235441Sbostic * from this software without specific prior written permission. 1335441Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1435441Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1535441Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621174Sdist */ 1721174Sdist 186446Swnj #ifndef lint 1921174Sdist char copyright[] = 2036517Skarels "@(#) Copyright (c) 1983, 1988 The Regents of the University of California.\n\ 2121174Sdist All rights reserved.\n"; 2235441Sbostic #endif /* not lint */ 236446Swnj 2421174Sdist #ifndef lint 25*36715Skfall static char sccsid[] = "@(#)rlogind.c 5.34 (Berkeley) 02/09/89"; 2635441Sbostic #endif /* not lint */ 2721174Sdist 2816369Skarels /* 2916369Skarels * remote login server: 3036453Skfall * \0 3116369Skarels * remuser\0 3216369Skarels * locuser\0 3336453Skfall * terminal_type/speed\0 3436518Skarels * data 3516369Skarels */ 3616369Skarels 376446Swnj #include <stdio.h> 3836711Skfall #include <sys/types.h> 396446Swnj #include <sys/stat.h> 406446Swnj #include <sys/socket.h> 4113554Ssam #include <sys/wait.h> 4218357Ssam #include <sys/file.h> 4336711Skfall #include <sys/param.h> 449208Ssam 459208Ssam #include <netinet/in.h> 469208Ssam 476446Swnj #include <errno.h> 486446Swnj #include <pwd.h> 496446Swnj #include <signal.h> 5036711Skfall #include <sys/ioctl.h> 5136711Skfall #include <sys/termios.h> 526446Swnj #include <stdio.h> 538380Ssam #include <netdb.h> 5417187Sralph #include <syslog.h> 5518357Ssam #include <strings.h> 566446Swnj 5736518Skarels #ifndef TIOCPKT_WINDOW 5836518Skarels #define TIOCPKT_WINDOW 0x80 5936518Skarels #endif 6036518Skarels 6136711Skfall #ifdef KERBEROS 6236711Skfall #include <kerberos/krb.h> 6336711Skfall #define SECURE_MESSAGE "This rlogin session is using DES encryption for all transmissions.\r\n" 6436711Skfall 6536711Skfall AUTH_DAT *kdata; 6636711Skfall KTEXT ticket; 6736711Skfall u_char auth_buf[sizeof(AUTH_DAT)]; 6836711Skfall u_char tick_buf[sizeof(KTEXT_ST)]; 6936711Skfall Key_schedule schedule; 7036711Skfall int encrypt = 0, retval, use_kerberos = 0, vacuous = 0; 7136711Skfall int do_krb_login(); 7236711Skfall 73*36715Skfall #define ARGSTR "lnkvx" 7436711Skfall #else 7536711Skfall #define ARGSTR "ln" 7636711Skfall #endif /* KERBEROS */ 7736711Skfall 7836518Skarels char *env[2]; 7936518Skarels #define NMAX 30 8036517Skarels char lusername[NMAX+1], rusername[NMAX+1]; 8136517Skarels static char term[64] = "TERM="; 8236517Skarels #define ENVSIZE (sizeof("TERM=")-1) /* skip null for concatenation */ 8336517Skarels int keepalive = 1; 8436453Skfall 8536453Skfall #define SUPERUSER(pwd) ((pwd)->pw_uid == 0) 8636453Skfall 8734424Sbostic extern int errno; 8810417Ssam int reapchild(); 8936453Skfall struct passwd *getpwnam(), *pwd; 9024723Smckusick char *malloc(); 9116369Skarels 926446Swnj main(argc, argv) 936446Swnj int argc; 946446Swnj char **argv; 956446Swnj { 9636319Sbostic extern int opterr, optind, _check_rhosts_file; 9736319Sbostic int ch; 9834424Sbostic int on = 1, fromlen; 996446Swnj struct sockaddr_in from; 1006446Swnj 10136625Skfall openlog("rlogind", LOG_PID | LOG_CONS, LOG_AUTH); 10236319Sbostic 10336319Sbostic opterr = 0; 10436711Skfall while ((ch = getopt(argc, argv, ARGSTR)) != EOF) 10536517Skarels switch (ch) { 10636319Sbostic case 'l': 10736319Sbostic _check_rhosts_file = 0; 10836319Sbostic break; 10936517Skarels case 'n': 11036517Skarels keepalive = 0; 11136517Skarels break; 11236711Skfall #ifdef KERBEROS 11336711Skfall case 'k': 11436711Skfall use_kerberos = 1; 11536711Skfall break; 11636711Skfall case 'v': 11736711Skfall vacuous = 1; 11836711Skfall break; 119*36715Skfall case 'x': 120*36715Skfall encrypt = 1; 121*36715Skfall break; 12236711Skfall #endif 12336319Sbostic case '?': 12436319Sbostic default: 12536711Skfall usage(); 12636319Sbostic break; 12736319Sbostic } 12836319Sbostic argc -= optind; 12936319Sbostic argv += optind; 13036319Sbostic 13136711Skfall #ifdef KERBEROS 13236711Skfall if (use_kerberos && vacuous) { 13336711Skfall usage(); 13436711Skfall fatal("only one of -k and -v allowed\n"); 13536711Skfall } 13636711Skfall #endif 13716369Skarels fromlen = sizeof (from); 13816369Skarels if (getpeername(0, &from, &fromlen) < 0) { 13936711Skfall syslog(LOG_ERR,"Can't get peer name of remote host: %m"); 14036711Skfall fatalperror("Can't get peer name of remote host"); 1418380Ssam } 14236517Skarels if (keepalive && 14336517Skarels setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) 14417187Sralph syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); 14516369Skarels doit(0, &from); 1466446Swnj } 1476446Swnj 1486446Swnj int child; 1496446Swnj int cleanup(); 1506446Swnj int netf; 1516446Swnj char *line; 15224724Smckusick extern char *inet_ntoa(); 1536446Swnj 15424889Smckusick struct winsize win = { 0, 0, 0, 0 }; 15524723Smckusick 15624889Smckusick 1576446Swnj doit(f, fromp) 1586446Swnj int f; 1596446Swnj struct sockaddr_in *fromp; 1606446Swnj { 16118357Ssam int i, p, t, pid, on = 1; 16236631Skarels int authenticated = 0, hostok = 0; 16336711Skfall register struct hostent *hp; 16436703Skarels char remotehost[2 * MAXHOSTNAMELEN + 1]; 16524724Smckusick struct hostent hostent; 1668380Ssam char c; 1676446Swnj 1686446Swnj alarm(60); 1696446Swnj read(f, &c, 1); 17036711Skfall 171*36715Skfall if(c != 0) 172*36715Skfall exit(1); 17336711Skfall #ifdef KERBEROS 174*36715Skfall if(vacuous) 175*36715Skfall fatal(f, "Remote host requires Kerberos authentication"); 17636711Skfall #endif 17736453Skfall 1786446Swnj alarm(0); 17916227Skarels fromp->sin_port = ntohs((u_short)fromp->sin_port); 1808380Ssam hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr), 1818380Ssam fromp->sin_family); 18211345Ssam if (hp == 0) { 18324724Smckusick /* 18424724Smckusick * Only the name is used below. 18524724Smckusick */ 18624724Smckusick hp = &hostent; 18724724Smckusick hp->h_name = inet_ntoa(fromp->sin_addr); 18836635Skarels hostok++; 18936711Skfall } else if (local_domain(hp->h_name)) { 19036635Skarels /* 19136635Skarels * If name returned by gethostbyaddr is in our domain, 19236635Skarels * attempt to verify that we haven't been fooled by someone 19336635Skarels * in a remote net; look up the name and check that this 19436635Skarels * address corresponds to the name. 19536635Skarels */ 19636635Skarels strncpy(remotehost, hp->h_name, sizeof(remotehost) - 1); 19736635Skarels remotehost[sizeof(remotehost) - 1] = 0; 19836635Skarels hp = gethostbyname(remotehost); 19936635Skarels if (hp) 20036635Skarels for (; hp->h_addr_list[0]; hp->h_addr_list++) 20136635Skarels if (!bcmp(hp->h_addr_list[0], (caddr_t)&fromp->sin_addr, 20236635Skarels sizeof(fromp->sin_addr))) { 20336635Skarels hostok++; 20436635Skarels break; 20536635Skarels } 20636633Skarels } else 20736635Skarels hostok++; 20836711Skfall 20936711Skfall #ifdef KERBEROS 21036711Skfall if (use_kerberos) { 21136711Skfall retval = do_krb_login(hp->h_name, fromp, encrypt); 21236711Skfall write(f, &c, 1); 21336711Skfall if (retval == 0 && hostok) 21436711Skfall authenticated++; 21536711Skfall else if (retval > 0) 21636711Skfall fatal(f, krb_err_txt[retval]); 21736711Skfall else if(!hostok) 21836711Skfall fatal(f, "krlogind: Host address mismatch.\r\n"); 21936711Skfall } else 22036703Skarels #endif 22136711Skfall { 22236711Skfall if (fromp->sin_family != AF_INET || 22336711Skfall fromp->sin_port >= IPPORT_RESERVED || 22436711Skfall fromp->sin_port < IPPORT_RESERVED/2) { 22536711Skfall syslog(LOG_NOTICE, "Connection from %s on illegal port", 22636711Skfall inet_ntoa(fromp->sin_addr)); 22736711Skfall fatal(f, "Permission denied"); 22836711Skfall } 22936702Skarels #ifdef IP_OPTIONS 23036711Skfall { 23136711Skfall u_char optbuf[BUFSIZ/3], *cp; 23236711Skfall char lbuf[BUFSIZ], *lp; 23336711Skfall int optsize = sizeof(optbuf), ipproto; 23436711Skfall struct protoent *ip; 23536702Skarels 23636711Skfall if ((ip = getprotobyname("ip")) != NULL) 23736711Skfall ipproto = ip->p_proto; 23836711Skfall else 23936711Skfall ipproto = IPPROTO_IP; 24036711Skfall if (getsockopt(0, ipproto, IP_OPTIONS, (char *)optbuf, 24136711Skfall &optsize) == 0 && optsize != 0) { 24236711Skfall lp = lbuf; 24336711Skfall for (cp = optbuf; optsize > 0; cp++, optsize--, lp += 3) 24436711Skfall sprintf(lp, " %2.2x", *cp); 24536711Skfall syslog(LOG_NOTICE, 24636711Skfall "Connection received using IP options (ignored):%s", 24736711Skfall lbuf); 24836711Skfall if (setsockopt(0, ipproto, IP_OPTIONS, 24936711Skfall (char *)NULL, &optsize) != 0) { 25036711Skfall syslog(LOG_ERR, "setsockopt IP_OPTIONS NULL: %m"); 25136711Skfall exit(1); 25236711Skfall } 25336711Skfall } 25436711Skfall } 25536702Skarels #endif 25636711Skfall write(f, "", 1); 25736711Skfall 25836711Skfall if (do_rlogin(hp->h_name) == 0) { 25936711Skfall if (hostok) 26036711Skfall authenticated++; 26136711Skfall else 26236711Skfall write(f, "rlogind: Host address mismatch.\r\n", 26336711Skfall sizeof("rlogind: Host address mismatch.\r\n") - 1); 26436711Skfall } 26536631Skarels } 26636636Skarels 2676446Swnj for (c = 'p'; c <= 's'; c++) { 2686446Swnj struct stat stb; 2696446Swnj line = "/dev/ptyXX"; 2706446Swnj line[strlen("/dev/pty")] = c; 2716446Swnj line[strlen("/dev/ptyp")] = '0'; 2726446Swnj if (stat(line, &stb) < 0) 2736446Swnj break; 2746446Swnj for (i = 0; i < 16; i++) { 27534424Sbostic line[sizeof("/dev/ptyp") - 1] = "0123456789abcdef"[i]; 27634424Sbostic p = open(line, O_RDWR); 2776446Swnj if (p > 0) 2786446Swnj goto gotpty; 2796446Swnj } 2806446Swnj } 28124723Smckusick fatal(f, "Out of ptys"); 2829242Ssam /*NOTREACHED*/ 2836446Swnj gotpty: 28424889Smckusick (void) ioctl(p, TIOCSWINSZ, &win); 28516227Skarels netf = f; 2866446Swnj line[strlen("/dev/")] = 't'; 28734424Sbostic t = open(line, O_RDWR); 28834424Sbostic if (t < 0) 28934424Sbostic fatalperror(f, line); 29034424Sbostic if (fchmod(t, 0)) 29134424Sbostic fatalperror(f, line); 29234424Sbostic (void)signal(SIGHUP, SIG_IGN); 29334424Sbostic vhangup(); 29434424Sbostic (void)signal(SIGHUP, SIG_DFL); 29534424Sbostic t = open(line, O_RDWR); 29634424Sbostic if (t < 0) 29734424Sbostic fatalperror(f, line); 29836453Skfall setup_term(t); 2996446Swnj #ifdef DEBUG 30034424Sbostic { 30134424Sbostic int tt = open("/dev/tty", O_RDWR); 30234424Sbostic if (tt > 0) { 30334424Sbostic (void)ioctl(tt, TIOCNOTTY, 0); 30434424Sbostic (void)close(tt); 30534424Sbostic } 3066446Swnj } 3076446Swnj #endif 3089242Ssam pid = fork(); 3099242Ssam if (pid < 0) 31034424Sbostic fatalperror(f, ""); 31118357Ssam if (pid == 0) { 31236711Skfall if (setsid() < 0) 31336711Skfall fatalperror(f, "setsid"); 31436711Skfall if (ioctl(t, TIOCSCTTY, 0) < 0) 31536711Skfall fatalperror(f, "ioctl(sctty)"); 31618357Ssam close(f), close(p); 31718357Ssam dup2(t, 0), dup2(t, 1), dup2(t, 2); 31816227Skarels close(t); 31936631Skarels if (authenticated) 32036711Skfall execl("/bin/login", "login", "-p", 32136711Skfall "-h", hp->h_name, "-f", lusername, 0); 32236525Skfall else 32336711Skfall execl("/bin/login", "login", "-p", 32436711Skfall "-h", hp->h_name, lusername, 0); 32534424Sbostic fatalperror(2, "/bin/login"); 32618357Ssam /*NOTREACHED*/ 32718357Ssam } 32818357Ssam close(t); 32936453Skfall 33036711Skfall #ifdef KERBEROS 33136711Skfall /* 33236711Skfall * If encrypted, don't turn on NBIO or the des read/write 33336711Skfall * routines will croak. 33436711Skfall */ 33536711Skfall 33636711Skfall if (encrypt) 33736711Skfall (void) des_write(f, SECURE_MESSAGE, sizeof(SECURE_MESSAGE)); 33836711Skfall else 33936711Skfall #endif 34036711Skfall ioctl(f, FIONBIO, &on); 34118357Ssam ioctl(p, FIONBIO, &on); 34218357Ssam ioctl(p, TIOCPKT, &on); 34318357Ssam signal(SIGTSTP, SIG_IGN); 34418357Ssam signal(SIGCHLD, cleanup); 34524724Smckusick setpgrp(0, 0); 34618357Ssam protocol(f, p); 34730600Smckusick signal(SIGCHLD, SIG_IGN); 34818357Ssam cleanup(); 34918357Ssam } 3509242Ssam 35118357Ssam char magic[2] = { 0377, 0377 }; 35225423Skarels char oobdata[] = {TIOCPKT_WINDOW}; 35318357Ssam 35418357Ssam /* 35518357Ssam * Handle a "control" request (signaled by magic being present) 35618357Ssam * in the data stream. For now, we are only willing to handle 35718357Ssam * window size changes. 35818357Ssam */ 35918357Ssam control(pty, cp, n) 36018357Ssam int pty; 36118357Ssam char *cp; 36218357Ssam int n; 36318357Ssam { 36428705Smckusick struct winsize w; 36518357Ssam 36628705Smckusick if (n < 4+sizeof (w) || cp[2] != 's' || cp[3] != 's') 36718357Ssam return (0); 36825423Skarels oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */ 36928705Smckusick bcopy(cp+4, (char *)&w, sizeof(w)); 37028705Smckusick w.ws_row = ntohs(w.ws_row); 37128705Smckusick w.ws_col = ntohs(w.ws_col); 37228705Smckusick w.ws_xpixel = ntohs(w.ws_xpixel); 37328705Smckusick w.ws_ypixel = ntohs(w.ws_ypixel); 37428705Smckusick (void)ioctl(pty, TIOCSWINSZ, &w); 37528705Smckusick return (4+sizeof (w)); 37618357Ssam } 37718357Ssam 37818357Ssam /* 37918357Ssam * rlogin "protocol" machine. 38018357Ssam */ 38118357Ssam protocol(f, p) 38218357Ssam int f, p; 38318357Ssam { 38418357Ssam char pibuf[1024], fibuf[1024], *pbp, *fbp; 38518357Ssam register pcc = 0, fcc = 0; 38636517Skarels int cc, nfd, pmask, fmask; 38725740Skarels char cntl; 38818357Ssam 38918482Ssam /* 39018484Ssam * Must ignore SIGTTOU, otherwise we'll stop 39118484Ssam * when we try and set slave pty's window shape 39225423Skarels * (our controlling tty is the master pty). 39318482Ssam */ 39418484Ssam (void) signal(SIGTTOU, SIG_IGN); 39525423Skarels send(f, oobdata, 1, MSG_OOB); /* indicate new rlogin */ 39636517Skarels if (f > p) 39736517Skarels nfd = f + 1; 39836517Skarels else 39936517Skarels nfd = p + 1; 40036517Skarels fmask = 1 << f; 40136517Skarels pmask = 1 << p; 40218357Ssam for (;;) { 40325740Skarels int ibits, obits, ebits; 40418357Ssam 40525740Skarels ibits = 0; 40625740Skarels obits = 0; 40718357Ssam if (fcc) 40836517Skarels obits |= pmask; 40918357Ssam else 41036517Skarels ibits |= fmask; 41118357Ssam if (pcc >= 0) 41218357Ssam if (pcc) 41336517Skarels obits |= fmask; 4149242Ssam else 41536517Skarels ibits |= pmask; 41636517Skarels ebits = pmask; 41736517Skarels if (select(nfd, &ibits, obits ? &obits : (int *)NULL, 41836517Skarels &ebits, 0) < 0) { 41918357Ssam if (errno == EINTR) 4206446Swnj continue; 42134424Sbostic fatalperror(f, "select"); 42218357Ssam } 42325740Skarels if (ibits == 0 && obits == 0 && ebits == 0) { 42418357Ssam /* shouldn't happen... */ 42518357Ssam sleep(5); 42618357Ssam continue; 42718357Ssam } 42825740Skarels #define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP)) 42936517Skarels if (ebits & pmask) { 43025740Skarels cc = read(p, &cntl, 1); 43125740Skarels if (cc == 1 && pkcontrol(cntl)) { 43225740Skarels cntl |= oobdata[0]; 43325740Skarels send(f, &cntl, 1, MSG_OOB); 43425740Skarels if (cntl & TIOCPKT_FLUSHWRITE) { 43525740Skarels pcc = 0; 43636517Skarels ibits &= ~pmask; 43725740Skarels } 43825740Skarels } 43925740Skarels } 44036517Skarels if (ibits & fmask) { 44136711Skfall #ifdef KERBEROS 44236711Skfall if (encrypt) 44336711Skfall fcc = des_read(f, fibuf, sizeof(fibuf)); 44436711Skfall else 44536711Skfall #endif 44636711Skfall fcc = read(f, fibuf, sizeof(fibuf)); 44718357Ssam if (fcc < 0 && errno == EWOULDBLOCK) 44818357Ssam fcc = 0; 44918357Ssam else { 45018357Ssam register char *cp; 45118357Ssam int left, n; 45218357Ssam 45318357Ssam if (fcc <= 0) 45416227Skarels break; 45518357Ssam fbp = fibuf; 45624723Smckusick 45718357Ssam top: 45825423Skarels for (cp = fibuf; cp < fibuf+fcc-1; cp++) 45918357Ssam if (cp[0] == magic[0] && 46018357Ssam cp[1] == magic[1]) { 46118357Ssam left = fcc - (cp-fibuf); 46218357Ssam n = control(p, cp, left); 46318357Ssam if (n) { 46418357Ssam left -= n; 46518357Ssam if (left > 0) 46625423Skarels bcopy(cp+n, cp, left); 46718357Ssam fcc -= n; 46818357Ssam goto top; /* n^2 */ 46925423Skarels } 47025423Skarels } 47136517Skarels obits |= pmask; /* try write */ 47225423Skarels } 47325423Skarels } 47424723Smckusick 47536517Skarels if ((obits & pmask) && fcc > 0) { 47625423Skarels cc = write(p, fbp, fcc); 47724723Smckusick if (cc > 0) { 47824723Smckusick fcc -= cc; 47924723Smckusick fbp += cc; 4806446Swnj } 48118357Ssam } 48224723Smckusick 48336517Skarels if (ibits & pmask) { 48418357Ssam pcc = read(p, pibuf, sizeof (pibuf)); 48518357Ssam pbp = pibuf; 48618357Ssam if (pcc < 0 && errno == EWOULDBLOCK) 48718357Ssam pcc = 0; 48818357Ssam else if (pcc <= 0) 48918357Ssam break; 49036517Skarels else if (pibuf[0] == 0) { 49118357Ssam pbp++, pcc--; 49236711Skfall #ifdef KERBEROS 49336711Skfall if (!encrypt) 49436711Skfall #endif 49536711Skfall obits |= fmask; /* try a write */ 49636517Skarels } else { 49718357Ssam if (pkcontrol(pibuf[0])) { 49825423Skarels pibuf[0] |= oobdata[0]; 49918357Ssam send(f, &pibuf[0], 1, MSG_OOB); 50016227Skarels } 50118357Ssam pcc = 0; 5026446Swnj } 50318357Ssam } 50436517Skarels if ((obits & fmask) && pcc > 0) { 50536711Skfall #ifdef KERBEROS 50636711Skfall if (encrypt) 50736711Skfall cc = des_write(f, pbp, pcc); 50836711Skfall else 50936711Skfall #endif 51036711Skfall cc = write(f, pbp, pcc); 51125423Skarels if (cc < 0 && errno == EWOULDBLOCK) { 51225423Skarels /* also shouldn't happen */ 51325423Skarels sleep(5); 51425423Skarels continue; 51525423Skarels } 51618357Ssam if (cc > 0) { 51718357Ssam pcc -= cc; 51818357Ssam pbp += cc; 51918357Ssam } 5206446Swnj } 5216446Swnj } 5226446Swnj } 5236446Swnj 5246446Swnj cleanup() 5256446Swnj { 52635440Sbostic char *p; 52735440Sbostic 52835440Sbostic p = line + sizeof("/dev/") - 1; 52935440Sbostic if (logout(p)) 53035440Sbostic logwtmp(p, "", ""); 53135440Sbostic (void)chmod(line, 0666); 53235440Sbostic (void)chown(line, 0, 0); 53335440Sbostic *p = 'p'; 53435440Sbostic (void)chmod(line, 0666); 53535440Sbostic (void)chown(line, 0, 0); 53610192Ssam shutdown(netf, 2); 5376446Swnj exit(1); 5386446Swnj } 5396446Swnj 5409242Ssam fatal(f, msg) 5419242Ssam int f; 5429242Ssam char *msg; 5439242Ssam { 5449242Ssam char buf[BUFSIZ]; 5459242Ssam 5469242Ssam buf[0] = '\01'; /* error indicator */ 54713554Ssam (void) sprintf(buf + 1, "rlogind: %s.\r\n", msg); 5489242Ssam (void) write(f, buf, strlen(buf)); 5499242Ssam exit(1); 5509242Ssam } 5519242Ssam 55234424Sbostic fatalperror(f, msg) 5539242Ssam int f; 5549242Ssam char *msg; 5559242Ssam { 5569242Ssam char buf[BUFSIZ]; 55716227Skarels extern int sys_nerr; 5589242Ssam extern char *sys_errlist[]; 5599242Ssam 56018357Ssam if ((unsigned)errno < sys_nerr) 56116227Skarels (void) sprintf(buf, "%s: %s", msg, sys_errlist[errno]); 56216227Skarels else 56316227Skarels (void) sprintf(buf, "%s: Error %d", msg, errno); 5649242Ssam fatal(f, buf); 5659242Ssam } 56636453Skfall 56736453Skfall do_rlogin(host) 56836518Skarels char *host; 56936453Skfall { 57036453Skfall 57136518Skarels getstr(rusername, sizeof(rusername), "remuser too long"); 57236518Skarels getstr(lusername, sizeof(lusername), "locuser too long"); 57336518Skarels getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type too long"); 57436518Skarels 57536518Skarels if (getuid()) 57636453Skfall return(-1); 57736453Skfall pwd = getpwnam(lusername); 57836518Skarels if (pwd == NULL) 57936453Skfall return(-1); 58036453Skfall return(ruserok(host, SUPERUSER(pwd), rusername, lusername)); 58136453Skfall } 58236453Skfall 58336453Skfall 58436518Skarels getstr(buf, cnt, errmsg) 58536518Skarels char *buf; 58636518Skarels int cnt; 58736518Skarels char *errmsg; 58836453Skfall { 58936518Skarels char c; 59036518Skarels 59136453Skfall do { 59236518Skarels if (read(0, &c, 1) != 1) 59336453Skfall exit(1); 59436518Skarels if (--cnt < 0) 59536518Skarels fatal(1, errmsg); 59636453Skfall *buf++ = c; 59736518Skarels } while (c != 0); 59836453Skfall } 59936453Skfall 60036518Skarels extern char **environ; 60136453Skfall 60236519Skarels setup_term(fd) 60336519Skarels int fd; 60436519Skarels { 60536711Skfall struct termios tt; 60636711Skfall register char *cp = index(term+ENVSIZE, '/'); 60736519Skarels char *speed; 60836519Skarels 60936711Skfall tcgetattr(fd, &tt); 61036519Skarels if (cp) { 61136519Skarels *cp++ = '\0'; 61236519Skarels speed = cp; 61336519Skarels cp = index(speed, '/'); 61436519Skarels if (cp) 61536519Skarels *cp++ = '\0'; 61636711Skfall cfsetspeed(&tt, atoi(speed)); 61736519Skarels } 61836711Skfall tt.c_iflag = BRKINT|ICRNL|IXON|ISTRIP|IEXTEN|IMAXBEL; 61936711Skfall tt.c_oflag = OPOST|ONLCR|OXTABS; 62036711Skfall tt.c_lflag = ISIG|ICANON|ECHO; 62136711Skfall tcsetattr(fd, TCSADFLUSH, &tt); 62236519Skarels 62336519Skarels env[0] = term; 62436519Skarels env[1] = 0; 62536519Skarels environ = env; 62636519Skarels } 62736609Skfall 62836711Skfall #ifdef KERBEROS 62936711Skfall #define VERSION_SIZE 9 63036711Skfall 63136609Skfall /* 63236711Skfall * Do the remote kerberos login to the named host with the 63336711Skfall * given inet address 63436711Skfall * 63536711Skfall * Return 0 on valid authorization 63636711Skfall * Return -1 on valid authentication, no authorization 63736711Skfall * Return >0 for error conditions 63836711Skfall */ 63936711Skfall do_krb_login(host, dest, encrypt) 64036711Skfall char *host; 64136711Skfall struct sockaddr_in *dest; 64236711Skfall int encrypt; 64336711Skfall { 64436711Skfall int rc; 64536711Skfall char instance[INST_SZ], version[VERSION_SIZE]; 64636711Skfall long authopts = 0L; /* !mutual */ 64736711Skfall struct sockaddr_in faddr; 64836711Skfall 64936711Skfall if (getuid()) 65036711Skfall return(KFAILURE); 65136711Skfall 65236711Skfall kdata = (AUTH_DAT *) auth_buf; 65336711Skfall ticket = (KTEXT) tick_buf; 65436711Skfall strcpy(instance, "*"); 65536711Skfall 65636711Skfall if (encrypt) { 65736711Skfall rc = sizeof(faddr); 65836711Skfall if (getsockname(0, &faddr, &rc)) 65936711Skfall return(-1); 66036711Skfall authopts = KOPT_DO_MUTUAL; 66136711Skfall rc = krb_recvauth( 66236711Skfall authopts, 0, 66336711Skfall ticket, "rcmd", 66436711Skfall instance, dest, &faddr, 66536711Skfall kdata, "", schedule, version); 66636711Skfall des_set_key(kdata->session, schedule); 66736711Skfall 66836711Skfall } else { 66936711Skfall rc = krb_recvauth( 67036711Skfall authopts, 0, 67136711Skfall ticket, "rcmd", 67236711Skfall instance, dest, (struct sockaddr_in *) 0, 67336711Skfall kdata, "", (bit_64 *) 0, version); 67436711Skfall } 67536711Skfall 67636711Skfall if (rc != KSUCCESS) 67736711Skfall return(rc); 67836711Skfall 67936711Skfall getstr(lusername, sizeof(lusername), "locuser"); 68036711Skfall /* get the "cmd" in the rcmd protocol */ 68136711Skfall getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type"); 68236711Skfall 68336711Skfall pwd = getpwnam(lusername); 68436711Skfall if (pwd == NULL) 68536711Skfall return(-1); 68636711Skfall 68736711Skfall /* returns nonzero for no access */ 68836711Skfall /* return(ruserok(host, SUPERUSER(pwd), rusername, lusername)); */ 68936711Skfall if (kuserok(kdata,lusername) != 0) 69036711Skfall return(-1); 69136711Skfall 69236711Skfall return(0); 69336711Skfall 69436711Skfall } 69536711Skfall 69636711Skfall #endif /* KERBEROS */ 69736711Skfall 69836711Skfall usage() 69936711Skfall { 70036711Skfall #ifdef KERBEROS 70136711Skfall syslog(LOG_ERR, "usage: rlogind [-k | -v] [-l] [-n]"); 70236711Skfall #else 70336711Skfall syslog(LOG_ERR, "usage: rlogind [-l] [-n]"); 70436711Skfall #endif 70536711Skfall } 70636711Skfall 70736711Skfall /* 70836631Skarels * Check whether host h is in our local domain, 70936631Skarels * as determined by the part of the name following 71036631Skarels * the first '.' in its name and in ours. 71136631Skarels * If either name is unqualified (contains no '.'), 71236631Skarels * assume that the host is local, as it will be 71336631Skarels * interpreted as such. 71436631Skarels */ 71536631Skarels local_domain(h) 71636631Skarels char *h; 71736625Skfall { 71836631Skarels char localhost[MAXHOSTNAMELEN]; 71936631Skarels char *p1, *p2 = index(h, '.'); 72036631Skarels 72136631Skarels (void) gethostname(localhost, sizeof(localhost)); 72236631Skarels p1 = index(localhost, '.'); 72336631Skarels if (p1 == NULL || p2 == NULL || !strcasecmp(p1, p2)) 72436625Skfall return(1); 72536625Skfall return(0); 72636625Skfall } 727