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*36625Skfall static char sccsid[] = "@(#)rlogind.c 5.23 (Berkeley) 1/7/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> 386446Swnj #include <sys/types.h> 396446Swnj #include <sys/stat.h> 406446Swnj #include <sys/socket.h> 4113554Ssam #include <sys/wait.h> 4218357Ssam #include <sys/file.h> 43*36625Skfall #include <sys/param.h> 449208Ssam 459208Ssam #include <netinet/in.h> 469208Ssam 476446Swnj #include <errno.h> 486446Swnj #include <pwd.h> 496446Swnj #include <signal.h> 5036609Skfall #include <sys/ioctl.h> 5136609Skfall #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 6136609Skfall #ifdef KERBEROS 6236609Skfall #include <kerberos/krb.h> 6336609Skfall #define SECURE_MESSAGE "This rlogin session is using DES encryption for all transmissions.\r\n" 6436609Skfall 6536609Skfall AUTH_DAT *kdata; 6636609Skfall KTEXT ticket; 6736609Skfall u_char auth_buf[sizeof(AUTH_DAT)]; 6836609Skfall u_char tick_buf[sizeof(KTEXT_ST)]; 6936609Skfall Key_schedule schedule; 7036609Skfall int encrypt, retval, use_kerberos = 0, vacuous = 0; 7136609Skfall int do_krb_login(); 7236609Skfall 7336609Skfall #define OLD_RCMD 0x00 7436609Skfall #define KERB_RCMD 0x00 7536609Skfall #define KERB_RCMD_MUTUAL 0x03 7636609Skfall 7736609Skfall #define ARGSTR "lnkv" 7836609Skfall #else 7936609Skfall #define ARGSTR "ln" 8036609Skfall #endif /* KERBEROS */ 8136609Skfall 8236518Skarels char *env[2]; 8336518Skarels #define NMAX 30 8436517Skarels char lusername[NMAX+1], rusername[NMAX+1]; 8536517Skarels static char term[64] = "TERM="; 8636517Skarels #define ENVSIZE (sizeof("TERM=")-1) /* skip null for concatenation */ 8736517Skarels int keepalive = 1; 8836453Skfall 8936453Skfall #define SUPERUSER(pwd) ((pwd)->pw_uid == 0) 9036453Skfall 9134424Sbostic extern int errno; 9210417Ssam int reapchild(); 9336453Skfall struct passwd *getpwnam(), *pwd; 9424723Smckusick char *malloc(); 9516369Skarels 966446Swnj main(argc, argv) 976446Swnj int argc; 986446Swnj char **argv; 996446Swnj { 10036319Sbostic extern int opterr, optind, _check_rhosts_file; 10136319Sbostic int ch; 10234424Sbostic int on = 1, fromlen; 1036446Swnj struct sockaddr_in from; 1046446Swnj 105*36625Skfall openlog("rlogind", LOG_PID | LOG_CONS, LOG_AUTH); 10636319Sbostic 10736319Sbostic opterr = 0; 10836609Skfall while ((ch = getopt(argc, argv, ARGSTR)) != EOF) 10936517Skarels switch (ch) { 11036319Sbostic case 'l': 11136319Sbostic _check_rhosts_file = 0; 11236319Sbostic break; 11336517Skarels case 'n': 11436517Skarels keepalive = 0; 11536517Skarels break; 11636609Skfall #ifdef KERBEROS 11736609Skfall case 'k': 11836609Skfall use_kerberos = 1; 11936609Skfall break; 12036609Skfall case 'v': 12136609Skfall vacuous = 1; 12236609Skfall break; 12336609Skfall #endif 12436319Sbostic case '?': 12536319Sbostic default: 12636609Skfall usage(); 12736319Sbostic break; 12836319Sbostic } 12936319Sbostic argc -= optind; 13036319Sbostic argv += optind; 13136319Sbostic 13236609Skfall #ifdef KERBEROS 13336609Skfall if(use_kerberos && vacuous) { 13436609Skfall fprintf(stderr, "%s: only one of -k and -v allowed\n", argv[0]); 13536609Skfall usage(); 13636609Skfall exit(1); 13736609Skfall } 13836609Skfall #endif 13916369Skarels fromlen = sizeof (from); 14016369Skarels if (getpeername(0, &from, &fromlen) < 0) { 141*36625Skfall syslog(LOG_ERR,"Couldn't get peer name of remote host: %m"); 14236319Sbostic exit(1); 1438380Ssam } 14436517Skarels if (keepalive && 14536517Skarels setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) 14617187Sralph syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); 14716369Skarels doit(0, &from); 1486446Swnj } 1496446Swnj 1506446Swnj int child; 1516446Swnj int cleanup(); 1526446Swnj int netf; 1536446Swnj char *line; 15424724Smckusick extern char *inet_ntoa(); 1556446Swnj 15624889Smckusick struct winsize win = { 0, 0, 0, 0 }; 15724723Smckusick 15824889Smckusick 1596446Swnj doit(f, fromp) 1606446Swnj int f; 1616446Swnj struct sockaddr_in *fromp; 1626446Swnj { 16318357Ssam int i, p, t, pid, on = 1; 16436518Skarels int authenticated = 0; 16518357Ssam register struct hostent *hp; 166*36625Skfall char remotehost[MAXHOSTNAMELEN]; 167*36625Skfall char localhost[MAXHOSTNAMELEN]; 16824724Smckusick struct hostent hostent; 169*36625Skfall char *raddr; 1708380Ssam char c; 1716446Swnj 1726446Swnj alarm(60); 1736446Swnj read(f, &c, 1); 17436609Skfall 17536609Skfall #ifdef KERBEROS 17636609Skfall /* 17736609Skfall * XXX 1st char tells us which client we're talking to 17836609Skfall */ 17936609Skfall switch (c) { 18036609Skfall 18136609Skfall case OLD_RCMD: /* OLD_RCMD is same as KERB_RCMD */ 18236609Skfall if(vacuous) 18336609Skfall fatal(f, "Remote host requires Kerberos authentication"); 18436609Skfall break; 18536609Skfall 18636609Skfall case KERB_RCMD_MUTUAL: 18736609Skfall encrypt = 1; 18836609Skfall break; 18936609Skfall 19036609Skfall default: 19136609Skfall fatal(f, "Remote protocol error"); 19236609Skfall } 19336609Skfall #else 1946446Swnj if (c != 0) 1956446Swnj exit(1); 19636609Skfall #endif 19736453Skfall 1986446Swnj alarm(0); 19916227Skarels fromp->sin_port = ntohs((u_short)fromp->sin_port); 2008380Ssam hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr), 2018380Ssam fromp->sin_family); 20211345Ssam if (hp == 0) { 20324724Smckusick /* 20424724Smckusick * Only the name is used below. 20524724Smckusick */ 20624724Smckusick hp = &hostent; 20724724Smckusick hp->h_name = inet_ntoa(fromp->sin_addr); 208*36625Skfall } else { 209*36625Skfall (void) gethostname(localhost, sizeof(localhost)); 210*36625Skfall if(same_domain(hp->h_name, localhost)) { 211*36625Skfall bcopy(hp->h_name, remotehost, sizeof(remotehost)); 212*36625Skfall hp = gethostbyname(remotehost); 213*36625Skfall authenticated = -10; /* !authenticated */ 214*36625Skfall if(hp == NULL) { 215*36625Skfall syslog(LOG_NOTICE, "Couldn't get entry for remote host %s\n", 216*36625Skfall remotehost); 217*36625Skfall } else { 218*36625Skfall for(;;) { 219*36625Skfall if(!(raddr = hp->h_addr_list[0])) 220*36625Skfall break; 221*36625Skfall 222*36625Skfall if(!bcmp(raddr, (caddr_t) &fromp->sin_addr, 223*36625Skfall sizeof(struct in_addr))) { 224*36625Skfall authenticated = 0; 225*36625Skfall break; 226*36625Skfall } 227*36625Skfall hp->h_addr_list++; 228*36625Skfall } 229*36625Skfall if(authenticated < 0) { 230*36625Skfall syslog(LOG_NOTICE,"Host address not listed for name %s", 231*36625Skfall remotehost); 232*36625Skfall } 233*36625Skfall } 234*36625Skfall } 23511345Ssam } 23636453Skfall 23736609Skfall #ifdef KERBEROS 23836609Skfall if(use_kerberos) { 23936609Skfall retval = do_krb_login(hp->h_name, fromp, encrypt); 24036609Skfall write(f, &c, 1); 24136609Skfall if (retval == 0) { 24236609Skfall authenticated++; 24336609Skfall } else { 24436609Skfall if (retval > 0) 24536609Skfall fatal(f, krb_err_txt[retval]); 24636609Skfall } 24736609Skfall } else 24836519Skarels #endif 24936609Skfall if (fromp->sin_family != AF_INET || 25036609Skfall fromp->sin_port >= IPPORT_RESERVED || 251*36625Skfall fromp->sin_port < IPPORT_RESERVED/2) { 252*36625Skfall syslog(LOG_NOTICE, "Connection from %s on illegal port", 253*36625Skfall inet_ntoa(fromp->sin_addr)); 25436609Skfall fatal(f, "Permission denied"); 255*36625Skfall } else { 25636609Skfall write(f, "", 1); 25736453Skfall 25836609Skfall if (do_rlogin(hp->h_name) == 0) 25936609Skfall authenticated++; 26036609Skfall } 26136609Skfall 2626446Swnj for (c = 'p'; c <= 's'; c++) { 2636446Swnj struct stat stb; 2646446Swnj line = "/dev/ptyXX"; 2656446Swnj line[strlen("/dev/pty")] = c; 2666446Swnj line[strlen("/dev/ptyp")] = '0'; 2676446Swnj if (stat(line, &stb) < 0) 2686446Swnj break; 2696446Swnj for (i = 0; i < 16; i++) { 27034424Sbostic line[sizeof("/dev/ptyp") - 1] = "0123456789abcdef"[i]; 27134424Sbostic p = open(line, O_RDWR); 2726446Swnj if (p > 0) 2736446Swnj goto gotpty; 2746446Swnj } 2756446Swnj } 27624723Smckusick fatal(f, "Out of ptys"); 2779242Ssam /*NOTREACHED*/ 2786446Swnj gotpty: 27924889Smckusick (void) ioctl(p, TIOCSWINSZ, &win); 28016227Skarels netf = f; 2816446Swnj line[strlen("/dev/")] = 't'; 28234424Sbostic t = open(line, O_RDWR); 28334424Sbostic if (t < 0) 28434424Sbostic fatalperror(f, line); 28534424Sbostic if (fchmod(t, 0)) 28634424Sbostic fatalperror(f, line); 28734424Sbostic (void)signal(SIGHUP, SIG_IGN); 28834424Sbostic vhangup(); 28934424Sbostic (void)signal(SIGHUP, SIG_DFL); 29034424Sbostic t = open(line, O_RDWR); 29134424Sbostic if (t < 0) 29234424Sbostic fatalperror(f, line); 29336453Skfall setup_term(t); 2946446Swnj #ifdef DEBUG 29534424Sbostic { 29634424Sbostic int tt = open("/dev/tty", O_RDWR); 29734424Sbostic if (tt > 0) { 29834424Sbostic (void)ioctl(tt, TIOCNOTTY, 0); 29934424Sbostic (void)close(tt); 30034424Sbostic } 3016446Swnj } 3026446Swnj #endif 3039242Ssam pid = fork(); 3049242Ssam if (pid < 0) 30534424Sbostic fatalperror(f, ""); 30618357Ssam if (pid == 0) { 30736609Skfall if (setsid() < 0) 30836609Skfall fatalperror(f, "setsid"); 30936609Skfall if (ioctl(t, TIOCSCTTY, 0) < 0) 31036609Skfall fatalperror(f, "ioctl(sctty)"); 31118357Ssam close(f), close(p); 31218357Ssam dup2(t, 0), dup2(t, 1), dup2(t, 2); 31316227Skarels close(t); 314*36625Skfall if (authenticated > 0) 31536609Skfall execl("/bin/login", "login", "-p", 31636609Skfall "-h", hp->h_name, "-f", lusername, 0); 31736525Skfall else 31836609Skfall execl("/bin/login", "login", "-p", 31936609Skfall "-h", hp->h_name, lusername, 0); 32034424Sbostic fatalperror(2, "/bin/login"); 32118357Ssam /*NOTREACHED*/ 32218357Ssam } 32318357Ssam close(t); 32436453Skfall 32536609Skfall #ifdef KERBEROS 32636609Skfall /* 32736609Skfall * If encrypted, don't turn on NBIO or the des read/write 32836609Skfall * routines will croak. 32936609Skfall */ 33036609Skfall 33136609Skfall if (encrypt) 33236609Skfall (void) des_write(f, SECURE_MESSAGE, sizeof(SECURE_MESSAGE)); 33336609Skfall else 33436609Skfall #endif 33536609Skfall ioctl(f, FIONBIO, &on); 33618357Ssam ioctl(p, FIONBIO, &on); 33718357Ssam ioctl(p, TIOCPKT, &on); 33818357Ssam signal(SIGTSTP, SIG_IGN); 33918357Ssam signal(SIGCHLD, cleanup); 34024724Smckusick setpgrp(0, 0); 34118357Ssam protocol(f, p); 34230600Smckusick signal(SIGCHLD, SIG_IGN); 34318357Ssam cleanup(); 34418357Ssam } 3459242Ssam 34618357Ssam char magic[2] = { 0377, 0377 }; 34725423Skarels char oobdata[] = {TIOCPKT_WINDOW}; 34818357Ssam 34918357Ssam /* 35018357Ssam * Handle a "control" request (signaled by magic being present) 35118357Ssam * in the data stream. For now, we are only willing to handle 35218357Ssam * window size changes. 35318357Ssam */ 35418357Ssam control(pty, cp, n) 35518357Ssam int pty; 35618357Ssam char *cp; 35718357Ssam int n; 35818357Ssam { 35928705Smckusick struct winsize w; 36018357Ssam 36128705Smckusick if (n < 4+sizeof (w) || cp[2] != 's' || cp[3] != 's') 36218357Ssam return (0); 36325423Skarels oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */ 36428705Smckusick bcopy(cp+4, (char *)&w, sizeof(w)); 36528705Smckusick w.ws_row = ntohs(w.ws_row); 36628705Smckusick w.ws_col = ntohs(w.ws_col); 36728705Smckusick w.ws_xpixel = ntohs(w.ws_xpixel); 36828705Smckusick w.ws_ypixel = ntohs(w.ws_ypixel); 36928705Smckusick (void)ioctl(pty, TIOCSWINSZ, &w); 37028705Smckusick return (4+sizeof (w)); 37118357Ssam } 37218357Ssam 37318357Ssam /* 37418357Ssam * rlogin "protocol" machine. 37518357Ssam */ 37618357Ssam protocol(f, p) 37718357Ssam int f, p; 37818357Ssam { 37918357Ssam char pibuf[1024], fibuf[1024], *pbp, *fbp; 38018357Ssam register pcc = 0, fcc = 0; 38136517Skarels int cc, nfd, pmask, fmask; 38225740Skarels char cntl; 38318357Ssam 38418482Ssam /* 38518484Ssam * Must ignore SIGTTOU, otherwise we'll stop 38618484Ssam * when we try and set slave pty's window shape 38725423Skarels * (our controlling tty is the master pty). 38818482Ssam */ 38918484Ssam (void) signal(SIGTTOU, SIG_IGN); 39025423Skarels send(f, oobdata, 1, MSG_OOB); /* indicate new rlogin */ 39136517Skarels if (f > p) 39236517Skarels nfd = f + 1; 39336517Skarels else 39436517Skarels nfd = p + 1; 39536517Skarels fmask = 1 << f; 39636517Skarels pmask = 1 << p; 39718357Ssam for (;;) { 39825740Skarels int ibits, obits, ebits; 39918357Ssam 40025740Skarels ibits = 0; 40125740Skarels obits = 0; 40218357Ssam if (fcc) 40336517Skarels obits |= pmask; 40418357Ssam else 40536517Skarels ibits |= fmask; 40618357Ssam if (pcc >= 0) 40718357Ssam if (pcc) 40836517Skarels obits |= fmask; 4099242Ssam else 41036517Skarels ibits |= pmask; 41136517Skarels ebits = pmask; 41236517Skarels if (select(nfd, &ibits, obits ? &obits : (int *)NULL, 41336517Skarels &ebits, 0) < 0) { 41418357Ssam if (errno == EINTR) 4156446Swnj continue; 41634424Sbostic fatalperror(f, "select"); 41718357Ssam } 41825740Skarels if (ibits == 0 && obits == 0 && ebits == 0) { 41918357Ssam /* shouldn't happen... */ 42018357Ssam sleep(5); 42118357Ssam continue; 42218357Ssam } 42325740Skarels #define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP)) 42436517Skarels if (ebits & pmask) { 42525740Skarels cc = read(p, &cntl, 1); 42625740Skarels if (cc == 1 && pkcontrol(cntl)) { 42725740Skarels cntl |= oobdata[0]; 42825740Skarels send(f, &cntl, 1, MSG_OOB); 42925740Skarels if (cntl & TIOCPKT_FLUSHWRITE) { 43025740Skarels pcc = 0; 43136517Skarels ibits &= ~pmask; 43225740Skarels } 43325740Skarels } 43425740Skarels } 43536517Skarels if (ibits & fmask) { 43636609Skfall #ifdef KERBEROS 43736609Skfall if (encrypt) 43836609Skfall fcc = des_read(f, fibuf, sizeof(fibuf)); 43936609Skfall else 44036609Skfall #endif 44136609Skfall fcc = read(f, fibuf, sizeof(fibuf)); 44218357Ssam if (fcc < 0 && errno == EWOULDBLOCK) 44318357Ssam fcc = 0; 44418357Ssam else { 44518357Ssam register char *cp; 44618357Ssam int left, n; 44718357Ssam 44818357Ssam if (fcc <= 0) 44916227Skarels break; 45018357Ssam fbp = fibuf; 45124723Smckusick 45218357Ssam top: 45325423Skarels for (cp = fibuf; cp < fibuf+fcc-1; cp++) 45418357Ssam if (cp[0] == magic[0] && 45518357Ssam cp[1] == magic[1]) { 45618357Ssam left = fcc - (cp-fibuf); 45718357Ssam n = control(p, cp, left); 45818357Ssam if (n) { 45918357Ssam left -= n; 46018357Ssam if (left > 0) 46125423Skarels bcopy(cp+n, cp, left); 46218357Ssam fcc -= n; 46318357Ssam goto top; /* n^2 */ 46425423Skarels } 46525423Skarels } 46636517Skarels obits |= pmask; /* try write */ 46725423Skarels } 46825423Skarels } 46924723Smckusick 47036517Skarels if ((obits & pmask) && fcc > 0) { 47125423Skarels cc = write(p, fbp, fcc); 47224723Smckusick if (cc > 0) { 47324723Smckusick fcc -= cc; 47424723Smckusick fbp += cc; 4756446Swnj } 47618357Ssam } 47724723Smckusick 47836517Skarels if (ibits & pmask) { 47918357Ssam pcc = read(p, pibuf, sizeof (pibuf)); 48018357Ssam pbp = pibuf; 48118357Ssam if (pcc < 0 && errno == EWOULDBLOCK) 48218357Ssam pcc = 0; 48318357Ssam else if (pcc <= 0) 48418357Ssam break; 48536517Skarels else if (pibuf[0] == 0) { 48618357Ssam pbp++, pcc--; 48736609Skfall #ifdef KERBEROS 48836609Skfall if (!encrypt) 48936609Skfall #endif 49036609Skfall obits |= fmask; /* try a write */ 49136517Skarels } else { 49218357Ssam if (pkcontrol(pibuf[0])) { 49325423Skarels pibuf[0] |= oobdata[0]; 49418357Ssam send(f, &pibuf[0], 1, MSG_OOB); 49516227Skarels } 49618357Ssam pcc = 0; 4976446Swnj } 49818357Ssam } 49936517Skarels if ((obits & fmask) && pcc > 0) { 50036609Skfall #ifdef KERBEROS 50136609Skfall if (encrypt) 50236609Skfall cc = des_write(f, pbp, pcc); 50336609Skfall else 50436609Skfall #endif 50536609Skfall cc = write(f, pbp, pcc); 50625423Skarels if (cc < 0 && errno == EWOULDBLOCK) { 50725423Skarels /* also shouldn't happen */ 50825423Skarels sleep(5); 50925423Skarels continue; 51025423Skarels } 51118357Ssam if (cc > 0) { 51218357Ssam pcc -= cc; 51318357Ssam pbp += cc; 51418357Ssam } 5156446Swnj } 5166446Swnj } 5176446Swnj } 5186446Swnj 5196446Swnj cleanup() 5206446Swnj { 52135440Sbostic char *p; 52235440Sbostic 52335440Sbostic p = line + sizeof("/dev/") - 1; 52435440Sbostic if (logout(p)) 52535440Sbostic logwtmp(p, "", ""); 52635440Sbostic (void)chmod(line, 0666); 52735440Sbostic (void)chown(line, 0, 0); 52835440Sbostic *p = 'p'; 52935440Sbostic (void)chmod(line, 0666); 53035440Sbostic (void)chown(line, 0, 0); 53110192Ssam shutdown(netf, 2); 5326446Swnj exit(1); 5336446Swnj } 5346446Swnj 5359242Ssam fatal(f, msg) 5369242Ssam int f; 5379242Ssam char *msg; 5389242Ssam { 5399242Ssam char buf[BUFSIZ]; 5409242Ssam 5419242Ssam buf[0] = '\01'; /* error indicator */ 54213554Ssam (void) sprintf(buf + 1, "rlogind: %s.\r\n", msg); 5439242Ssam (void) write(f, buf, strlen(buf)); 5449242Ssam exit(1); 5459242Ssam } 5469242Ssam 54734424Sbostic fatalperror(f, msg) 5489242Ssam int f; 5499242Ssam char *msg; 5509242Ssam { 5519242Ssam char buf[BUFSIZ]; 55216227Skarels extern int sys_nerr; 5539242Ssam extern char *sys_errlist[]; 5549242Ssam 55518357Ssam if ((unsigned)errno < sys_nerr) 55616227Skarels (void) sprintf(buf, "%s: %s", msg, sys_errlist[errno]); 55716227Skarels else 55816227Skarels (void) sprintf(buf, "%s: Error %d", msg, errno); 5599242Ssam fatal(f, buf); 5609242Ssam } 56136453Skfall 56236453Skfall do_rlogin(host) 56336518Skarels char *host; 56436453Skfall { 56536453Skfall 56636518Skarels getstr(rusername, sizeof(rusername), "remuser too long"); 56736518Skarels getstr(lusername, sizeof(lusername), "locuser too long"); 56836518Skarels getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type too long"); 56936518Skarels 57036518Skarels if (getuid()) 57136453Skfall return(-1); 57236453Skfall pwd = getpwnam(lusername); 57336518Skarels if (pwd == NULL) 57436453Skfall return(-1); 57536453Skfall return(ruserok(host, SUPERUSER(pwd), rusername, lusername)); 57636453Skfall } 57736453Skfall 57836453Skfall 57936518Skarels getstr(buf, cnt, errmsg) 58036518Skarels char *buf; 58136518Skarels int cnt; 58236518Skarels char *errmsg; 58336453Skfall { 58436518Skarels char c; 58536518Skarels 58636453Skfall do { 58736518Skarels if (read(0, &c, 1) != 1) 58836453Skfall exit(1); 58936518Skarels if (--cnt < 0) 59036518Skarels fatal(1, errmsg); 59136453Skfall *buf++ = c; 59236518Skarels } while (c != 0); 59336453Skfall } 59436453Skfall 59536518Skarels extern char **environ; 59636453Skfall 59736519Skarels setup_term(fd) 59836519Skarels int fd; 59936519Skarels { 60036609Skfall struct termios tt; 60136609Skfall register char *cp = index(term+ENVSIZE, '/'); 60236519Skarels char *speed; 60336519Skarels 60436609Skfall tcgetattr(fd, &tt); 60536519Skarels if (cp) { 60636519Skarels *cp++ = '\0'; 60736519Skarels speed = cp; 60836519Skarels cp = index(speed, '/'); 60936519Skarels if (cp) 61036519Skarels *cp++ = '\0'; 61136609Skfall cfsetspeed(&tt, atoi(speed)); 61236519Skarels } 61336609Skfall tt.c_iflag = BRKINT|ICRNL|IXON|ISTRIP|IEXTEN|IMAXBEL; 61436609Skfall tt.c_oflag = OPOST|ONLCR|OXTABS; 61536609Skfall tt.c_lflag = ISIG|ICANON|ECHO; 61636609Skfall tcsetattr(fd, TCSADFLUSH, &tt); 61736519Skarels 61836519Skarels env[0] = term; 61936519Skarels env[1] = 0; 62036519Skarels environ = env; 62136519Skarels } 62236609Skfall 62336609Skfall #ifdef KERBEROS 62436609Skfall #define VERSION_SIZE 9 62536609Skfall 62636609Skfall /* 62736609Skfall * Do the remote kerberos login to the named host with the 62836609Skfall * given inet address 62936609Skfall * 63036609Skfall * Return 0 on valid authorization 63136609Skfall * Return -1 on valid authentication, no authorization 63236609Skfall * Return >0 for error conditions 63336609Skfall */ 63436609Skfall do_krb_login(host, dest, encrypt) 63536609Skfall char *host; 63636609Skfall struct sockaddr_in *dest; 63736609Skfall int encrypt; 63836609Skfall { 63936609Skfall int rc; 64036609Skfall char instance[INST_SZ], version[VERSION_SIZE]; 64136609Skfall long authopts = 0L; /* !mutual */ 64236609Skfall struct sockaddr_in faddr; 64336609Skfall 64436609Skfall if (getuid()) 64536609Skfall return(KFAILURE); 64636609Skfall 64736609Skfall kdata = (AUTH_DAT *) auth_buf; 64836609Skfall ticket = (KTEXT) tick_buf; 64936609Skfall strcpy(instance, "*"); 65036609Skfall 65136609Skfall if (encrypt) { 65236609Skfall rc = sizeof(faddr); 65336609Skfall if (getsockname(0, &faddr, &rc)) 65436609Skfall return(-1); 65536609Skfall authopts = KOPT_DO_MUTUAL; 65636609Skfall rc = krb_recvauth( 65736609Skfall authopts, 0, 65836609Skfall ticket, "rcmd", 65936609Skfall instance, dest, &faddr, 66036609Skfall kdata, "", schedule, version); 66136609Skfall des_set_key(kdata->session, schedule); 66236609Skfall 66336609Skfall } else { 66436609Skfall rc = krb_recvauth( 66536609Skfall authopts, 0, 66636609Skfall ticket, "rcmd", 66736609Skfall instance, dest, (struct sockaddr_in *) 0, 66836609Skfall kdata, "", (bit_64 *) 0, version); 66936609Skfall } 67036609Skfall 67136609Skfall if (rc != KSUCCESS) 67236609Skfall return(rc); 67336609Skfall 67436609Skfall if ((rc = krb_kntoln(kdata, rusername)) != KSUCCESS) 67536609Skfall return(rc); 67636609Skfall 67736609Skfall getstr(lusername, sizeof(lusername), "locuser"); 67836609Skfall /* get the "cmd" in the rcmd protocol */ 67936609Skfall getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type"); 68036609Skfall 68136609Skfall pwd = getpwnam(lusername); 68236609Skfall if (pwd == NULL) 68336609Skfall return(-1); 68436609Skfall 68536609Skfall /* returns nonzero for no access */ 68636609Skfall /* return(ruserok(host, SUPERUSER(pwd), rusername, lusername)); */ 68736609Skfall if(kuserok(kdata,lusername) != 0) 68836609Skfall return(-1); 68936609Skfall 69036609Skfall return(0); 69136609Skfall 69236609Skfall } 69336609Skfall 69436609Skfall #endif /* KERBEROS */ 69536609Skfall 69636609Skfall usage() 69736609Skfall { 69836609Skfall #ifdef KERBEROS 69936609Skfall syslog(LOG_ERR, "usage: rlogind [-k | -v] [-l] [-n]"); 70036609Skfall #else 70136609Skfall syslog(LOG_ERR, "usage: rlogind [-l] [-n]"); 70236609Skfall #endif 70336609Skfall } 704*36625Skfall 705*36625Skfall int 706*36625Skfall same_domain(h1, h2) 707*36625Skfall char *h1, *h2; 708*36625Skfall { 709*36625Skfall register char *p1 = index(h1, '.'); 710*36625Skfall register char *p2 = index(h2, '.'); 711*36625Skfall if(!strcasecmp(p1, p2)) 712*36625Skfall return(1); 713*36625Skfall return(0); 714*36625Skfall } 715