147928Sbostic /*- 240917Skarels * Copyright (c) 1983, 1988, 1989 The Regents of the University of California. 335441Sbostic * All rights reserved. 435441Sbostic * 547928Sbostic * %sccs.include.redist.c% 621174Sdist */ 721174Sdist 86446Swnj #ifndef lint 921174Sdist char copyright[] = 1040917Skarels "@(#) Copyright (c) 1983, 1988, 1989 The Regents of the University of California.\n\ 1121174Sdist All rights reserved.\n"; 1235441Sbostic #endif /* not lint */ 136446Swnj 1421174Sdist #ifndef lint 15*54547Sleres static char sccsid[] = "@(#)rlogind.c 5.54 (Berkeley) 06/29/92"; 1635441Sbostic #endif /* not lint */ 1721174Sdist 1840917Skarels #ifdef KERBEROS 1940917Skarels /* From: 2040917Skarels * $Source: /mit/kerberos/ucb/mit/rlogind/RCS/rlogind.c,v $ 2140917Skarels * $Header: rlogind.c,v 5.0 89/06/26 18:31:01 kfall Locked $ 2240917Skarels */ 2340917Skarels #endif 2440917Skarels 2516369Skarels /* 2616369Skarels * remote login server: 2736453Skfall * \0 2816369Skarels * remuser\0 2916369Skarels * locuser\0 3036453Skfall * terminal_type/speed\0 3136518Skarels * data 3216369Skarels */ 3316369Skarels 3440917Skarels #define FD_SETSIZE 16 /* don't need many bits for select */ 3537290Sbostic #include <sys/param.h> 366446Swnj #include <sys/stat.h> 3737290Sbostic #include <sys/ioctl.h> 3846982Sbostic #include <signal.h> 3946982Sbostic #include <termios.h> 409208Ssam 4146982Sbostic #include <sys/socket.h> 429208Ssam #include <netinet/in.h> 4344347Skarels #include <netinet/in_systm.h> 4444347Skarels #include <netinet/ip.h> 4546982Sbostic #include <arpa/inet.h> 4646982Sbostic #include <netdb.h> 479208Ssam 486446Swnj #include <pwd.h> 4917187Sralph #include <syslog.h> 5046982Sbostic #include <errno.h> 5140917Skarels #include <stdio.h> 5240917Skarels #include <unistd.h> 5346982Sbostic #include <stdlib.h> 5446982Sbostic #include <string.h> 5540917Skarels #include "pathnames.h" 566446Swnj 5736518Skarels #ifndef TIOCPKT_WINDOW 5836518Skarels #define TIOCPKT_WINDOW 0x80 5936518Skarels #endif 6036518Skarels 6140917Skarels #ifdef KERBEROS 6241761Skfall #include <kerberosIV/des.h> 6340917Skarels #include <kerberosIV/krb.h> 6440917Skarels #define SECURE_MESSAGE "This rlogin session is using DES encryption for all transmissions.\r\n" 6540917Skarels 6640917Skarels AUTH_DAT *kdata; 6740917Skarels KTEXT ticket; 6840917Skarels u_char auth_buf[sizeof(AUTH_DAT)]; 6940917Skarels u_char tick_buf[sizeof(KTEXT_ST)]; 7040917Skarels Key_schedule schedule; 7146982Sbostic int doencrypt, retval, use_kerberos, vacuous; 7240917Skarels 7340917Skarels #define ARGSTR "alnkvx" 7440917Skarels #else 7540917Skarels #define ARGSTR "aln" 7640917Skarels #endif /* KERBEROS */ 7740917Skarels 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; 8439058Skarels int check_all = 0; 8536453Skfall 8646982Sbostic struct passwd *pwd; 8716369Skarels 88*54547Sleres void doit __P((int, struct sockaddr_in *)); 89*54547Sleres int control __P((int, char *, int)); 90*54547Sleres void protocol __P((int, int)); 91*54547Sleres void cleanup __P((void)); 92*54547Sleres void fatal __P((int, char *, int)); 93*54547Sleres int do_rlogin __P((struct sockaddr_in *)); 94*54547Sleres void getstr __P((char *, int, char *)); 95*54547Sleres void setup_term __P((int)); 96*54547Sleres int do_krb_login __P((struct sockaddr_in *)); 97*54547Sleres void usage __P((void)); 98*54547Sleres int local_domain __P((char *)); 99*54547Sleres char *topdomain __P((char *)); 100*54547Sleres 101*54547Sleres int 1026446Swnj main(argc, argv) 1036446Swnj int argc; 104*54547Sleres char *argv[]; 1056446Swnj { 106*54547Sleres extern int __check_rhosts_file; 1076446Swnj struct sockaddr_in from; 108*54547Sleres int ch, fromlen, on; 1096446Swnj 11036625Skfall openlog("rlogind", LOG_PID | LOG_CONS, LOG_AUTH); 11136319Sbostic 11236319Sbostic opterr = 0; 11340917Skarels while ((ch = getopt(argc, argv, ARGSTR)) != EOF) 11436517Skarels switch (ch) { 11539058Skarels case 'a': 11639058Skarels check_all = 1; 11739058Skarels break; 11836319Sbostic case 'l': 119*54547Sleres __check_rhosts_file = 0; 12036319Sbostic break; 12136517Skarels case 'n': 12236517Skarels keepalive = 0; 12336517Skarels break; 12440917Skarels #ifdef KERBEROS 12540917Skarels case 'k': 12640917Skarels use_kerberos = 1; 12740917Skarels break; 12840917Skarels case 'v': 12940917Skarels vacuous = 1; 13040917Skarels break; 131*54547Sleres #ifdef CRYPT 132*54547Sleres case 'x': 133*54547Sleres doencrypt = 1; 134*54547Sleres break; 13540917Skarels #endif 136*54547Sleres #endif 13736319Sbostic case '?': 13836319Sbostic default: 13940917Skarels usage(); 14036319Sbostic break; 14136319Sbostic } 14236319Sbostic argc -= optind; 14336319Sbostic argv += optind; 14436319Sbostic 14540917Skarels #ifdef KERBEROS 14640917Skarels if (use_kerberos && vacuous) { 14740917Skarels usage(); 14840917Skarels fatal(STDERR_FILENO, "only one of -k and -v allowed", 0); 14940917Skarels } 15040917Skarels #endif 15116369Skarels fromlen = sizeof (from); 15246982Sbostic if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { 15340917Skarels syslog(LOG_ERR,"Can't get peer name of remote host: %m"); 15440917Skarels fatal(STDERR_FILENO, "Can't get peer name of remote host", 1); 1558380Ssam } 156*54547Sleres on = 1; 15736517Skarels if (keepalive && 15836517Skarels setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) 15917187Sralph syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); 16044347Skarels on = IPTOS_LOWDELAY; 16144347Skarels if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) 16244347Skarels syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); 16316369Skarels doit(0, &from); 1646446Swnj } 1656446Swnj 1666446Swnj int child; 16746982Sbostic void cleanup(); 1686446Swnj int netf; 16944349Smarc char line[MAXPATHLEN]; 17040917Skarels int confirmed; 1716446Swnj 17224889Smckusick struct winsize win = { 0, 0, 0, 0 }; 17324723Smckusick 17424889Smckusick 175*54547Sleres void 1766446Swnj doit(f, fromp) 1776446Swnj int f; 1786446Swnj struct sockaddr_in *fromp; 1796446Swnj { 180*54547Sleres int master, pid, on = 1; 181*54547Sleres int authenticated = 0; 18240917Skarels register struct hostent *hp; 183*54547Sleres register char *hostname; 18439249Smarc char remotehost[2 * MAXHOSTNAMELEN + 1]; 1858380Ssam char c; 1866446Swnj 1876446Swnj alarm(60); 1886446Swnj read(f, &c, 1); 18940917Skarels 19039249Smarc if (c != 0) 19136715Skfall exit(1); 19240917Skarels #ifdef KERBEROS 19340917Skarels if (vacuous) 19440917Skarels fatal(f, "Remote host requires Kerberos authentication", 0); 19540917Skarels #endif 19636453Skfall 1976446Swnj alarm(0); 19816227Skarels fromp->sin_port = ntohs((u_short)fromp->sin_port); 19946982Sbostic hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof(struct in_addr), 200*54547Sleres fromp->sin_family); 201*54547Sleres if (hp) 202*54547Sleres hostname = hp->h_name; 203*54547Sleres else 204*54547Sleres hostname = strcpy(remotehost, inet_ntoa(fromp->sin_addr)); 20536711Skfall 20640917Skarels #ifdef KERBEROS 20740917Skarels if (use_kerberos) { 208*54547Sleres retval = do_krb_login(fromp); 20942264Sbostic if (retval == 0) 21040917Skarels authenticated++; 21140917Skarels else if (retval > 0) 21240917Skarels fatal(f, krb_err_txt[retval], 0); 21340917Skarels write(f, &c, 1); 21440917Skarels confirmed = 1; /* we sent the null! */ 21540917Skarels } else 21640917Skarels #endif 21740917Skarels { 218*54547Sleres if (fromp->sin_family != AF_INET || 219*54547Sleres fromp->sin_port >= IPPORT_RESERVED || 220*54547Sleres fromp->sin_port < IPPORT_RESERVED/2) { 221*54547Sleres syslog(LOG_NOTICE, "Connection from %s on illegal port", 222*54547Sleres inet_ntoa(fromp->sin_addr)); 223*54547Sleres fatal(f, "Permission denied", 0); 224*54547Sleres } 22536702Skarels #ifdef IP_OPTIONS 226*54547Sleres { 227*54547Sleres u_char optbuf[BUFSIZ/3], *cp; 228*54547Sleres char lbuf[BUFSIZ], *lp; 229*54547Sleres int optsize = sizeof(optbuf), ipproto; 230*54547Sleres struct protoent *ip; 23136702Skarels 232*54547Sleres if ((ip = getprotobyname("ip")) != NULL) 233*54547Sleres ipproto = ip->p_proto; 234*54547Sleres else 235*54547Sleres ipproto = IPPROTO_IP; 236*54547Sleres if (getsockopt(0, ipproto, IP_OPTIONS, (char *)optbuf, 237*54547Sleres &optsize) == 0 && optsize != 0) { 238*54547Sleres lp = lbuf; 239*54547Sleres for (cp = optbuf; optsize > 0; cp++, optsize--, lp += 3) 240*54547Sleres sprintf(lp, " %2.2x", *cp); 241*54547Sleres syslog(LOG_NOTICE, 242*54547Sleres "Connection received using IP options (ignored):%s", 243*54547Sleres lbuf); 244*54547Sleres if (setsockopt(0, ipproto, IP_OPTIONS, 245*54547Sleres (char *)NULL, optsize) != 0) { 246*54547Sleres syslog(LOG_ERR, 247*54547Sleres "setsockopt IP_OPTIONS NULL: %m"); 248*54547Sleres exit(1); 249*54547Sleres } 250*54547Sleres } 251*54547Sleres } 25236702Skarels #endif 253*54547Sleres if (do_rlogin(fromp) == 0) 254*54547Sleres authenticated++; 25536631Skarels } 25640917Skarels if (confirmed == 0) { 25740917Skarels write(f, "", 1); 25840917Skarels confirmed = 1; /* we sent the null! */ 25939249Smarc } 26040917Skarels #ifdef KERBEROS 261*54547Sleres #ifdef CRYPT 262*54547Sleres if (doencrypt) 263*54547Sleres (void) des_write(f, SECURE_MESSAGE, sizeof(SECURE_MESSAGE)); 26439249Smarc #endif 265*54547Sleres #endif 26644349Smarc netf = f; 26744349Smarc 26844349Smarc pid = forkpty(&master, line, NULL, &win); 26944349Smarc if (pid < 0) { 27044349Smarc if (errno == ENOENT) 27144349Smarc fatal(f, "Out of ptys", 0); 27244349Smarc else 27344349Smarc fatal(f, "Forkpty", 1); 27444349Smarc } 27518357Ssam if (pid == 0) { 276*54547Sleres if (f > 2) /* f should always be 0, but... */ 27744349Smarc (void) close(f); 27844349Smarc setup_term(0); 27943363Skfall if (authenticated) { 28044347Skarels #ifdef KERBEROS 28143363Skfall if (use_kerberos && (pwd->pw_uid == 0)) 28243363Skfall syslog(LOG_INFO|LOG_AUTH, 28343363Skfall "ROOT Kerberos login from %s.%s@%s on %s\n", 28443363Skfall kdata->pname, kdata->pinst, kdata->prealm, 285*54547Sleres hostname); 28644347Skarels #endif 28743363Skfall 28840917Skarels execl(_PATH_LOGIN, "login", "-p", 289*54547Sleres "-h", hostname, "-f", lusername, (char *)NULL); 29043363Skfall } else 29140917Skarels execl(_PATH_LOGIN, "login", "-p", 292*54547Sleres "-h", hostname, lusername, (char *)NULL); 29340917Skarels fatal(STDERR_FILENO, _PATH_LOGIN, 1); 29418357Ssam /*NOTREACHED*/ 29518357Ssam } 296*54547Sleres #ifdef CRYPT 297*54547Sleres #ifdef KERBEROS 298*54547Sleres /* 299*54547Sleres * If encrypted, don't turn on NBIO or the des read/write 300*54547Sleres * routines will croak. 301*54547Sleres */ 302*54547Sleres 303*54547Sleres if (!doencrypt) 304*54547Sleres #endif 305*54547Sleres #endif 30640917Skarels ioctl(f, FIONBIO, &on); 30744349Smarc ioctl(master, FIONBIO, &on); 30844349Smarc ioctl(master, TIOCPKT, &on); 30918357Ssam signal(SIGCHLD, cleanup); 31044349Smarc protocol(f, master); 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 */ 323*54547Sleres int 32418357Ssam control(pty, cp, n) 32518357Ssam int pty; 32618357Ssam char *cp; 32718357Ssam int n; 32818357Ssam { 32928705Smckusick struct winsize w; 33018357Ssam 33128705Smckusick if (n < 4+sizeof (w) || cp[2] != 's' || cp[3] != 's') 33218357Ssam return (0); 33325423Skarels oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */ 33428705Smckusick bcopy(cp+4, (char *)&w, sizeof(w)); 33528705Smckusick w.ws_row = ntohs(w.ws_row); 33628705Smckusick w.ws_col = ntohs(w.ws_col); 33728705Smckusick w.ws_xpixel = ntohs(w.ws_xpixel); 33828705Smckusick w.ws_ypixel = ntohs(w.ws_ypixel); 33928705Smckusick (void)ioctl(pty, TIOCSWINSZ, &w); 34028705Smckusick return (4+sizeof (w)); 34118357Ssam } 34218357Ssam 34318357Ssam /* 34418357Ssam * rlogin "protocol" machine. 34518357Ssam */ 346*54547Sleres void 34718357Ssam protocol(f, p) 34840917Skarels register int f, p; 34918357Ssam { 35040917Skarels char pibuf[1024+1], fibuf[1024], *pbp, *fbp; 35118357Ssam register pcc = 0, fcc = 0; 35240917Skarels int cc, nfd, n; 35325740Skarels char cntl; 35418357Ssam 35518482Ssam /* 35618484Ssam * Must ignore SIGTTOU, otherwise we'll stop 35718484Ssam * when we try and set slave pty's window shape 35825423Skarels * (our controlling tty is the master pty). 35918482Ssam */ 36018484Ssam (void) signal(SIGTTOU, SIG_IGN); 36125423Skarels send(f, oobdata, 1, MSG_OOB); /* indicate new rlogin */ 36236517Skarels if (f > p) 36336517Skarels nfd = f + 1; 36436517Skarels else 36536517Skarels nfd = p + 1; 36640917Skarels if (nfd > FD_SETSIZE) { 36740917Skarels syslog(LOG_ERR, "select mask too small, increase FD_SETSIZE"); 36840917Skarels fatal(f, "internal error (select mask too small)", 0); 36940917Skarels } 37018357Ssam for (;;) { 37140917Skarels fd_set ibits, obits, ebits, *omask; 37218357Ssam 37342956Sbostic FD_ZERO(&ebits); 37440917Skarels FD_ZERO(&ibits); 37540917Skarels FD_ZERO(&obits); 37640917Skarels omask = (fd_set *)NULL; 37740917Skarels if (fcc) { 37840917Skarels FD_SET(p, &obits); 37940917Skarels omask = &obits; 38040917Skarels } else 38140917Skarels FD_SET(f, &ibits); 38218357Ssam if (pcc >= 0) 38340917Skarels if (pcc) { 38440917Skarels FD_SET(f, &obits); 38540917Skarels omask = &obits; 38640917Skarels } else 38740917Skarels FD_SET(p, &ibits); 38840917Skarels FD_SET(p, &ebits); 38940917Skarels if ((n = select(nfd, &ibits, omask, &ebits, 0)) < 0) { 39018357Ssam if (errno == EINTR) 3916446Swnj continue; 39240917Skarels fatal(f, "select", 1); 39318357Ssam } 39440917Skarels if (n == 0) { 39518357Ssam /* shouldn't happen... */ 39618357Ssam sleep(5); 39718357Ssam continue; 39818357Ssam } 39925740Skarels #define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP)) 40040917Skarels if (FD_ISSET(p, &ebits)) { 40125740Skarels cc = read(p, &cntl, 1); 40225740Skarels if (cc == 1 && pkcontrol(cntl)) { 40325740Skarels cntl |= oobdata[0]; 40425740Skarels send(f, &cntl, 1, MSG_OOB); 40525740Skarels if (cntl & TIOCPKT_FLUSHWRITE) { 40625740Skarels pcc = 0; 40740917Skarels FD_CLR(p, &ibits); 40825740Skarels } 40925740Skarels } 41025740Skarels } 41140917Skarels if (FD_ISSET(f, &ibits)) { 412*54547Sleres #ifdef CRYPT 413*54547Sleres #ifdef KERBEROS 414*54547Sleres if (doencrypt) 415*54547Sleres fcc = des_read(f, fibuf, sizeof(fibuf)); 416*54547Sleres else 417*54547Sleres #endif 418*54547Sleres #endif 41940917Skarels fcc = read(f, fibuf, sizeof(fibuf)); 42018357Ssam if (fcc < 0 && errno == EWOULDBLOCK) 42118357Ssam fcc = 0; 42218357Ssam else { 42318357Ssam register char *cp; 42418357Ssam int left, n; 42518357Ssam 42618357Ssam if (fcc <= 0) 42716227Skarels break; 42818357Ssam fbp = fibuf; 42924723Smckusick 43018357Ssam top: 43125423Skarels for (cp = fibuf; cp < fibuf+fcc-1; cp++) 43218357Ssam if (cp[0] == magic[0] && 43318357Ssam cp[1] == magic[1]) { 43418357Ssam left = fcc - (cp-fibuf); 43518357Ssam n = control(p, cp, left); 43618357Ssam if (n) { 43718357Ssam left -= n; 43818357Ssam if (left > 0) 43925423Skarels bcopy(cp+n, cp, left); 44018357Ssam fcc -= n; 44118357Ssam goto top; /* n^2 */ 44225423Skarels } 44325423Skarels } 44440917Skarels FD_SET(p, &obits); /* try write */ 44525423Skarels } 44625423Skarels } 44724723Smckusick 44840917Skarels if (FD_ISSET(p, &obits) && fcc > 0) { 44925423Skarels cc = write(p, fbp, fcc); 45024723Smckusick if (cc > 0) { 45124723Smckusick fcc -= cc; 45224723Smckusick fbp += cc; 4536446Swnj } 45418357Ssam } 45524723Smckusick 45640917Skarels if (FD_ISSET(p, &ibits)) { 45718357Ssam pcc = read(p, pibuf, sizeof (pibuf)); 45818357Ssam pbp = pibuf; 45918357Ssam if (pcc < 0 && errno == EWOULDBLOCK) 46018357Ssam pcc = 0; 46118357Ssam else if (pcc <= 0) 46218357Ssam break; 46336517Skarels else if (pibuf[0] == 0) { 46418357Ssam pbp++, pcc--; 465*54547Sleres #ifdef CRYPT 466*54547Sleres #ifdef KERBEROS 467*54547Sleres if (!doencrypt) 468*54547Sleres #endif 469*54547Sleres #endif 47040917Skarels FD_SET(f, &obits); /* try write */ 47136517Skarels } else { 47218357Ssam if (pkcontrol(pibuf[0])) { 47325423Skarels pibuf[0] |= oobdata[0]; 47418357Ssam send(f, &pibuf[0], 1, MSG_OOB); 47516227Skarels } 47618357Ssam pcc = 0; 4776446Swnj } 47818357Ssam } 47940917Skarels if ((FD_ISSET(f, &obits)) && pcc > 0) { 480*54547Sleres #ifdef CRYPT 481*54547Sleres #ifdef KERBEROS 482*54547Sleres if (doencrypt) 483*54547Sleres cc = des_write(f, pbp, pcc); 484*54547Sleres else 485*54547Sleres #endif 486*54547Sleres #endif 48740917Skarels cc = write(f, pbp, pcc); 48825423Skarels if (cc < 0 && errno == EWOULDBLOCK) { 48940917Skarels /* 49040917Skarels * This happens when we try write after read 49140917Skarels * from p, but some old kernels balk at large 49240917Skarels * writes even when select returns true. 49340917Skarels */ 49440917Skarels if (!FD_ISSET(p, &ibits)) 49540917Skarels sleep(5); 49625423Skarels continue; 49725423Skarels } 49818357Ssam if (cc > 0) { 49918357Ssam pcc -= cc; 50018357Ssam pbp += cc; 50118357Ssam } 5026446Swnj } 5036446Swnj } 5046446Swnj } 5056446Swnj 50646982Sbostic void 5076446Swnj cleanup() 5086446Swnj { 50935440Sbostic char *p; 51035440Sbostic 51140917Skarels p = line + sizeof(_PATH_DEV) - 1; 51235440Sbostic if (logout(p)) 51335440Sbostic logwtmp(p, "", ""); 51448380Skarels (void)chmod(line, 0666); 51535440Sbostic (void)chown(line, 0, 0); 51635440Sbostic *p = 'p'; 51748380Skarels (void)chmod(line, 0666); 51835440Sbostic (void)chown(line, 0, 0); 51910192Ssam shutdown(netf, 2); 5206446Swnj exit(1); 5216446Swnj } 5226446Swnj 523*54547Sleres void 52440917Skarels fatal(f, msg, syserr) 525*54547Sleres int f; 5269242Ssam char *msg; 527*54547Sleres int syserr; 5289242Ssam { 52940917Skarels int len; 53040917Skarels char buf[BUFSIZ], *bp = buf; 5319242Ssam 53240917Skarels /* 53340917Skarels * Prepend binary one to message if we haven't sent 53440917Skarels * the magic null as confirmation. 53540917Skarels */ 53640917Skarels if (!confirmed) 53740917Skarels *bp++ = '\01'; /* error indicator */ 53840917Skarels if (syserr) 53940917Skarels len = sprintf(bp, "rlogind: %s: %s.\r\n", 54040917Skarels msg, strerror(errno)); 54140917Skarels else 54240917Skarels len = sprintf(bp, "rlogind: %s.\r\n", msg); 54340917Skarels (void) write(f, buf, bp + len - buf); 5449242Ssam exit(1); 5459242Ssam } 5469242Ssam 547*54547Sleres int 548*54547Sleres do_rlogin(dest) 549*54547Sleres struct sockaddr_in *dest; 55036453Skfall { 55136518Skarels getstr(rusername, sizeof(rusername), "remuser too long"); 55236518Skarels getstr(lusername, sizeof(lusername), "locuser too long"); 55336518Skarels getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type too long"); 55436518Skarels 55536453Skfall pwd = getpwnam(lusername); 55636518Skarels if (pwd == NULL) 557*54547Sleres return (-1); 55842264Sbostic if (pwd->pw_uid == 0) 559*54547Sleres return (-1); 560*54547Sleres /* XXX why don't we syslog() failure? */ 561*54547Sleres return (iruserok(dest->sin_addr.s_addr, 0, rusername, lusername)); 56236453Skfall } 56336453Skfall 564*54547Sleres void 56536518Skarels getstr(buf, cnt, errmsg) 56636518Skarels char *buf; 56736518Skarels int cnt; 56836518Skarels char *errmsg; 56936453Skfall { 57036518Skarels char c; 57136518Skarels 57236453Skfall do { 57336518Skarels if (read(0, &c, 1) != 1) 57436453Skfall exit(1); 57536518Skarels if (--cnt < 0) 57640917Skarels fatal(STDOUT_FILENO, errmsg, 0); 57736453Skfall *buf++ = c; 57836518Skarels } while (c != 0); 57936453Skfall } 58036453Skfall 58136518Skarels extern char **environ; 58236453Skfall 583*54547Sleres void 58436519Skarels setup_term(fd) 58536519Skarels int fd; 58636519Skarels { 58740917Skarels register char *cp = index(term+ENVSIZE, '/'); 58836519Skarels char *speed; 58939118Skarels struct termios tt; 59036519Skarels 59140917Skarels #ifndef notyet 59236711Skfall tcgetattr(fd, &tt); 59336519Skarels if (cp) { 59436519Skarels *cp++ = '\0'; 59536519Skarels speed = cp; 59636519Skarels cp = index(speed, '/'); 59736519Skarels if (cp) 59836519Skarels *cp++ = '\0'; 59936711Skfall cfsetspeed(&tt, atoi(speed)); 60036519Skarels } 60138710Skfall 60239118Skarels tt.c_iflag = TTYDEF_IFLAG; 60339118Skarels tt.c_oflag = TTYDEF_OFLAG; 60439118Skarels tt.c_lflag = TTYDEF_LFLAG; 60543272Sbostic tcsetattr(fd, TCSAFLUSH, &tt); 60639118Skarels #else 60739118Skarels if (cp) { 60839118Skarels *cp++ = '\0'; 60939118Skarels speed = cp; 61039118Skarels cp = index(speed, '/'); 61139118Skarels if (cp) 61239118Skarels *cp++ = '\0'; 61340917Skarels tcgetattr(fd, &tt); 61440917Skarels cfsetspeed(&tt, atoi(speed)); 61543272Sbostic tcsetattr(fd, TCSAFLUSH, &tt); 61638710Skfall } 61738710Skfall #endif 61836519Skarels 61936519Skarels env[0] = term; 62036519Skarels env[1] = 0; 62136519Skarels environ = env; 62236519Skarels } 62336609Skfall 62440917Skarels #ifdef KERBEROS 62540917Skarels #define VERSION_SIZE 9 62640917Skarels 62736609Skfall /* 62840917Skarels * Do the remote kerberos login to the named host with the 62940917Skarels * given inet address 63040917Skarels * 63140917Skarels * Return 0 on valid authorization 63240917Skarels * Return -1 on valid authentication, no authorization 63340917Skarels * Return >0 for error conditions 63440917Skarels */ 635*54547Sleres int 636*54547Sleres do_krb_login(dest) 63740917Skarels struct sockaddr_in *dest; 63840917Skarels { 63940917Skarels int rc; 64040917Skarels char instance[INST_SZ], version[VERSION_SIZE]; 64140917Skarels long authopts = 0L; /* !mutual */ 64240917Skarels struct sockaddr_in faddr; 64340917Skarels 64440917Skarels kdata = (AUTH_DAT *) auth_buf; 64540917Skarels ticket = (KTEXT) tick_buf; 64640917Skarels 64742264Sbostic instance[0] = '*'; 64842264Sbostic instance[1] = '\0'; 64942264Sbostic 650*54547Sleres #ifdef CRYPT 651*54547Sleres if (doencrypt) { 652*54547Sleres rc = sizeof(faddr); 653*54547Sleres if (getsockname(0, (struct sockaddr *)&faddr, &rc)) 654*54547Sleres return (-1); 655*54547Sleres authopts = KOPT_DO_MUTUAL; 65640917Skarels rc = krb_recvauth( 65740917Skarels authopts, 0, 65840917Skarels ticket, "rcmd", 659*54547Sleres instance, dest, &faddr, 660*54547Sleres kdata, "", schedule, version); 661*54547Sleres des_set_key(kdata->session, schedule); 662*54547Sleres 663*54547Sleres } else 664*54547Sleres #endif 665*54547Sleres rc = krb_recvauth( 666*54547Sleres authopts, 0, 667*54547Sleres ticket, "rcmd", 66840917Skarels instance, dest, (struct sockaddr_in *) 0, 66940917Skarels kdata, "", (bit_64 *) 0, version); 67040917Skarels 67140917Skarels if (rc != KSUCCESS) 672*54547Sleres return (rc); 67340917Skarels 67440917Skarels getstr(lusername, sizeof(lusername), "locuser"); 67540917Skarels /* get the "cmd" in the rcmd protocol */ 67640917Skarels getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type"); 67740917Skarels 67840917Skarels pwd = getpwnam(lusername); 67940917Skarels if (pwd == NULL) 680*54547Sleres return (-1); 68140917Skarels 68240917Skarels /* returns nonzero for no access */ 683*54547Sleres if (kuserok(kdata, lusername) != 0) 684*54547Sleres return (-1); 68540917Skarels 686*54547Sleres return (0); 68740917Skarels 68840917Skarels } 68940917Skarels #endif /* KERBEROS */ 69040917Skarels 691*54547Sleres void 69240917Skarels usage() 69340917Skarels { 69440917Skarels #ifdef KERBEROS 69540917Skarels syslog(LOG_ERR, "usage: rlogind [-aln] [-k | -v]"); 69640917Skarels #else 69740917Skarels syslog(LOG_ERR, "usage: rlogind [-aln]"); 69840917Skarels #endif 69940917Skarels } 70040917Skarels 70140917Skarels /* 70236631Skarels * Check whether host h is in our local domain, 70339058Skarels * defined as sharing the last two components of the domain part, 70439058Skarels * or the entire domain part if the local domain has only one component. 70536631Skarels * If either name is unqualified (contains no '.'), 70636631Skarels * assume that the host is local, as it will be 70736631Skarels * interpreted as such. 70836631Skarels */ 709*54547Sleres int 71036631Skarels local_domain(h) 71136631Skarels char *h; 71236625Skfall { 71336631Skarels char localhost[MAXHOSTNAMELEN]; 714*54547Sleres char *p1, *p2; 71536631Skarels 71639058Skarels localhost[0] = 0; 71736631Skarels (void) gethostname(localhost, sizeof(localhost)); 71839058Skarels p1 = topdomain(localhost); 71939058Skarels p2 = topdomain(h); 72036631Skarels if (p1 == NULL || p2 == NULL || !strcasecmp(p1, p2)) 721*54547Sleres return (1); 722*54547Sleres return (0); 72336625Skfall } 72439058Skarels 72539058Skarels char * 72639058Skarels topdomain(h) 72739058Skarels char *h; 72839058Skarels { 72939058Skarels register char *p; 73039058Skarels char *maybe = NULL; 73139058Skarels int dots = 0; 73239058Skarels 73339058Skarels for (p = h + strlen(h); p >= h; p--) { 73439058Skarels if (*p == '.') { 73539058Skarels if (++dots == 2) 73639058Skarels return (p); 73739058Skarels maybe = p; 73839058Skarels } 73939058Skarels } 74039058Skarels return (maybe); 74139058Skarels } 742