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*54554Sbostic static char sccsid[] = "@(#)rlogind.c 5.55 (Berkeley) 06/29/92"; 1635441Sbostic #endif /* not lint */ 1721174Sdist 1816369Skarels /* 1916369Skarels * remote login server: 2036453Skfall * \0 2116369Skarels * remuser\0 2216369Skarels * locuser\0 2336453Skfall * terminal_type/speed\0 2436518Skarels * data 2516369Skarels */ 2616369Skarels 2740917Skarels #define FD_SETSIZE 16 /* don't need many bits for select */ 2837290Sbostic #include <sys/param.h> 296446Swnj #include <sys/stat.h> 3037290Sbostic #include <sys/ioctl.h> 3146982Sbostic #include <signal.h> 3246982Sbostic #include <termios.h> 339208Ssam 3446982Sbostic #include <sys/socket.h> 359208Ssam #include <netinet/in.h> 3644347Skarels #include <netinet/in_systm.h> 3744347Skarels #include <netinet/ip.h> 3846982Sbostic #include <arpa/inet.h> 3946982Sbostic #include <netdb.h> 409208Ssam 416446Swnj #include <pwd.h> 4217187Sralph #include <syslog.h> 4346982Sbostic #include <errno.h> 4440917Skarels #include <stdio.h> 4540917Skarels #include <unistd.h> 4646982Sbostic #include <stdlib.h> 4746982Sbostic #include <string.h> 4840917Skarels #include "pathnames.h" 496446Swnj 5036518Skarels #ifndef TIOCPKT_WINDOW 5136518Skarels #define TIOCPKT_WINDOW 0x80 5236518Skarels #endif 5336518Skarels 5440917Skarels #ifdef KERBEROS 5541761Skfall #include <kerberosIV/des.h> 5640917Skarels #include <kerberosIV/krb.h> 5740917Skarels #define SECURE_MESSAGE "This rlogin session is using DES encryption for all transmissions.\r\n" 5840917Skarels 5940917Skarels AUTH_DAT *kdata; 6040917Skarels KTEXT ticket; 6140917Skarels u_char auth_buf[sizeof(AUTH_DAT)]; 6240917Skarels u_char tick_buf[sizeof(KTEXT_ST)]; 6340917Skarels Key_schedule schedule; 6446982Sbostic int doencrypt, retval, use_kerberos, vacuous; 6540917Skarels 6640917Skarels #define ARGSTR "alnkvx" 6740917Skarels #else 6840917Skarels #define ARGSTR "aln" 6940917Skarels #endif /* KERBEROS */ 7040917Skarels 7136518Skarels char *env[2]; 7236518Skarels #define NMAX 30 7336517Skarels char lusername[NMAX+1], rusername[NMAX+1]; 7436517Skarels static char term[64] = "TERM="; 7536517Skarels #define ENVSIZE (sizeof("TERM=")-1) /* skip null for concatenation */ 7636517Skarels int keepalive = 1; 7739058Skarels int check_all = 0; 7836453Skfall 7946982Sbostic struct passwd *pwd; 8016369Skarels 8154547Sleres void doit __P((int, struct sockaddr_in *)); 8254547Sleres int control __P((int, char *, int)); 8354547Sleres void protocol __P((int, int)); 84*54554Sbostic void cleanup __P((int)); 8554547Sleres void fatal __P((int, char *, int)); 8654547Sleres int do_rlogin __P((struct sockaddr_in *)); 8754547Sleres void getstr __P((char *, int, char *)); 8854547Sleres void setup_term __P((int)); 8954547Sleres int do_krb_login __P((struct sockaddr_in *)); 9054547Sleres void usage __P((void)); 9154547Sleres int local_domain __P((char *)); 9254547Sleres char *topdomain __P((char *)); 9354547Sleres 9454547Sleres int 956446Swnj main(argc, argv) 966446Swnj int argc; 9754547Sleres char *argv[]; 986446Swnj { 9954547Sleres extern int __check_rhosts_file; 1006446Swnj struct sockaddr_in from; 10154547Sleres int ch, fromlen, on; 1026446Swnj 10336625Skfall openlog("rlogind", LOG_PID | LOG_CONS, LOG_AUTH); 10436319Sbostic 10536319Sbostic opterr = 0; 10640917Skarels while ((ch = getopt(argc, argv, ARGSTR)) != EOF) 10736517Skarels switch (ch) { 10839058Skarels case 'a': 10939058Skarels check_all = 1; 11039058Skarels break; 11136319Sbostic case 'l': 11254547Sleres __check_rhosts_file = 0; 11336319Sbostic break; 11436517Skarels case 'n': 11536517Skarels keepalive = 0; 11636517Skarels break; 11740917Skarels #ifdef KERBEROS 11840917Skarels case 'k': 11940917Skarels use_kerberos = 1; 12040917Skarels break; 12140917Skarels case 'v': 12240917Skarels vacuous = 1; 12340917Skarels break; 12454547Sleres #ifdef CRYPT 12554547Sleres case 'x': 12654547Sleres doencrypt = 1; 12754547Sleres break; 12840917Skarels #endif 12954547Sleres #endif 13036319Sbostic case '?': 13136319Sbostic default: 13240917Skarels usage(); 13336319Sbostic break; 13436319Sbostic } 13536319Sbostic argc -= optind; 13636319Sbostic argv += optind; 13736319Sbostic 13840917Skarels #ifdef KERBEROS 13940917Skarels if (use_kerberos && vacuous) { 14040917Skarels usage(); 14140917Skarels fatal(STDERR_FILENO, "only one of -k and -v allowed", 0); 14240917Skarels } 14340917Skarels #endif 14416369Skarels fromlen = sizeof (from); 14546982Sbostic if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { 14640917Skarels syslog(LOG_ERR,"Can't get peer name of remote host: %m"); 14740917Skarels fatal(STDERR_FILENO, "Can't get peer name of remote host", 1); 1488380Ssam } 14954547Sleres on = 1; 15036517Skarels if (keepalive && 15136517Skarels setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) 15217187Sralph syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); 15344347Skarels on = IPTOS_LOWDELAY; 15444347Skarels if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) 15544347Skarels syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); 15616369Skarels doit(0, &from); 1576446Swnj } 1586446Swnj 1596446Swnj int child; 1606446Swnj int netf; 16144349Smarc char line[MAXPATHLEN]; 16240917Skarels int confirmed; 1636446Swnj 16424889Smckusick struct winsize win = { 0, 0, 0, 0 }; 16524723Smckusick 16624889Smckusick 16754547Sleres void 1686446Swnj doit(f, fromp) 1696446Swnj int f; 1706446Swnj struct sockaddr_in *fromp; 1716446Swnj { 17254547Sleres int master, pid, on = 1; 17354547Sleres int authenticated = 0; 17440917Skarels register struct hostent *hp; 17554547Sleres register char *hostname; 17639249Smarc char remotehost[2 * MAXHOSTNAMELEN + 1]; 1778380Ssam char c; 1786446Swnj 1796446Swnj alarm(60); 1806446Swnj read(f, &c, 1); 18140917Skarels 18239249Smarc if (c != 0) 18336715Skfall exit(1); 18440917Skarels #ifdef KERBEROS 18540917Skarels if (vacuous) 18640917Skarels fatal(f, "Remote host requires Kerberos authentication", 0); 18740917Skarels #endif 18836453Skfall 1896446Swnj alarm(0); 19016227Skarels fromp->sin_port = ntohs((u_short)fromp->sin_port); 19146982Sbostic hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof(struct in_addr), 19254547Sleres fromp->sin_family); 19354547Sleres if (hp) 19454547Sleres hostname = hp->h_name; 19554547Sleres else 19654547Sleres hostname = strcpy(remotehost, inet_ntoa(fromp->sin_addr)); 19736711Skfall 19840917Skarels #ifdef KERBEROS 19940917Skarels if (use_kerberos) { 20054547Sleres retval = do_krb_login(fromp); 20142264Sbostic if (retval == 0) 20240917Skarels authenticated++; 20340917Skarels else if (retval > 0) 20440917Skarels fatal(f, krb_err_txt[retval], 0); 20540917Skarels write(f, &c, 1); 20640917Skarels confirmed = 1; /* we sent the null! */ 20740917Skarels } else 20840917Skarels #endif 20940917Skarels { 21054547Sleres if (fromp->sin_family != AF_INET || 21154547Sleres fromp->sin_port >= IPPORT_RESERVED || 21254547Sleres fromp->sin_port < IPPORT_RESERVED/2) { 21354547Sleres syslog(LOG_NOTICE, "Connection from %s on illegal port", 21454547Sleres inet_ntoa(fromp->sin_addr)); 21554547Sleres fatal(f, "Permission denied", 0); 21654547Sleres } 21736702Skarels #ifdef IP_OPTIONS 21854547Sleres { 21954547Sleres u_char optbuf[BUFSIZ/3], *cp; 22054547Sleres char lbuf[BUFSIZ], *lp; 22154547Sleres int optsize = sizeof(optbuf), ipproto; 22254547Sleres struct protoent *ip; 22336702Skarels 22454547Sleres if ((ip = getprotobyname("ip")) != NULL) 22554547Sleres ipproto = ip->p_proto; 22654547Sleres else 22754547Sleres ipproto = IPPROTO_IP; 22854547Sleres if (getsockopt(0, ipproto, IP_OPTIONS, (char *)optbuf, 22954547Sleres &optsize) == 0 && optsize != 0) { 23054547Sleres lp = lbuf; 23154547Sleres for (cp = optbuf; optsize > 0; cp++, optsize--, lp += 3) 23254547Sleres sprintf(lp, " %2.2x", *cp); 23354547Sleres syslog(LOG_NOTICE, 23454547Sleres "Connection received using IP options (ignored):%s", 23554547Sleres lbuf); 23654547Sleres if (setsockopt(0, ipproto, IP_OPTIONS, 23754547Sleres (char *)NULL, optsize) != 0) { 23854547Sleres syslog(LOG_ERR, 23954547Sleres "setsockopt IP_OPTIONS NULL: %m"); 24054547Sleres exit(1); 24154547Sleres } 24254547Sleres } 24354547Sleres } 24436702Skarels #endif 24554547Sleres if (do_rlogin(fromp) == 0) 24654547Sleres authenticated++; 24736631Skarels } 24840917Skarels if (confirmed == 0) { 24940917Skarels write(f, "", 1); 25040917Skarels confirmed = 1; /* we sent the null! */ 25139249Smarc } 25240917Skarels #ifdef KERBEROS 25354547Sleres #ifdef CRYPT 25454547Sleres if (doencrypt) 25554547Sleres (void) des_write(f, SECURE_MESSAGE, sizeof(SECURE_MESSAGE)); 25639249Smarc #endif 25754547Sleres #endif 25844349Smarc netf = f; 25944349Smarc 26044349Smarc pid = forkpty(&master, line, NULL, &win); 26144349Smarc if (pid < 0) { 26244349Smarc if (errno == ENOENT) 26344349Smarc fatal(f, "Out of ptys", 0); 26444349Smarc else 26544349Smarc fatal(f, "Forkpty", 1); 26644349Smarc } 26718357Ssam if (pid == 0) { 26854547Sleres if (f > 2) /* f should always be 0, but... */ 26944349Smarc (void) close(f); 27044349Smarc setup_term(0); 27143363Skfall if (authenticated) { 27244347Skarels #ifdef KERBEROS 27343363Skfall if (use_kerberos && (pwd->pw_uid == 0)) 27443363Skfall syslog(LOG_INFO|LOG_AUTH, 27543363Skfall "ROOT Kerberos login from %s.%s@%s on %s\n", 27643363Skfall kdata->pname, kdata->pinst, kdata->prealm, 27754547Sleres hostname); 27844347Skarels #endif 27943363Skfall 28040917Skarels execl(_PATH_LOGIN, "login", "-p", 28154547Sleres "-h", hostname, "-f", lusername, (char *)NULL); 28243363Skfall } else 28340917Skarels execl(_PATH_LOGIN, "login", "-p", 28454547Sleres "-h", hostname, lusername, (char *)NULL); 28540917Skarels fatal(STDERR_FILENO, _PATH_LOGIN, 1); 28618357Ssam /*NOTREACHED*/ 28718357Ssam } 28854547Sleres #ifdef CRYPT 28954547Sleres #ifdef KERBEROS 29054547Sleres /* 29154547Sleres * If encrypted, don't turn on NBIO or the des read/write 29254547Sleres * routines will croak. 29354547Sleres */ 29454547Sleres 29554547Sleres if (!doencrypt) 29654547Sleres #endif 29754547Sleres #endif 29840917Skarels ioctl(f, FIONBIO, &on); 29944349Smarc ioctl(master, FIONBIO, &on); 30044349Smarc ioctl(master, TIOCPKT, &on); 30118357Ssam signal(SIGCHLD, cleanup); 30244349Smarc protocol(f, master); 30330600Smckusick signal(SIGCHLD, SIG_IGN); 304*54554Sbostic cleanup(0); 30518357Ssam } 3069242Ssam 30718357Ssam char magic[2] = { 0377, 0377 }; 30825423Skarels char oobdata[] = {TIOCPKT_WINDOW}; 30918357Ssam 31018357Ssam /* 31118357Ssam * Handle a "control" request (signaled by magic being present) 31218357Ssam * in the data stream. For now, we are only willing to handle 31318357Ssam * window size changes. 31418357Ssam */ 31554547Sleres int 31618357Ssam control(pty, cp, n) 31718357Ssam int pty; 31818357Ssam char *cp; 31918357Ssam int n; 32018357Ssam { 32128705Smckusick struct winsize w; 32218357Ssam 32328705Smckusick if (n < 4+sizeof (w) || cp[2] != 's' || cp[3] != 's') 32418357Ssam return (0); 32525423Skarels oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */ 32628705Smckusick bcopy(cp+4, (char *)&w, sizeof(w)); 32728705Smckusick w.ws_row = ntohs(w.ws_row); 32828705Smckusick w.ws_col = ntohs(w.ws_col); 32928705Smckusick w.ws_xpixel = ntohs(w.ws_xpixel); 33028705Smckusick w.ws_ypixel = ntohs(w.ws_ypixel); 33128705Smckusick (void)ioctl(pty, TIOCSWINSZ, &w); 33228705Smckusick return (4+sizeof (w)); 33318357Ssam } 33418357Ssam 33518357Ssam /* 33618357Ssam * rlogin "protocol" machine. 33718357Ssam */ 33854547Sleres void 33918357Ssam protocol(f, p) 34040917Skarels register int f, p; 34118357Ssam { 34240917Skarels char pibuf[1024+1], fibuf[1024], *pbp, *fbp; 34318357Ssam register pcc = 0, fcc = 0; 34440917Skarels int cc, nfd, n; 34525740Skarels char cntl; 34618357Ssam 34718482Ssam /* 34818484Ssam * Must ignore SIGTTOU, otherwise we'll stop 34918484Ssam * when we try and set slave pty's window shape 35025423Skarels * (our controlling tty is the master pty). 35118482Ssam */ 35218484Ssam (void) signal(SIGTTOU, SIG_IGN); 35325423Skarels send(f, oobdata, 1, MSG_OOB); /* indicate new rlogin */ 35436517Skarels if (f > p) 35536517Skarels nfd = f + 1; 35636517Skarels else 35736517Skarels nfd = p + 1; 35840917Skarels if (nfd > FD_SETSIZE) { 35940917Skarels syslog(LOG_ERR, "select mask too small, increase FD_SETSIZE"); 36040917Skarels fatal(f, "internal error (select mask too small)", 0); 36140917Skarels } 36218357Ssam for (;;) { 36340917Skarels fd_set ibits, obits, ebits, *omask; 36418357Ssam 36542956Sbostic FD_ZERO(&ebits); 36640917Skarels FD_ZERO(&ibits); 36740917Skarels FD_ZERO(&obits); 36840917Skarels omask = (fd_set *)NULL; 36940917Skarels if (fcc) { 37040917Skarels FD_SET(p, &obits); 37140917Skarels omask = &obits; 37240917Skarels } else 37340917Skarels FD_SET(f, &ibits); 37418357Ssam if (pcc >= 0) 37540917Skarels if (pcc) { 37640917Skarels FD_SET(f, &obits); 37740917Skarels omask = &obits; 37840917Skarels } else 37940917Skarels FD_SET(p, &ibits); 38040917Skarels FD_SET(p, &ebits); 38140917Skarels if ((n = select(nfd, &ibits, omask, &ebits, 0)) < 0) { 38218357Ssam if (errno == EINTR) 3836446Swnj continue; 38440917Skarels fatal(f, "select", 1); 38518357Ssam } 38640917Skarels if (n == 0) { 38718357Ssam /* shouldn't happen... */ 38818357Ssam sleep(5); 38918357Ssam continue; 39018357Ssam } 39125740Skarels #define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP)) 39240917Skarels if (FD_ISSET(p, &ebits)) { 39325740Skarels cc = read(p, &cntl, 1); 39425740Skarels if (cc == 1 && pkcontrol(cntl)) { 39525740Skarels cntl |= oobdata[0]; 39625740Skarels send(f, &cntl, 1, MSG_OOB); 39725740Skarels if (cntl & TIOCPKT_FLUSHWRITE) { 39825740Skarels pcc = 0; 39940917Skarels FD_CLR(p, &ibits); 40025740Skarels } 40125740Skarels } 40225740Skarels } 40340917Skarels if (FD_ISSET(f, &ibits)) { 40454547Sleres #ifdef CRYPT 40554547Sleres #ifdef KERBEROS 40654547Sleres if (doencrypt) 40754547Sleres fcc = des_read(f, fibuf, sizeof(fibuf)); 40854547Sleres else 40954547Sleres #endif 41054547Sleres #endif 41140917Skarels fcc = read(f, fibuf, sizeof(fibuf)); 41218357Ssam if (fcc < 0 && errno == EWOULDBLOCK) 41318357Ssam fcc = 0; 41418357Ssam else { 41518357Ssam register char *cp; 41618357Ssam int left, n; 41718357Ssam 41818357Ssam if (fcc <= 0) 41916227Skarels break; 42018357Ssam fbp = fibuf; 42124723Smckusick 42218357Ssam top: 42325423Skarels for (cp = fibuf; cp < fibuf+fcc-1; cp++) 42418357Ssam if (cp[0] == magic[0] && 42518357Ssam cp[1] == magic[1]) { 42618357Ssam left = fcc - (cp-fibuf); 42718357Ssam n = control(p, cp, left); 42818357Ssam if (n) { 42918357Ssam left -= n; 43018357Ssam if (left > 0) 43125423Skarels bcopy(cp+n, cp, left); 43218357Ssam fcc -= n; 43318357Ssam goto top; /* n^2 */ 43425423Skarels } 43525423Skarels } 43640917Skarels FD_SET(p, &obits); /* try write */ 43725423Skarels } 43825423Skarels } 43924723Smckusick 44040917Skarels if (FD_ISSET(p, &obits) && fcc > 0) { 44125423Skarels cc = write(p, fbp, fcc); 44224723Smckusick if (cc > 0) { 44324723Smckusick fcc -= cc; 44424723Smckusick fbp += cc; 4456446Swnj } 44618357Ssam } 44724723Smckusick 44840917Skarels if (FD_ISSET(p, &ibits)) { 44918357Ssam pcc = read(p, pibuf, sizeof (pibuf)); 45018357Ssam pbp = pibuf; 45118357Ssam if (pcc < 0 && errno == EWOULDBLOCK) 45218357Ssam pcc = 0; 45318357Ssam else if (pcc <= 0) 45418357Ssam break; 45536517Skarels else if (pibuf[0] == 0) { 45618357Ssam pbp++, pcc--; 45754547Sleres #ifdef CRYPT 45854547Sleres #ifdef KERBEROS 45954547Sleres if (!doencrypt) 46054547Sleres #endif 46154547Sleres #endif 46240917Skarels FD_SET(f, &obits); /* try write */ 46336517Skarels } else { 46418357Ssam if (pkcontrol(pibuf[0])) { 46525423Skarels pibuf[0] |= oobdata[0]; 46618357Ssam send(f, &pibuf[0], 1, MSG_OOB); 46716227Skarels } 46818357Ssam pcc = 0; 4696446Swnj } 47018357Ssam } 47140917Skarels if ((FD_ISSET(f, &obits)) && pcc > 0) { 47254547Sleres #ifdef CRYPT 47354547Sleres #ifdef KERBEROS 47454547Sleres if (doencrypt) 47554547Sleres cc = des_write(f, pbp, pcc); 47654547Sleres else 47754547Sleres #endif 47854547Sleres #endif 47940917Skarels cc = write(f, pbp, pcc); 48025423Skarels if (cc < 0 && errno == EWOULDBLOCK) { 48140917Skarels /* 48240917Skarels * This happens when we try write after read 48340917Skarels * from p, but some old kernels balk at large 48440917Skarels * writes even when select returns true. 48540917Skarels */ 48640917Skarels if (!FD_ISSET(p, &ibits)) 48740917Skarels sleep(5); 48825423Skarels continue; 48925423Skarels } 49018357Ssam if (cc > 0) { 49118357Ssam pcc -= cc; 49218357Ssam pbp += cc; 49318357Ssam } 4946446Swnj } 4956446Swnj } 4966446Swnj } 4976446Swnj 49846982Sbostic void 499*54554Sbostic cleanup(signo) 500*54554Sbostic int signo; 5016446Swnj { 50235440Sbostic char *p; 50335440Sbostic 50440917Skarels p = line + sizeof(_PATH_DEV) - 1; 50535440Sbostic if (logout(p)) 50635440Sbostic logwtmp(p, "", ""); 50748380Skarels (void)chmod(line, 0666); 50835440Sbostic (void)chown(line, 0, 0); 50935440Sbostic *p = 'p'; 51048380Skarels (void)chmod(line, 0666); 51135440Sbostic (void)chown(line, 0, 0); 51210192Ssam shutdown(netf, 2); 5136446Swnj exit(1); 5146446Swnj } 5156446Swnj 51654547Sleres void 51740917Skarels fatal(f, msg, syserr) 51854547Sleres int f; 5199242Ssam char *msg; 52054547Sleres int syserr; 5219242Ssam { 52240917Skarels int len; 52340917Skarels char buf[BUFSIZ], *bp = buf; 5249242Ssam 52540917Skarels /* 52640917Skarels * Prepend binary one to message if we haven't sent 52740917Skarels * the magic null as confirmation. 52840917Skarels */ 52940917Skarels if (!confirmed) 53040917Skarels *bp++ = '\01'; /* error indicator */ 53140917Skarels if (syserr) 53240917Skarels len = sprintf(bp, "rlogind: %s: %s.\r\n", 53340917Skarels msg, strerror(errno)); 53440917Skarels else 53540917Skarels len = sprintf(bp, "rlogind: %s.\r\n", msg); 53640917Skarels (void) write(f, buf, bp + len - buf); 5379242Ssam exit(1); 5389242Ssam } 5399242Ssam 54054547Sleres int 54154547Sleres do_rlogin(dest) 54254547Sleres struct sockaddr_in *dest; 54336453Skfall { 54436518Skarels getstr(rusername, sizeof(rusername), "remuser too long"); 54536518Skarels getstr(lusername, sizeof(lusername), "locuser too long"); 54636518Skarels getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type too long"); 54736518Skarels 54836453Skfall pwd = getpwnam(lusername); 54936518Skarels if (pwd == NULL) 55054547Sleres return (-1); 55142264Sbostic if (pwd->pw_uid == 0) 55254547Sleres return (-1); 55354547Sleres /* XXX why don't we syslog() failure? */ 55454547Sleres return (iruserok(dest->sin_addr.s_addr, 0, rusername, lusername)); 55536453Skfall } 55636453Skfall 55754547Sleres void 55836518Skarels getstr(buf, cnt, errmsg) 55936518Skarels char *buf; 56036518Skarels int cnt; 56136518Skarels char *errmsg; 56236453Skfall { 56336518Skarels char c; 56436518Skarels 56536453Skfall do { 56636518Skarels if (read(0, &c, 1) != 1) 56736453Skfall exit(1); 56836518Skarels if (--cnt < 0) 56940917Skarels fatal(STDOUT_FILENO, errmsg, 0); 57036453Skfall *buf++ = c; 57136518Skarels } while (c != 0); 57236453Skfall } 57336453Skfall 57436518Skarels extern char **environ; 57536453Skfall 57654547Sleres void 57736519Skarels setup_term(fd) 57836519Skarels int fd; 57936519Skarels { 58040917Skarels register char *cp = index(term+ENVSIZE, '/'); 58136519Skarels char *speed; 58239118Skarels struct termios tt; 58336519Skarels 58440917Skarels #ifndef notyet 58536711Skfall tcgetattr(fd, &tt); 58636519Skarels if (cp) { 58736519Skarels *cp++ = '\0'; 58836519Skarels speed = cp; 58936519Skarels cp = index(speed, '/'); 59036519Skarels if (cp) 59136519Skarels *cp++ = '\0'; 59236711Skfall cfsetspeed(&tt, atoi(speed)); 59336519Skarels } 59438710Skfall 59539118Skarels tt.c_iflag = TTYDEF_IFLAG; 59639118Skarels tt.c_oflag = TTYDEF_OFLAG; 59739118Skarels tt.c_lflag = TTYDEF_LFLAG; 59843272Sbostic tcsetattr(fd, TCSAFLUSH, &tt); 59939118Skarels #else 60039118Skarels if (cp) { 60139118Skarels *cp++ = '\0'; 60239118Skarels speed = cp; 60339118Skarels cp = index(speed, '/'); 60439118Skarels if (cp) 60539118Skarels *cp++ = '\0'; 60640917Skarels tcgetattr(fd, &tt); 60740917Skarels cfsetspeed(&tt, atoi(speed)); 60843272Sbostic tcsetattr(fd, TCSAFLUSH, &tt); 60938710Skfall } 61038710Skfall #endif 61136519Skarels 61236519Skarels env[0] = term; 61336519Skarels env[1] = 0; 61436519Skarels environ = env; 61536519Skarels } 61636609Skfall 61740917Skarels #ifdef KERBEROS 61840917Skarels #define VERSION_SIZE 9 61940917Skarels 62036609Skfall /* 62140917Skarels * Do the remote kerberos login to the named host with the 62240917Skarels * given inet address 62340917Skarels * 62440917Skarels * Return 0 on valid authorization 62540917Skarels * Return -1 on valid authentication, no authorization 62640917Skarels * Return >0 for error conditions 62740917Skarels */ 62854547Sleres int 62954547Sleres do_krb_login(dest) 63040917Skarels struct sockaddr_in *dest; 63140917Skarels { 63240917Skarels int rc; 63340917Skarels char instance[INST_SZ], version[VERSION_SIZE]; 63440917Skarels long authopts = 0L; /* !mutual */ 63540917Skarels struct sockaddr_in faddr; 63640917Skarels 63740917Skarels kdata = (AUTH_DAT *) auth_buf; 63840917Skarels ticket = (KTEXT) tick_buf; 63940917Skarels 64042264Sbostic instance[0] = '*'; 64142264Sbostic instance[1] = '\0'; 64242264Sbostic 64354547Sleres #ifdef CRYPT 64454547Sleres if (doencrypt) { 64554547Sleres rc = sizeof(faddr); 64654547Sleres if (getsockname(0, (struct sockaddr *)&faddr, &rc)) 64754547Sleres return (-1); 64854547Sleres authopts = KOPT_DO_MUTUAL; 64940917Skarels rc = krb_recvauth( 65040917Skarels authopts, 0, 65140917Skarels ticket, "rcmd", 65254547Sleres instance, dest, &faddr, 65354547Sleres kdata, "", schedule, version); 65454547Sleres des_set_key(kdata->session, schedule); 65554547Sleres 65654547Sleres } else 65754547Sleres #endif 65854547Sleres rc = krb_recvauth( 65954547Sleres authopts, 0, 66054547Sleres ticket, "rcmd", 66140917Skarels instance, dest, (struct sockaddr_in *) 0, 66240917Skarels kdata, "", (bit_64 *) 0, version); 66340917Skarels 66440917Skarels if (rc != KSUCCESS) 66554547Sleres return (rc); 66640917Skarels 66740917Skarels getstr(lusername, sizeof(lusername), "locuser"); 66840917Skarels /* get the "cmd" in the rcmd protocol */ 66940917Skarels getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type"); 67040917Skarels 67140917Skarels pwd = getpwnam(lusername); 67240917Skarels if (pwd == NULL) 67354547Sleres return (-1); 67440917Skarels 67540917Skarels /* returns nonzero for no access */ 67654547Sleres if (kuserok(kdata, lusername) != 0) 67754547Sleres return (-1); 67840917Skarels 67954547Sleres return (0); 68040917Skarels 68140917Skarels } 68240917Skarels #endif /* KERBEROS */ 68340917Skarels 68454547Sleres void 68540917Skarels usage() 68640917Skarels { 68740917Skarels #ifdef KERBEROS 68840917Skarels syslog(LOG_ERR, "usage: rlogind [-aln] [-k | -v]"); 68940917Skarels #else 69040917Skarels syslog(LOG_ERR, "usage: rlogind [-aln]"); 69140917Skarels #endif 69240917Skarels } 69340917Skarels 69440917Skarels /* 69536631Skarels * Check whether host h is in our local domain, 69639058Skarels * defined as sharing the last two components of the domain part, 69739058Skarels * or the entire domain part if the local domain has only one component. 69836631Skarels * If either name is unqualified (contains no '.'), 69936631Skarels * assume that the host is local, as it will be 70036631Skarels * interpreted as such. 70136631Skarels */ 70254547Sleres int 70336631Skarels local_domain(h) 70436631Skarels char *h; 70536625Skfall { 70636631Skarels char localhost[MAXHOSTNAMELEN]; 70754547Sleres char *p1, *p2; 70836631Skarels 70939058Skarels localhost[0] = 0; 71036631Skarels (void) gethostname(localhost, sizeof(localhost)); 71139058Skarels p1 = topdomain(localhost); 71239058Skarels p2 = topdomain(h); 71336631Skarels if (p1 == NULL || p2 == NULL || !strcasecmp(p1, p2)) 71454547Sleres return (1); 71554547Sleres return (0); 71636625Skfall } 71739058Skarels 71839058Skarels char * 71939058Skarels topdomain(h) 72039058Skarels char *h; 72139058Skarels { 72239058Skarels register char *p; 72339058Skarels char *maybe = NULL; 72439058Skarels int dots = 0; 72539058Skarels 72639058Skarels for (p = h + strlen(h); p >= h; p--) { 72739058Skarels if (*p == '.') { 72839058Skarels if (++dots == 2) 72939058Skarels return (p); 73039058Skarels maybe = p; 73139058Skarels } 73239058Skarels } 73339058Skarels return (maybe); 73439058Skarels } 735