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*36525Skfall static char sccsid[] = "@(#)rlogind.c 5.23 (Berkeley) 01/07/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> 439208Ssam 449208Ssam #include <netinet/in.h> 459208Ssam 466446Swnj #include <errno.h> 476446Swnj #include <pwd.h> 486446Swnj #include <signal.h> 49*36525Skfall #include <sys/ioctl.h> 50*36525Skfall #include <sys/termios.h> 516446Swnj #include <stdio.h> 528380Ssam #include <netdb.h> 5317187Sralph #include <syslog.h> 5418357Ssam #include <strings.h> 556446Swnj 5636518Skarels #ifndef TIOCPKT_WINDOW 5736518Skarels #define TIOCPKT_WINDOW 0x80 5836518Skarels #endif 5936518Skarels 60*36525Skfall #ifdef KERBEROS 61*36525Skfall #include <sys/param.h> 62*36525Skfall #include <kerberos/krb.h> 63*36525Skfall #define SECURE_MESSAGE "This rlogin session is using DES encryption for all transmissions.\r\n" 64*36525Skfall 65*36525Skfall AUTH_DAT *kdata; 66*36525Skfall KTEXT ticket; 67*36525Skfall u_char auth_buf[sizeof(AUTH_DAT)]; 68*36525Skfall u_char tick_buf[sizeof(KTEXT_ST)]; 69*36525Skfall Key_schedule schedule; 70*36525Skfall int encrypt, retval, use_kerberos = 0, vacuous = 0; 71*36525Skfall int do_krb_login(); 72*36525Skfall 73*36525Skfall #define OLD_RCMD 0x00 74*36525Skfall #define KERB_RCMD 0x00 75*36525Skfall #define KERB_RCMD_MUTUAL 0x03 76*36525Skfall 77*36525Skfall #define ARGSTR "lnkv" 78*36525Skfall #else 79*36525Skfall #define ARGSTR "ln" 80*36525Skfall #endif /* KERBEROS */ 81*36525Skfall 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 10524855Seric openlog("rlogind", LOG_PID | LOG_AUTH, LOG_AUTH); 10636319Sbostic 10736319Sbostic opterr = 0; 108*36525Skfall 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; 116*36525Skfall #ifdef KERBEROS 117*36525Skfall case 'k': 118*36525Skfall use_kerberos = 1; 119*36525Skfall break; 120*36525Skfall case 'v': 121*36525Skfall vacuous = 1; 122*36525Skfall break; 123*36525Skfall #endif 12436319Sbostic case '?': 12536319Sbostic default: 126*36525Skfall usage(); 12736319Sbostic break; 12836319Sbostic } 12936319Sbostic argc -= optind; 13036319Sbostic argv += optind; 13136319Sbostic 132*36525Skfall #ifdef KERBEROS 133*36525Skfall if(use_kerberos && vacuous) { 134*36525Skfall fprintf(stderr, "%s: only one of -k and -v allowed\n", argv[0]); 135*36525Skfall usage(); 136*36525Skfall exit(1); 137*36525Skfall } 138*36525Skfall #endif 13916369Skarels fromlen = sizeof (from); 14016369Skarels if (getpeername(0, &from, &fromlen) < 0) { 14116369Skarels fprintf(stderr, "%s: ", argv[0]); 14216369Skarels perror("getpeername"); 14336319Sbostic exit(1); 1448380Ssam } 14536517Skarels if (keepalive && 14636517Skarels setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) 14717187Sralph syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); 14816369Skarels doit(0, &from); 1496446Swnj } 1506446Swnj 1516446Swnj int child; 1526446Swnj int cleanup(); 1536446Swnj int netf; 1546446Swnj char *line; 15524724Smckusick extern char *inet_ntoa(); 1566446Swnj 15724889Smckusick struct winsize win = { 0, 0, 0, 0 }; 15824723Smckusick 15924889Smckusick 1606446Swnj doit(f, fromp) 1616446Swnj int f; 1626446Swnj struct sockaddr_in *fromp; 1636446Swnj { 16418357Ssam int i, p, t, pid, on = 1; 16536518Skarels int authenticated = 0; 16618357Ssam register struct hostent *hp; 16724724Smckusick struct hostent hostent; 1688380Ssam char c; 1696446Swnj 1706446Swnj alarm(60); 1716446Swnj read(f, &c, 1); 172*36525Skfall 173*36525Skfall #ifdef KERBEROS 174*36525Skfall /* 175*36525Skfall * XXX 1st char tells us which client we're talking to 176*36525Skfall */ 177*36525Skfall switch (c) { 178*36525Skfall 179*36525Skfall case OLD_RCMD: /* OLD_RCMD is same as KERB_RCMD */ 180*36525Skfall if(vacuous) 181*36525Skfall fatal(f, "Remote host requires Kerberos authentication"); 182*36525Skfall break; 183*36525Skfall 184*36525Skfall case KERB_RCMD_MUTUAL: 185*36525Skfall encrypt = 1; 186*36525Skfall break; 187*36525Skfall 188*36525Skfall default: 189*36525Skfall fatal(f, "Remote protocol error"); 190*36525Skfall } 191*36525Skfall #else 1926446Swnj if (c != 0) 1936446Swnj exit(1); 194*36525Skfall #endif 19536453Skfall 1966446Swnj alarm(0); 19716227Skarels fromp->sin_port = ntohs((u_short)fromp->sin_port); 1988380Ssam hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr), 1998380Ssam fromp->sin_family); 20011345Ssam if (hp == 0) { 20124724Smckusick /* 20224724Smckusick * Only the name is used below. 20324724Smckusick */ 20424724Smckusick hp = &hostent; 20524724Smckusick hp->h_name = inet_ntoa(fromp->sin_addr); 20611345Ssam } 20736453Skfall 208*36525Skfall #ifdef KERBEROS 209*36525Skfall if(use_kerberos) { 210*36525Skfall retval = do_krb_login(hp->h_name, fromp, encrypt); 211*36525Skfall write(f, &c, 1); 212*36525Skfall if (retval == 0) { 213*36525Skfall authenticated++; 214*36525Skfall } else { 215*36525Skfall if (retval > 0) 216*36525Skfall fatal(f, krb_err_txt[retval]); 217*36525Skfall } 218*36525Skfall } else 21936519Skarels #endif 220*36525Skfall if (fromp->sin_family != AF_INET || 221*36525Skfall fromp->sin_port >= IPPORT_RESERVED || 222*36525Skfall fromp->sin_port < IPPORT_RESERVED/2) 223*36525Skfall fatal(f, "Permission denied"); 224*36525Skfall else { 225*36525Skfall write(f, "", 1); 22636453Skfall 227*36525Skfall if (do_rlogin(hp->h_name) == 0) 228*36525Skfall authenticated++; 229*36525Skfall } 230*36525Skfall 2316446Swnj for (c = 'p'; c <= 's'; c++) { 2326446Swnj struct stat stb; 2336446Swnj line = "/dev/ptyXX"; 2346446Swnj line[strlen("/dev/pty")] = c; 2356446Swnj line[strlen("/dev/ptyp")] = '0'; 2366446Swnj if (stat(line, &stb) < 0) 2376446Swnj break; 2386446Swnj for (i = 0; i < 16; i++) { 23934424Sbostic line[sizeof("/dev/ptyp") - 1] = "0123456789abcdef"[i]; 24034424Sbostic p = open(line, O_RDWR); 2416446Swnj if (p > 0) 2426446Swnj goto gotpty; 2436446Swnj } 2446446Swnj } 24524723Smckusick fatal(f, "Out of ptys"); 2469242Ssam /*NOTREACHED*/ 2476446Swnj gotpty: 24824889Smckusick (void) ioctl(p, TIOCSWINSZ, &win); 24916227Skarels netf = f; 2506446Swnj line[strlen("/dev/")] = 't'; 25134424Sbostic t = open(line, O_RDWR); 25234424Sbostic if (t < 0) 25334424Sbostic fatalperror(f, line); 25434424Sbostic if (fchmod(t, 0)) 25534424Sbostic fatalperror(f, line); 25634424Sbostic (void)signal(SIGHUP, SIG_IGN); 25734424Sbostic vhangup(); 25834424Sbostic (void)signal(SIGHUP, SIG_DFL); 25934424Sbostic t = open(line, O_RDWR); 26034424Sbostic if (t < 0) 26134424Sbostic fatalperror(f, line); 26236453Skfall setup_term(t); 2636446Swnj #ifdef DEBUG 26434424Sbostic { 26534424Sbostic int tt = open("/dev/tty", O_RDWR); 26634424Sbostic if (tt > 0) { 26734424Sbostic (void)ioctl(tt, TIOCNOTTY, 0); 26834424Sbostic (void)close(tt); 26934424Sbostic } 2706446Swnj } 2716446Swnj #endif 2729242Ssam pid = fork(); 2739242Ssam if (pid < 0) 27434424Sbostic fatalperror(f, ""); 27518357Ssam if (pid == 0) { 276*36525Skfall if (setsid() < 0) 277*36525Skfall fatalperror(f, "setsid"); 278*36525Skfall if (ioctl(t, TIOCSCTTY, 0) < 0) 279*36525Skfall fatalperror(f, "ioctl(sctty)"); 28018357Ssam close(f), close(p); 28118357Ssam dup2(t, 0), dup2(t, 1), dup2(t, 2); 28216227Skarels close(t); 28336517Skarels if (authenticated) 284*36525Skfall execl("/bin/login", "login", "-p", 285*36525Skfall "-h", hp->h_name, "-f", lusername, 0); 286*36525Skfall else 287*36525Skfall execl("/bin/login", "login", "-p", 28836518Skarels "-h", hp->h_name, lusername, 0); 28934424Sbostic fatalperror(2, "/bin/login"); 29018357Ssam /*NOTREACHED*/ 29118357Ssam } 29218357Ssam close(t); 29336453Skfall 294*36525Skfall #ifdef KERBEROS 295*36525Skfall /* 296*36525Skfall * If encrypted, don't turn on NBIO or the des read/write 297*36525Skfall * routines will croak. 298*36525Skfall */ 299*36525Skfall 300*36525Skfall if (encrypt) 301*36525Skfall (void) des_write(f, SECURE_MESSAGE, sizeof(SECURE_MESSAGE)); 302*36525Skfall else 303*36525Skfall #endif 304*36525Skfall ioctl(f, FIONBIO, &on); 30518357Ssam ioctl(p, FIONBIO, &on); 30618357Ssam ioctl(p, TIOCPKT, &on); 30718357Ssam signal(SIGTSTP, SIG_IGN); 30818357Ssam signal(SIGCHLD, cleanup); 30924724Smckusick setpgrp(0, 0); 31018357Ssam protocol(f, p); 31130600Smckusick signal(SIGCHLD, SIG_IGN); 31218357Ssam cleanup(); 31318357Ssam } 3149242Ssam 31518357Ssam char magic[2] = { 0377, 0377 }; 31625423Skarels char oobdata[] = {TIOCPKT_WINDOW}; 31718357Ssam 31818357Ssam /* 31918357Ssam * Handle a "control" request (signaled by magic being present) 32018357Ssam * in the data stream. For now, we are only willing to handle 32118357Ssam * window size changes. 32218357Ssam */ 32318357Ssam control(pty, cp, n) 32418357Ssam int pty; 32518357Ssam char *cp; 32618357Ssam int n; 32718357Ssam { 32828705Smckusick struct winsize w; 32918357Ssam 33028705Smckusick if (n < 4+sizeof (w) || cp[2] != 's' || cp[3] != 's') 33118357Ssam return (0); 33225423Skarels oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */ 33328705Smckusick bcopy(cp+4, (char *)&w, sizeof(w)); 33428705Smckusick w.ws_row = ntohs(w.ws_row); 33528705Smckusick w.ws_col = ntohs(w.ws_col); 33628705Smckusick w.ws_xpixel = ntohs(w.ws_xpixel); 33728705Smckusick w.ws_ypixel = ntohs(w.ws_ypixel); 33828705Smckusick (void)ioctl(pty, TIOCSWINSZ, &w); 33928705Smckusick return (4+sizeof (w)); 34018357Ssam } 34118357Ssam 34218357Ssam /* 34318357Ssam * rlogin "protocol" machine. 34418357Ssam */ 34518357Ssam protocol(f, p) 34618357Ssam int f, p; 34718357Ssam { 34818357Ssam char pibuf[1024], fibuf[1024], *pbp, *fbp; 34918357Ssam register pcc = 0, fcc = 0; 35036517Skarels int cc, nfd, pmask, fmask; 35125740Skarels char cntl; 35218357Ssam 35318482Ssam /* 35418484Ssam * Must ignore SIGTTOU, otherwise we'll stop 35518484Ssam * when we try and set slave pty's window shape 35625423Skarels * (our controlling tty is the master pty). 35718482Ssam */ 35818484Ssam (void) signal(SIGTTOU, SIG_IGN); 35925423Skarels send(f, oobdata, 1, MSG_OOB); /* indicate new rlogin */ 36036517Skarels if (f > p) 36136517Skarels nfd = f + 1; 36236517Skarels else 36336517Skarels nfd = p + 1; 36436517Skarels fmask = 1 << f; 36536517Skarels pmask = 1 << p; 36618357Ssam for (;;) { 36725740Skarels int ibits, obits, ebits; 36818357Ssam 36925740Skarels ibits = 0; 37025740Skarels obits = 0; 37118357Ssam if (fcc) 37236517Skarels obits |= pmask; 37318357Ssam else 37436517Skarels ibits |= fmask; 37518357Ssam if (pcc >= 0) 37618357Ssam if (pcc) 37736517Skarels obits |= fmask; 3789242Ssam else 37936517Skarels ibits |= pmask; 38036517Skarels ebits = pmask; 38136517Skarels if (select(nfd, &ibits, obits ? &obits : (int *)NULL, 38236517Skarels &ebits, 0) < 0) { 38318357Ssam if (errno == EINTR) 3846446Swnj continue; 38534424Sbostic fatalperror(f, "select"); 38618357Ssam } 38725740Skarels if (ibits == 0 && obits == 0 && ebits == 0) { 38818357Ssam /* shouldn't happen... */ 38918357Ssam sleep(5); 39018357Ssam continue; 39118357Ssam } 39225740Skarels #define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP)) 39336517Skarels if (ebits & pmask) { 39425740Skarels cc = read(p, &cntl, 1); 39525740Skarels if (cc == 1 && pkcontrol(cntl)) { 39625740Skarels cntl |= oobdata[0]; 39725740Skarels send(f, &cntl, 1, MSG_OOB); 39825740Skarels if (cntl & TIOCPKT_FLUSHWRITE) { 39925740Skarels pcc = 0; 40036517Skarels ibits &= ~pmask; 40125740Skarels } 40225740Skarels } 40325740Skarels } 40436517Skarels if (ibits & fmask) { 405*36525Skfall #ifdef KERBEROS 406*36525Skfall if (encrypt) 407*36525Skfall fcc = des_read(f, fibuf, sizeof(fibuf)); 408*36525Skfall else 409*36525Skfall #endif 410*36525Skfall fcc = read(f, fibuf, sizeof(fibuf)); 41118357Ssam if (fcc < 0 && errno == EWOULDBLOCK) 41218357Ssam fcc = 0; 41318357Ssam else { 41418357Ssam register char *cp; 41518357Ssam int left, n; 41618357Ssam 41718357Ssam if (fcc <= 0) 41816227Skarels break; 41918357Ssam fbp = fibuf; 42024723Smckusick 42118357Ssam top: 42225423Skarels for (cp = fibuf; cp < fibuf+fcc-1; cp++) 42318357Ssam if (cp[0] == magic[0] && 42418357Ssam cp[1] == magic[1]) { 42518357Ssam left = fcc - (cp-fibuf); 42618357Ssam n = control(p, cp, left); 42718357Ssam if (n) { 42818357Ssam left -= n; 42918357Ssam if (left > 0) 43025423Skarels bcopy(cp+n, cp, left); 43118357Ssam fcc -= n; 43218357Ssam goto top; /* n^2 */ 43325423Skarels } 43425423Skarels } 43536517Skarels obits |= pmask; /* try write */ 43625423Skarels } 43725423Skarels } 43824723Smckusick 43936517Skarels if ((obits & pmask) && fcc > 0) { 44025423Skarels cc = write(p, fbp, fcc); 44124723Smckusick if (cc > 0) { 44224723Smckusick fcc -= cc; 44324723Smckusick fbp += cc; 4446446Swnj } 44518357Ssam } 44624723Smckusick 44736517Skarels if (ibits & pmask) { 44818357Ssam pcc = read(p, pibuf, sizeof (pibuf)); 44918357Ssam pbp = pibuf; 45018357Ssam if (pcc < 0 && errno == EWOULDBLOCK) 45118357Ssam pcc = 0; 45218357Ssam else if (pcc <= 0) 45318357Ssam break; 45436517Skarels else if (pibuf[0] == 0) { 45518357Ssam pbp++, pcc--; 456*36525Skfall #ifdef KERBEROS 457*36525Skfall if (!encrypt) 458*36525Skfall #endif 459*36525Skfall obits |= fmask; /* try a write */ 46036517Skarels } else { 46118357Ssam if (pkcontrol(pibuf[0])) { 46225423Skarels pibuf[0] |= oobdata[0]; 46318357Ssam send(f, &pibuf[0], 1, MSG_OOB); 46416227Skarels } 46518357Ssam pcc = 0; 4666446Swnj } 46718357Ssam } 46836517Skarels if ((obits & fmask) && pcc > 0) { 469*36525Skfall #ifdef KERBEROS 470*36525Skfall if (encrypt) 471*36525Skfall cc = des_write(f, pbp, pcc); 472*36525Skfall else 473*36525Skfall #endif 474*36525Skfall cc = write(f, pbp, pcc); 47525423Skarels if (cc < 0 && errno == EWOULDBLOCK) { 47625423Skarels /* also shouldn't happen */ 47725423Skarels sleep(5); 47825423Skarels continue; 47925423Skarels } 48018357Ssam if (cc > 0) { 48118357Ssam pcc -= cc; 48218357Ssam pbp += cc; 48318357Ssam } 4846446Swnj } 4856446Swnj } 4866446Swnj } 4876446Swnj 4886446Swnj cleanup() 4896446Swnj { 49035440Sbostic char *p; 49135440Sbostic 49235440Sbostic p = line + sizeof("/dev/") - 1; 49335440Sbostic if (logout(p)) 49435440Sbostic logwtmp(p, "", ""); 49535440Sbostic (void)chmod(line, 0666); 49635440Sbostic (void)chown(line, 0, 0); 49735440Sbostic *p = 'p'; 49835440Sbostic (void)chmod(line, 0666); 49935440Sbostic (void)chown(line, 0, 0); 50010192Ssam shutdown(netf, 2); 5016446Swnj exit(1); 5026446Swnj } 5036446Swnj 5049242Ssam fatal(f, msg) 5059242Ssam int f; 5069242Ssam char *msg; 5079242Ssam { 5089242Ssam char buf[BUFSIZ]; 5099242Ssam 5109242Ssam buf[0] = '\01'; /* error indicator */ 51113554Ssam (void) sprintf(buf + 1, "rlogind: %s.\r\n", msg); 5129242Ssam (void) write(f, buf, strlen(buf)); 5139242Ssam exit(1); 5149242Ssam } 5159242Ssam 51634424Sbostic fatalperror(f, msg) 5179242Ssam int f; 5189242Ssam char *msg; 5199242Ssam { 5209242Ssam char buf[BUFSIZ]; 52116227Skarels extern int sys_nerr; 5229242Ssam extern char *sys_errlist[]; 5239242Ssam 52418357Ssam if ((unsigned)errno < sys_nerr) 52516227Skarels (void) sprintf(buf, "%s: %s", msg, sys_errlist[errno]); 52616227Skarels else 52716227Skarels (void) sprintf(buf, "%s: Error %d", msg, errno); 5289242Ssam fatal(f, buf); 5299242Ssam } 53036453Skfall 53136453Skfall do_rlogin(host) 53236518Skarels char *host; 53336453Skfall { 53436453Skfall 53536518Skarels getstr(rusername, sizeof(rusername), "remuser too long"); 53636518Skarels getstr(lusername, sizeof(lusername), "locuser too long"); 53736518Skarels getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type too long"); 53836518Skarels 53936518Skarels if (getuid()) 54036453Skfall return(-1); 54136453Skfall pwd = getpwnam(lusername); 54236518Skarels if (pwd == NULL) 54336453Skfall return(-1); 54436453Skfall return(ruserok(host, SUPERUSER(pwd), rusername, lusername)); 54536453Skfall } 54636453Skfall 54736453Skfall 54836518Skarels getstr(buf, cnt, errmsg) 54936518Skarels char *buf; 55036518Skarels int cnt; 55136518Skarels char *errmsg; 55236453Skfall { 55336518Skarels char c; 55436518Skarels 55536453Skfall do { 55636518Skarels if (read(0, &c, 1) != 1) 55736453Skfall exit(1); 55836518Skarels if (--cnt < 0) 55936518Skarels fatal(1, errmsg); 56036453Skfall *buf++ = c; 56136518Skarels } while (c != 0); 56236453Skfall } 56336453Skfall 56436518Skarels extern char **environ; 56536453Skfall 56636519Skarels setup_term(fd) 56736519Skarels int fd; 56836519Skarels { 569*36525Skfall struct termios tt; 570*36525Skfall register char *cp = index(term+ENVSIZE, '/'); 57136519Skarels char *speed; 57236519Skarels 573*36525Skfall tcgetattr(fd, &tt); 57436519Skarels if (cp) { 57536519Skarels *cp++ = '\0'; 57636519Skarels speed = cp; 57736519Skarels cp = index(speed, '/'); 57836519Skarels if (cp) 57936519Skarels *cp++ = '\0'; 580*36525Skfall cfsetspeed(&tt, atoi(speed)); 58136519Skarels } 582*36525Skfall tt.c_iflag = BRKINT|ICRNL|IXON|ISTRIP|IEXTEN|IMAXBEL; 583*36525Skfall tt.c_oflag = OPOST|ONLCR|OXTABS; 584*36525Skfall tt.c_lflag = ISIG|ICANON|ECHO; 585*36525Skfall tcsetattr(fd, TCSADFLUSH, &tt); 58636519Skarels 58736519Skarels env[0] = term; 58836519Skarels env[1] = 0; 58936519Skarels environ = env; 59036519Skarels } 591*36525Skfall 592*36525Skfall #ifdef KERBEROS 593*36525Skfall #define VERSION_SIZE 9 594*36525Skfall 595*36525Skfall /* 596*36525Skfall * Do the remote kerberos login to the named host with the 597*36525Skfall * given inet address 598*36525Skfall * 599*36525Skfall * Return 0 on valid authorization 600*36525Skfall * Return -1 on valid authentication, no authorization 601*36525Skfall * Return >0 for error conditions 602*36525Skfall */ 603*36525Skfall do_krb_login(host, dest, encrypt) 604*36525Skfall char *host; 605*36525Skfall struct sockaddr_in *dest; 606*36525Skfall int encrypt; 607*36525Skfall { 608*36525Skfall int rc; 609*36525Skfall char instance[INST_SZ], version[VERSION_SIZE]; 610*36525Skfall long authopts = 0L; /* !mutual */ 611*36525Skfall struct sockaddr_in faddr; 612*36525Skfall 613*36525Skfall if (getuid()) 614*36525Skfall return(KFAILURE); 615*36525Skfall 616*36525Skfall kdata = (AUTH_DAT *) auth_buf; 617*36525Skfall ticket = (KTEXT) tick_buf; 618*36525Skfall strcpy(instance, "*"); 619*36525Skfall 620*36525Skfall if (encrypt) { 621*36525Skfall rc = sizeof(faddr); 622*36525Skfall if (getsockname(0, &faddr, &rc)) 623*36525Skfall return(-1); 624*36525Skfall authopts = KOPT_DO_MUTUAL; 625*36525Skfall rc = krb_recvauth( 626*36525Skfall authopts, 0, 627*36525Skfall ticket, "rcmd", 628*36525Skfall instance, dest, &faddr, 629*36525Skfall kdata, "", schedule, version); 630*36525Skfall des_set_key(kdata->session, schedule); 631*36525Skfall 632*36525Skfall } else { 633*36525Skfall rc = krb_recvauth( 634*36525Skfall authopts, 0, 635*36525Skfall ticket, "rcmd", 636*36525Skfall instance, dest, (struct sockaddr_in *) 0, 637*36525Skfall kdata, "", (bit_64 *) 0, version); 638*36525Skfall } 639*36525Skfall 640*36525Skfall if (rc != KSUCCESS) 641*36525Skfall return(rc); 642*36525Skfall 643*36525Skfall if ((rc = krb_kntoln(kdata, rusername)) != KSUCCESS) 644*36525Skfall return(rc); 645*36525Skfall 646*36525Skfall getstr(lusername, sizeof(lusername), "locuser"); 647*36525Skfall /* get the "cmd" in the rcmd protocol */ 648*36525Skfall getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type"); 649*36525Skfall 650*36525Skfall pwd = getpwnam(lusername); 651*36525Skfall if (pwd == NULL) 652*36525Skfall return(-1); 653*36525Skfall 654*36525Skfall /* returns nonzero for no access */ 655*36525Skfall /* return(ruserok(host, SUPERUSER(pwd), rusername, lusername)); */ 656*36525Skfall if(kuserok(kdata,lusername) != 0) 657*36525Skfall return(-1); 658*36525Skfall 659*36525Skfall return(0); 660*36525Skfall 661*36525Skfall } 662*36525Skfall 663*36525Skfall #endif /* KERBEROS */ 664*36525Skfall 665*36525Skfall usage() 666*36525Skfall { 667*36525Skfall #ifdef KERBEROS 668*36525Skfall syslog(LOG_ERR, "usage: rlogind [-k | -v] [-l] [-n]"); 669*36525Skfall #else 670*36525Skfall syslog(LOG_ERR, "usage: rlogind [-l] [-n]"); 671*36525Skfall #endif 672*36525Skfall } 673