121174Sdist /* 235441Sbostic * Copyright (c) 1983 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[] = 2035441Sbostic "@(#) Copyright (c) 1983 The Regents of the University of California.\n\ 2121174Sdist All rights reserved.\n"; 2235441Sbostic #endif /* not lint */ 236446Swnj 2421174Sdist #ifndef lint 25*36453Skfall static char sccsid[] = "@(#)rlogind.c 5.19 (Berkeley) 12/20/88"; 2635441Sbostic #endif /* not lint */ 2721174Sdist 2816369Skarels /* 2916369Skarels * remote login server: 30*36453Skfall * \0 3116369Skarels * remuser\0 3216369Skarels * locuser\0 33*36453Skfall * terminal_type/speed\0 34*36453Skfall * data (not used currently) 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*36453Skfall #include <sys/ioctl.h> 50*36453Skfall #include <sys/termios.h> 516446Swnj #include <stdio.h> 528380Ssam #include <netdb.h> 5317187Sralph #include <syslog.h> 5418357Ssam #include <strings.h> 55*36453Skfall #include <utmp.h> 566446Swnj 57*36453Skfall #ifdef KERBEROS 58*36453Skfall #include <sys/param.h> 59*36453Skfall #include <kerberos/krb.h> 60*36453Skfall #define SECURE_MESSAGE "This rlogin session is using DES encryption for all transmissions.\r\n" 61*36453Skfall 62*36453Skfall AUTH_DAT *kdata; 63*36453Skfall KTEXT ticket; 64*36453Skfall u_char auth_buf[sizeof(AUTH_DAT)]; 65*36453Skfall u_char tick_buf[sizeof(KTEXT_ST)]; 66*36453Skfall Key_schedule schedule; 67*36453Skfall int encrypt = 0, retval; 68*36453Skfall int do_krb_login(); 69*36453Skfall 70*36453Skfall #define OLD_RCMD 0x00 71*36453Skfall #define KERB_RCMD 0x01 72*36453Skfall #define KERB_RCMD_MUTUAL 0x02 73*36453Skfall #endif /* KERBEROS */ 74*36453Skfall 75*36453Skfall char *envinit[2]; 76*36453Skfall struct utmp utmp; 77*36453Skfall #define NMAX sizeof(utmp.ut_name) 78*36453Skfall char lusername[NMAX+1], rusername[NMAX+1]; 79*36453Skfall static char term[64] = "TERM="; 80*36453Skfall #define ENVSIZE (strlen("TERM=")) 81*36453Skfall struct passwd nouser = {"", "nope", -1, -1, -1, "", "", "", "" }; 82*36453Skfall 83*36453Skfall #define SUPERUSER(pwd) ((pwd)->pw_uid == 0) 84*36453Skfall 8524723Smckusick # ifndef TIOCPKT_WINDOW 8624723Smckusick # define TIOCPKT_WINDOW 0x80 8724723Smckusick # endif TIOCPKT_WINDOW 8824723Smckusick 8934424Sbostic extern int errno; 9010417Ssam int reapchild(); 91*36453Skfall struct passwd *getpwnam(), *pwd; 9224723Smckusick char *malloc(); 9316369Skarels 9434424Sbostic /*ARGSUSED*/ 956446Swnj main(argc, argv) 966446Swnj int argc; 976446Swnj char **argv; 986446Swnj { 9936319Sbostic extern int opterr, optind, _check_rhosts_file; 10036319Sbostic int ch; 10134424Sbostic int on = 1, fromlen; 1026446Swnj struct sockaddr_in from; 1036446Swnj 10424855Seric openlog("rlogind", LOG_PID | LOG_AUTH, LOG_AUTH); 10536319Sbostic 10636319Sbostic opterr = 0; 10736319Sbostic while ((ch = getopt(argc, argv, "l")) != EOF) 10836319Sbostic switch((char)ch) { 10936319Sbostic case 'l': 11036319Sbostic _check_rhosts_file = 0; 11136319Sbostic break; 11236319Sbostic case '?': 11336319Sbostic default: 11436319Sbostic syslog(LOG_ERR, "usage: rlogind [-l]"); 11536319Sbostic break; 11636319Sbostic } 11736319Sbostic argc -= optind; 11836319Sbostic argv += optind; 11936319Sbostic 12016369Skarels fromlen = sizeof (from); 12116369Skarels if (getpeername(0, &from, &fromlen) < 0) { 12216369Skarels fprintf(stderr, "%s: ", argv[0]); 12316369Skarels perror("getpeername"); 12436319Sbostic exit(1); 1258380Ssam } 12617156Ssam if (setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) { 12717187Sralph syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); 1286446Swnj } 12916369Skarels doit(0, &from); 1306446Swnj } 1316446Swnj 1326446Swnj int child; 1336446Swnj int cleanup(); 1346446Swnj int netf; 1356446Swnj char *line; 13624724Smckusick extern char *inet_ntoa(); 1376446Swnj 13824889Smckusick struct winsize win = { 0, 0, 0, 0 }; 13924723Smckusick 14024889Smckusick 1416446Swnj doit(f, fromp) 1426446Swnj int f; 1436446Swnj struct sockaddr_in *fromp; 1446446Swnj { 14518357Ssam int i, p, t, pid, on = 1; 146*36453Skfall int authenticated = 0; 14718357Ssam register struct hostent *hp; 14824724Smckusick struct hostent hostent; 1498380Ssam char c; 1506446Swnj 1516446Swnj alarm(60); 1526446Swnj read(f, &c, 1); 153*36453Skfall 154*36453Skfall #ifdef KERBEROS 155*36453Skfall /* 156*36453Skfall * XXX 1st char tells us which client we're talking to 157*36453Skfall */ 158*36453Skfall switch(c) { 159*36453Skfall 160*36453Skfall case KERB_RCMD: 161*36453Skfall break; 162*36453Skfall 163*36453Skfall case KERB_RCMD_MUTUAL: 164*36453Skfall encrypt = 1; 165*36453Skfall break; 166*36453Skfall 167*36453Skfall 168*36453Skfall case OLD_RCMD: 169*36453Skfall default: 170*36453Skfall fatal(f, "Remote host requires Kerberos authentication"); 171*36453Skfall } 172*36453Skfall #else 1736446Swnj if (c != 0) 1746446Swnj exit(1); 175*36453Skfall #endif 176*36453Skfall 177*36453Skfall 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); 18811345Ssam } 189*36453Skfall 190*36453Skfall #ifdef KERBEROS 191*36453Skfall retval = do_krb_login(hp->h_name, fromp, encrypt); 192*36453Skfall write(f, &c, 1); 193*36453Skfall if(retval == 0) { 194*36453Skfall authenticated++; 195*36453Skfall } else { 196*36453Skfall if(retval > 0) 197*36453Skfall fatal(f, krb_err_txt[retval]); 198*36453Skfall } 199*36453Skfall #else 2006446Swnj if (fromp->sin_family != AF_INET || 20132116Skarels fromp->sin_port >= IPPORT_RESERVED || 20232116Skarels fromp->sin_port < IPPORT_RESERVED/2) 2039242Ssam fatal(f, "Permission denied"); 2046446Swnj write(f, "", 1); 205*36453Skfall if(do_rlogin(hp->h_name) == 0) 206*36453Skfall authenticated++; 207*36453Skfall #endif 208*36453Skfall 2096446Swnj for (c = 'p'; c <= 's'; c++) { 2106446Swnj struct stat stb; 2116446Swnj line = "/dev/ptyXX"; 2126446Swnj line[strlen("/dev/pty")] = c; 2136446Swnj line[strlen("/dev/ptyp")] = '0'; 2146446Swnj if (stat(line, &stb) < 0) 2156446Swnj break; 2166446Swnj for (i = 0; i < 16; i++) { 21734424Sbostic line[sizeof("/dev/ptyp") - 1] = "0123456789abcdef"[i]; 21834424Sbostic p = open(line, O_RDWR); 2196446Swnj if (p > 0) 2206446Swnj goto gotpty; 2216446Swnj } 2226446Swnj } 22324723Smckusick fatal(f, "Out of ptys"); 2249242Ssam /*NOTREACHED*/ 2256446Swnj gotpty: 22624889Smckusick (void) ioctl(p, TIOCSWINSZ, &win); 22716227Skarels netf = f; 2286446Swnj line[strlen("/dev/")] = 't'; 22934424Sbostic t = open(line, O_RDWR); 23034424Sbostic if (t < 0) 23134424Sbostic fatalperror(f, line); 23234424Sbostic if (fchmod(t, 0)) 23334424Sbostic fatalperror(f, line); 23434424Sbostic (void)signal(SIGHUP, SIG_IGN); 23534424Sbostic vhangup(); 23634424Sbostic (void)signal(SIGHUP, SIG_DFL); 23734424Sbostic t = open(line, O_RDWR); 23834424Sbostic if (t < 0) 23934424Sbostic fatalperror(f, line); 240*36453Skfall setup_term(t); 2416446Swnj #ifdef DEBUG 24234424Sbostic { 24334424Sbostic int tt = open("/dev/tty", O_RDWR); 24434424Sbostic if (tt > 0) { 24534424Sbostic (void)ioctl(tt, TIOCNOTTY, 0); 24634424Sbostic (void)close(tt); 24734424Sbostic } 2486446Swnj } 2496446Swnj #endif 2509242Ssam pid = fork(); 2519242Ssam if (pid < 0) 25234424Sbostic fatalperror(f, ""); 25318357Ssam if (pid == 0) { 254*36453Skfall if(setsid() < 0) 255*36453Skfall fatalperror(f, "setsid"); 256*36453Skfall if(ioctl(t, TIOCSCTTY, 0) < 0) 257*36453Skfall fatalperror(f, "ioctl(sctty)"); 25818357Ssam close(f), close(p); 25918357Ssam dup2(t, 0), dup2(t, 1), dup2(t, 2); 26016227Skarels close(t); 261*36453Skfall if(authenticated) 262*36453Skfall execl("/bin/login", "login", 263*36453Skfall "-h", hp->h_name, 264*36453Skfall "-f", pwd->pw_name, 265*36453Skfall "-p", 0 266*36453Skfall ); 267*36453Skfall else 268*36453Skfall execl("/bin/login", "login", 269*36453Skfall "-h", hp->h_name, 270*36453Skfall "-p", pwd->pw_name, 271*36453Skfall 0 272*36453Skfall ); 27334424Sbostic fatalperror(2, "/bin/login"); 27418357Ssam /*NOTREACHED*/ 27518357Ssam } 27618357Ssam close(t); 277*36453Skfall 278*36453Skfall #ifdef KERBEROS 279*36453Skfall /* 280*36453Skfall * If encrypted, don't turn on NBIO or the des read/write 281*36453Skfall * routines will croak. 282*36453Skfall */ 283*36453Skfall 284*36453Skfall if(encrypt) 285*36453Skfall (void) des_write(f, SECURE_MESSAGE, sizeof(SECURE_MESSAGE)); 286*36453Skfall else 287*36453Skfall ioctl(f, FIONBIO, &on); 288*36453Skfall #else 28918357Ssam ioctl(f, FIONBIO, &on); 290*36453Skfall #endif 291*36453Skfall 29218357Ssam ioctl(p, FIONBIO, &on); 29318357Ssam ioctl(p, TIOCPKT, &on); 29418357Ssam signal(SIGTSTP, SIG_IGN); 29518357Ssam signal(SIGCHLD, cleanup); 29624724Smckusick setpgrp(0, 0); 29718357Ssam protocol(f, p); 29830600Smckusick signal(SIGCHLD, SIG_IGN); 29918357Ssam cleanup(); 30018357Ssam } 3019242Ssam 30218357Ssam char magic[2] = { 0377, 0377 }; 30325423Skarels char oobdata[] = {TIOCPKT_WINDOW}; 30418357Ssam 30518357Ssam /* 30618357Ssam * Handle a "control" request (signaled by magic being present) 30718357Ssam * in the data stream. For now, we are only willing to handle 30818357Ssam * window size changes. 30918357Ssam */ 31018357Ssam control(pty, cp, n) 31118357Ssam int pty; 31218357Ssam char *cp; 31318357Ssam int n; 31418357Ssam { 31528705Smckusick struct winsize w; 31618357Ssam 31728705Smckusick if (n < 4+sizeof (w) || cp[2] != 's' || cp[3] != 's') 31818357Ssam return (0); 31925423Skarels oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */ 32028705Smckusick bcopy(cp+4, (char *)&w, sizeof(w)); 32128705Smckusick w.ws_row = ntohs(w.ws_row); 32228705Smckusick w.ws_col = ntohs(w.ws_col); 32328705Smckusick w.ws_xpixel = ntohs(w.ws_xpixel); 32428705Smckusick w.ws_ypixel = ntohs(w.ws_ypixel); 32528705Smckusick (void)ioctl(pty, TIOCSWINSZ, &w); 32628705Smckusick return (4+sizeof (w)); 32718357Ssam } 32818357Ssam 32918357Ssam /* 33018357Ssam * rlogin "protocol" machine. 33118357Ssam */ 33218357Ssam protocol(f, p) 33318357Ssam int f, p; 33418357Ssam { 33518357Ssam char pibuf[1024], fibuf[1024], *pbp, *fbp; 33618357Ssam register pcc = 0, fcc = 0; 33725423Skarels int cc; 33825740Skarels char cntl; 33918357Ssam 34018482Ssam /* 34118484Ssam * Must ignore SIGTTOU, otherwise we'll stop 34218484Ssam * when we try and set slave pty's window shape 34325423Skarels * (our controlling tty is the master pty). 34418482Ssam */ 34518484Ssam (void) signal(SIGTTOU, SIG_IGN); 34625423Skarels send(f, oobdata, 1, MSG_OOB); /* indicate new rlogin */ 34718357Ssam for (;;) { 34825740Skarels int ibits, obits, ebits; 34918357Ssam 35025740Skarels ibits = 0; 35125740Skarels obits = 0; 35218357Ssam if (fcc) 35318357Ssam obits |= (1<<p); 35418357Ssam else 35518357Ssam ibits |= (1<<f); 35618357Ssam if (pcc >= 0) 35718357Ssam if (pcc) 35818357Ssam obits |= (1<<f); 3599242Ssam else 36018357Ssam ibits |= (1<<p); 36125740Skarels ebits = (1<<p); 36225740Skarels if (select(16, &ibits, &obits, &ebits, 0) < 0) { 36318357Ssam if (errno == EINTR) 3646446Swnj continue; 36534424Sbostic fatalperror(f, "select"); 36618357Ssam } 36725740Skarels if (ibits == 0 && obits == 0 && ebits == 0) { 36818357Ssam /* shouldn't happen... */ 36918357Ssam sleep(5); 37018357Ssam continue; 37118357Ssam } 37225740Skarels #define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP)) 37325740Skarels if (ebits & (1<<p)) { 37425740Skarels cc = read(p, &cntl, 1); 37525740Skarels if (cc == 1 && pkcontrol(cntl)) { 37625740Skarels cntl |= oobdata[0]; 37725740Skarels send(f, &cntl, 1, MSG_OOB); 37825740Skarels if (cntl & TIOCPKT_FLUSHWRITE) { 37925740Skarels pcc = 0; 38025740Skarels ibits &= ~(1<<p); 38125740Skarels } 38225740Skarels } 38325740Skarels } 38418357Ssam if (ibits & (1<<f)) { 385*36453Skfall #ifdef KERBEROS 386*36453Skfall if(encrypt) { 387*36453Skfall fcc = des_read(f, fibuf, sizeof(fibuf)); 388*36453Skfall } else { 389*36453Skfall fcc = read(f, fibuf, sizeof(fibuf)); 390*36453Skfall } 391*36453Skfall #else 39218357Ssam fcc = read(f, fibuf, sizeof (fibuf)); 393*36453Skfall #endif 39418357Ssam if (fcc < 0 && errno == EWOULDBLOCK) 39518357Ssam fcc = 0; 39618357Ssam else { 39718357Ssam register char *cp; 39818357Ssam int left, n; 39918357Ssam 40018357Ssam if (fcc <= 0) 40116227Skarels break; 40218357Ssam fbp = fibuf; 40324723Smckusick 40418357Ssam top: 40525423Skarels for (cp = fibuf; cp < fibuf+fcc-1; cp++) 40618357Ssam if (cp[0] == magic[0] && 40718357Ssam cp[1] == magic[1]) { 40818357Ssam left = fcc - (cp-fibuf); 40918357Ssam n = control(p, cp, left); 41018357Ssam if (n) { 41118357Ssam left -= n; 41218357Ssam if (left > 0) 41325423Skarels bcopy(cp+n, cp, left); 41418357Ssam fcc -= n; 41518357Ssam goto top; /* n^2 */ 41625423Skarels } 41725423Skarels } 41825423Skarels } 41925423Skarels } 42024723Smckusick 42124723Smckusick if ((obits & (1<<p)) && fcc > 0) { 42225423Skarels cc = write(p, fbp, fcc); 42324723Smckusick if (cc > 0) { 42424723Smckusick fcc -= cc; 42524723Smckusick fbp += cc; 4266446Swnj } 42718357Ssam } 42824723Smckusick 42918357Ssam if (ibits & (1<<p)) { 43018357Ssam pcc = read(p, pibuf, sizeof (pibuf)); 43118357Ssam pbp = pibuf; 43218357Ssam if (pcc < 0 && errno == EWOULDBLOCK) 43318357Ssam pcc = 0; 43418357Ssam else if (pcc <= 0) 43518357Ssam break; 43618357Ssam else if (pibuf[0] == 0) 43718357Ssam pbp++, pcc--; 43818357Ssam else { 43918357Ssam if (pkcontrol(pibuf[0])) { 44025423Skarels pibuf[0] |= oobdata[0]; 44118357Ssam send(f, &pibuf[0], 1, MSG_OOB); 44216227Skarels } 44318357Ssam pcc = 0; 4446446Swnj } 44518357Ssam } 44618357Ssam if ((obits & (1<<f)) && pcc > 0) { 447*36453Skfall #ifdef KERBEROS 448*36453Skfall if(encrypt) { 449*36453Skfall cc = des_write(f, pbp, pcc); 450*36453Skfall } else { 451*36453Skfall cc = write(f, pbp, pcc); 452*36453Skfall } 453*36453Skfall #else 45425423Skarels cc = write(f, pbp, pcc); 455*36453Skfall #endif 45625423Skarels if (cc < 0 && errno == EWOULDBLOCK) { 45725423Skarels /* also shouldn't happen */ 45825423Skarels sleep(5); 45925423Skarels continue; 46025423Skarels } 46118357Ssam if (cc > 0) { 46218357Ssam pcc -= cc; 46318357Ssam pbp += cc; 46418357Ssam } 4656446Swnj } 4666446Swnj } 4676446Swnj } 4686446Swnj 4696446Swnj cleanup() 4706446Swnj { 47135440Sbostic char *p; 47235440Sbostic 47335440Sbostic p = line + sizeof("/dev/") - 1; 47435440Sbostic if (logout(p)) 47535440Sbostic logwtmp(p, "", ""); 47635440Sbostic (void)chmod(line, 0666); 47735440Sbostic (void)chown(line, 0, 0); 47835440Sbostic *p = 'p'; 47935440Sbostic (void)chmod(line, 0666); 48035440Sbostic (void)chown(line, 0, 0); 48110192Ssam shutdown(netf, 2); 4826446Swnj exit(1); 4836446Swnj } 4846446Swnj 4859242Ssam fatal(f, msg) 4869242Ssam int f; 4879242Ssam char *msg; 4889242Ssam { 4899242Ssam char buf[BUFSIZ]; 4909242Ssam 4919242Ssam buf[0] = '\01'; /* error indicator */ 49213554Ssam (void) sprintf(buf + 1, "rlogind: %s.\r\n", msg); 4939242Ssam (void) write(f, buf, strlen(buf)); 4949242Ssam exit(1); 4959242Ssam } 4969242Ssam 49734424Sbostic fatalperror(f, msg) 4989242Ssam int f; 4999242Ssam char *msg; 5009242Ssam { 5019242Ssam char buf[BUFSIZ]; 50216227Skarels extern int sys_nerr; 5039242Ssam extern char *sys_errlist[]; 5049242Ssam 50518357Ssam if ((unsigned)errno < sys_nerr) 50616227Skarels (void) sprintf(buf, "%s: %s", msg, sys_errlist[errno]); 50716227Skarels else 50816227Skarels (void) sprintf(buf, "%s: Error %d", msg, errno); 5099242Ssam fatal(f, buf); 5109242Ssam } 511*36453Skfall 512*36453Skfall 513*36453Skfall int 514*36453Skfall do_rlogin(host) 515*36453Skfall char *host; 516*36453Skfall { 517*36453Skfall getstr(rusername, sizeof(rusername), "remuser"); 518*36453Skfall getstr(lusername, sizeof(lusername), "locuser"); 519*36453Skfall getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type"); 520*36453Skfall 521*36453Skfall if(getuid()) { 522*36453Skfall pwd = &nouser; 523*36453Skfall return(-1); 524*36453Skfall } 525*36453Skfall pwd = getpwnam(lusername); 526*36453Skfall if(pwd == NULL) { 527*36453Skfall pwd = &nouser; 528*36453Skfall pwd->pw_name = lusername; /* pass on to login */ 529*36453Skfall return(-1); 530*36453Skfall } 531*36453Skfall return(ruserok(host, SUPERUSER(pwd), rusername, lusername)); 532*36453Skfall } 533*36453Skfall 534*36453Skfall 535*36453Skfall getstr(buf, cnt, err) 536*36453Skfall char *buf; 537*36453Skfall int cnt; 538*36453Skfall char *err; 539*36453Skfall { 540*36453Skfall char c; 541*36453Skfall do { 542*36453Skfall if(read(0, &c, 1) != 1) 543*36453Skfall exit(1); 544*36453Skfall if(--cnt < 0) { 545*36453Skfall printf("%s too long\r\n", err); 546*36453Skfall exit(1); 547*36453Skfall } 548*36453Skfall *buf++ = c; 549*36453Skfall } while(c != 0); 550*36453Skfall } 551*36453Skfall 552*36453Skfall extern char **environ; 553*36453Skfall 554*36453Skfall setup_term(fd) 555*36453Skfall int fd; 556*36453Skfall { 557*36453Skfall struct termios tt; 558*36453Skfall struct sgttyb tp; 559*36453Skfall register char *cp = index(term+ENVSIZE, '/'), **cpp; 560*36453Skfall char *speed; 561*36453Skfall 562*36453Skfall tcgetattr(fd, &tt); 563*36453Skfall if(cp) { 564*36453Skfall *cp++ = '\0'; 565*36453Skfall speed = cp; 566*36453Skfall cp = index(speed, '/'); 567*36453Skfall if(cp) 568*36453Skfall *cp++ = '\0'; 569*36453Skfall cfsetspeed(&tt, atoi(speed)); 570*36453Skfall } 571*36453Skfall tt.c_iflag = BRKINT|ICRNL|IXON|ISTRIP|IEXTEN|IMAXBEL; 572*36453Skfall tt.c_oflag = OPOST|ONLCR|OXTABS; 573*36453Skfall tt.c_lflag = ISIG|ICANON|ECHO; 574*36453Skfall tcsetattr(fd, TCSADFLUSH, &tt); 575*36453Skfall 576*36453Skfall envinit[0] = term; 577*36453Skfall envinit[1] = 0; 578*36453Skfall environ = envinit; 579*36453Skfall } 580*36453Skfall 581*36453Skfall #ifdef KERBEROS 582*36453Skfall #define VERSION_SIZE 9 583*36453Skfall 584*36453Skfall /* 585*36453Skfall * Do the remote kerberos login to the named host with the 586*36453Skfall * given inet address 587*36453Skfall * 588*36453Skfall * Return 0 on valid authorization 589*36453Skfall * Return -1 on valid authentication, no authorization 590*36453Skfall * Return >0 for error conditions 591*36453Skfall */ 592*36453Skfall 593*36453Skfall int 594*36453Skfall do_krb_login(host, dest, encrypt) 595*36453Skfall char *host; 596*36453Skfall struct sockaddr_in *dest; 597*36453Skfall int encrypt; 598*36453Skfall { 599*36453Skfall int rc; 600*36453Skfall char instance[INST_SZ], version[VERSION_SIZE]; 601*36453Skfall long authopts = 0L; /* !mutual */ 602*36453Skfall struct sockaddr_in faddr; 603*36453Skfall 604*36453Skfall if(getuid()) { 605*36453Skfall pwd = &nouser; 606*36453Skfall return(KFAILURE); 607*36453Skfall } 608*36453Skfall 609*36453Skfall kdata = (AUTH_DAT *) auth_buf; 610*36453Skfall ticket = (KTEXT) tick_buf; 611*36453Skfall strcpy(instance, "*"); 612*36453Skfall 613*36453Skfall if(encrypt) { 614*36453Skfall rc = sizeof(faddr); 615*36453Skfall if(getsockname(0, &faddr, &rc)) { 616*36453Skfall pwd = &nouser; 617*36453Skfall return(-1); 618*36453Skfall } 619*36453Skfall authopts = KOPT_DO_MUTUAL; 620*36453Skfall rc = krb_recvauth( 621*36453Skfall authopts, 0, 622*36453Skfall ticket, "rcmd", 623*36453Skfall instance, dest, &faddr, 624*36453Skfall kdata, "", schedule, version 625*36453Skfall ); 626*36453Skfall des_set_key(kdata->session, schedule); 627*36453Skfall 628*36453Skfall } else { 629*36453Skfall rc = krb_recvauth( 630*36453Skfall authopts, 0, 631*36453Skfall ticket, "rcmd", 632*36453Skfall instance, dest, (struct sockaddr_in *) 0, 633*36453Skfall kdata, "", (bit_64 *) 0, version 634*36453Skfall ); 635*36453Skfall } 636*36453Skfall 637*36453Skfall if(rc != KSUCCESS) { 638*36453Skfall pwd = &nouser; 639*36453Skfall return(rc); 640*36453Skfall } 641*36453Skfall 642*36453Skfall if((rc = krb_kntoln(kdata, rusername)) != KSUCCESS) { 643*36453Skfall pwd = &nouser; 644*36453Skfall return(rc); 645*36453Skfall } 646*36453Skfall 647*36453Skfall getstr(lusername, sizeof(lusername), "locuser"); 648*36453Skfall /* get the "cmd" in the rcmd protocol */ 649*36453Skfall getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type"); 650*36453Skfall 651*36453Skfall pwd = getpwnam(lusername); 652*36453Skfall if(pwd == NULL) { 653*36453Skfall pwd = &nouser; 654*36453Skfall pwd->pw_name = lusername; 655*36453Skfall return(-1); 656*36453Skfall } 657*36453Skfall 658*36453Skfall /* XXX need to use something other than ruserok */ 659*36453Skfall /* returns -1 for invalid authentication */ 660*36453Skfall return(ruserok(host, SUPERUSER(pwd), rusername, lusername)); 661*36453Skfall } 662*36453Skfall #endif 663