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*54589Sbostic static char sccsid[] = "@(#)rlogind.c 5.56 (Berkeley) 07/01/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)); 8454554Sbostic 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; 175*54589Sbostic char hostname[2 * MAXHOSTNAMELEN + 1]; 1768380Ssam char c; 1776446Swnj 1786446Swnj alarm(60); 1796446Swnj read(f, &c, 1); 18040917Skarels 18139249Smarc if (c != 0) 18236715Skfall exit(1); 18340917Skarels #ifdef KERBEROS 18440917Skarels if (vacuous) 18540917Skarels fatal(f, "Remote host requires Kerberos authentication", 0); 18640917Skarels #endif 18736453Skfall 1886446Swnj alarm(0); 18916227Skarels fromp->sin_port = ntohs((u_short)fromp->sin_port); 19046982Sbostic hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof(struct in_addr), 19154547Sleres fromp->sin_family); 19254547Sleres if (hp) 193*54589Sbostic (void)strcpy(hostname, hp->h_name); 19454547Sleres else 195*54589Sbostic (void)strcpy(hostname, inet_ntoa(fromp->sin_addr)); 19636711Skfall 19740917Skarels #ifdef KERBEROS 19840917Skarels if (use_kerberos) { 19954547Sleres retval = do_krb_login(fromp); 20042264Sbostic if (retval == 0) 20140917Skarels authenticated++; 20240917Skarels else if (retval > 0) 20340917Skarels fatal(f, krb_err_txt[retval], 0); 20440917Skarels write(f, &c, 1); 20540917Skarels confirmed = 1; /* we sent the null! */ 20640917Skarels } else 20740917Skarels #endif 20840917Skarels { 20954547Sleres if (fromp->sin_family != AF_INET || 21054547Sleres fromp->sin_port >= IPPORT_RESERVED || 21154547Sleres fromp->sin_port < IPPORT_RESERVED/2) { 21254547Sleres syslog(LOG_NOTICE, "Connection from %s on illegal port", 21354547Sleres inet_ntoa(fromp->sin_addr)); 21454547Sleres fatal(f, "Permission denied", 0); 21554547Sleres } 21636702Skarels #ifdef IP_OPTIONS 21754547Sleres { 21854547Sleres u_char optbuf[BUFSIZ/3], *cp; 21954547Sleres char lbuf[BUFSIZ], *lp; 22054547Sleres int optsize = sizeof(optbuf), ipproto; 22154547Sleres struct protoent *ip; 22236702Skarels 22354547Sleres if ((ip = getprotobyname("ip")) != NULL) 22454547Sleres ipproto = ip->p_proto; 22554547Sleres else 22654547Sleres ipproto = IPPROTO_IP; 22754547Sleres if (getsockopt(0, ipproto, IP_OPTIONS, (char *)optbuf, 22854547Sleres &optsize) == 0 && optsize != 0) { 22954547Sleres lp = lbuf; 23054547Sleres for (cp = optbuf; optsize > 0; cp++, optsize--, lp += 3) 23154547Sleres sprintf(lp, " %2.2x", *cp); 23254547Sleres syslog(LOG_NOTICE, 23354547Sleres "Connection received using IP options (ignored):%s", 23454547Sleres lbuf); 23554547Sleres if (setsockopt(0, ipproto, IP_OPTIONS, 23654547Sleres (char *)NULL, optsize) != 0) { 23754547Sleres syslog(LOG_ERR, 23854547Sleres "setsockopt IP_OPTIONS NULL: %m"); 23954547Sleres exit(1); 24054547Sleres } 24154547Sleres } 24254547Sleres } 24336702Skarels #endif 24454547Sleres if (do_rlogin(fromp) == 0) 24554547Sleres authenticated++; 24636631Skarels } 24740917Skarels if (confirmed == 0) { 24840917Skarels write(f, "", 1); 24940917Skarels confirmed = 1; /* we sent the null! */ 25039249Smarc } 25140917Skarels #ifdef KERBEROS 25254547Sleres #ifdef CRYPT 25354547Sleres if (doencrypt) 25454547Sleres (void) des_write(f, SECURE_MESSAGE, sizeof(SECURE_MESSAGE)); 25539249Smarc #endif 25654547Sleres #endif 25744349Smarc netf = f; 25844349Smarc 25944349Smarc pid = forkpty(&master, line, NULL, &win); 26044349Smarc if (pid < 0) { 26144349Smarc if (errno == ENOENT) 26244349Smarc fatal(f, "Out of ptys", 0); 26344349Smarc else 26444349Smarc fatal(f, "Forkpty", 1); 26544349Smarc } 26618357Ssam if (pid == 0) { 26754547Sleres if (f > 2) /* f should always be 0, but... */ 26844349Smarc (void) close(f); 26944349Smarc setup_term(0); 27043363Skfall if (authenticated) { 27144347Skarels #ifdef KERBEROS 27243363Skfall if (use_kerberos && (pwd->pw_uid == 0)) 27343363Skfall syslog(LOG_INFO|LOG_AUTH, 27443363Skfall "ROOT Kerberos login from %s.%s@%s on %s\n", 27543363Skfall kdata->pname, kdata->pinst, kdata->prealm, 27654547Sleres hostname); 27744347Skarels #endif 27843363Skfall 27940917Skarels execl(_PATH_LOGIN, "login", "-p", 28054547Sleres "-h", hostname, "-f", lusername, (char *)NULL); 28143363Skfall } else 28240917Skarels execl(_PATH_LOGIN, "login", "-p", 28354547Sleres "-h", hostname, lusername, (char *)NULL); 28440917Skarels fatal(STDERR_FILENO, _PATH_LOGIN, 1); 28518357Ssam /*NOTREACHED*/ 28618357Ssam } 28754547Sleres #ifdef CRYPT 28854547Sleres #ifdef KERBEROS 28954547Sleres /* 29054547Sleres * If encrypted, don't turn on NBIO or the des read/write 29154547Sleres * routines will croak. 29254547Sleres */ 29354547Sleres 29454547Sleres if (!doencrypt) 29554547Sleres #endif 29654547Sleres #endif 29740917Skarels ioctl(f, FIONBIO, &on); 29844349Smarc ioctl(master, FIONBIO, &on); 29944349Smarc ioctl(master, TIOCPKT, &on); 30018357Ssam signal(SIGCHLD, cleanup); 30144349Smarc protocol(f, master); 30230600Smckusick signal(SIGCHLD, SIG_IGN); 30354554Sbostic cleanup(0); 30418357Ssam } 3059242Ssam 30618357Ssam char magic[2] = { 0377, 0377 }; 30725423Skarels char oobdata[] = {TIOCPKT_WINDOW}; 30818357Ssam 30918357Ssam /* 31018357Ssam * Handle a "control" request (signaled by magic being present) 31118357Ssam * in the data stream. For now, we are only willing to handle 31218357Ssam * window size changes. 31318357Ssam */ 31454547Sleres int 31518357Ssam control(pty, cp, n) 31618357Ssam int pty; 31718357Ssam char *cp; 31818357Ssam int n; 31918357Ssam { 32028705Smckusick struct winsize w; 32118357Ssam 32228705Smckusick if (n < 4+sizeof (w) || cp[2] != 's' || cp[3] != 's') 32318357Ssam return (0); 32425423Skarels oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */ 32528705Smckusick bcopy(cp+4, (char *)&w, sizeof(w)); 32628705Smckusick w.ws_row = ntohs(w.ws_row); 32728705Smckusick w.ws_col = ntohs(w.ws_col); 32828705Smckusick w.ws_xpixel = ntohs(w.ws_xpixel); 32928705Smckusick w.ws_ypixel = ntohs(w.ws_ypixel); 33028705Smckusick (void)ioctl(pty, TIOCSWINSZ, &w); 33128705Smckusick return (4+sizeof (w)); 33218357Ssam } 33318357Ssam 33418357Ssam /* 33518357Ssam * rlogin "protocol" machine. 33618357Ssam */ 33754547Sleres void 33818357Ssam protocol(f, p) 33940917Skarels register int f, p; 34018357Ssam { 34140917Skarels char pibuf[1024+1], fibuf[1024], *pbp, *fbp; 34218357Ssam register pcc = 0, fcc = 0; 34340917Skarels int cc, nfd, n; 34425740Skarels char cntl; 34518357Ssam 34618482Ssam /* 34718484Ssam * Must ignore SIGTTOU, otherwise we'll stop 34818484Ssam * when we try and set slave pty's window shape 34925423Skarels * (our controlling tty is the master pty). 35018482Ssam */ 35118484Ssam (void) signal(SIGTTOU, SIG_IGN); 35225423Skarels send(f, oobdata, 1, MSG_OOB); /* indicate new rlogin */ 35336517Skarels if (f > p) 35436517Skarels nfd = f + 1; 35536517Skarels else 35636517Skarels nfd = p + 1; 35740917Skarels if (nfd > FD_SETSIZE) { 35840917Skarels syslog(LOG_ERR, "select mask too small, increase FD_SETSIZE"); 35940917Skarels fatal(f, "internal error (select mask too small)", 0); 36040917Skarels } 36118357Ssam for (;;) { 36240917Skarels fd_set ibits, obits, ebits, *omask; 36318357Ssam 36442956Sbostic FD_ZERO(&ebits); 36540917Skarels FD_ZERO(&ibits); 36640917Skarels FD_ZERO(&obits); 36740917Skarels omask = (fd_set *)NULL; 36840917Skarels if (fcc) { 36940917Skarels FD_SET(p, &obits); 37040917Skarels omask = &obits; 37140917Skarels } else 37240917Skarels FD_SET(f, &ibits); 37318357Ssam if (pcc >= 0) 37440917Skarels if (pcc) { 37540917Skarels FD_SET(f, &obits); 37640917Skarels omask = &obits; 37740917Skarels } else 37840917Skarels FD_SET(p, &ibits); 37940917Skarels FD_SET(p, &ebits); 38040917Skarels if ((n = select(nfd, &ibits, omask, &ebits, 0)) < 0) { 38118357Ssam if (errno == EINTR) 3826446Swnj continue; 38340917Skarels fatal(f, "select", 1); 38418357Ssam } 38540917Skarels if (n == 0) { 38618357Ssam /* shouldn't happen... */ 38718357Ssam sleep(5); 38818357Ssam continue; 38918357Ssam } 39025740Skarels #define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP)) 39140917Skarels if (FD_ISSET(p, &ebits)) { 39225740Skarels cc = read(p, &cntl, 1); 39325740Skarels if (cc == 1 && pkcontrol(cntl)) { 39425740Skarels cntl |= oobdata[0]; 39525740Skarels send(f, &cntl, 1, MSG_OOB); 39625740Skarels if (cntl & TIOCPKT_FLUSHWRITE) { 39725740Skarels pcc = 0; 39840917Skarels FD_CLR(p, &ibits); 39925740Skarels } 40025740Skarels } 40125740Skarels } 40240917Skarels if (FD_ISSET(f, &ibits)) { 40354547Sleres #ifdef CRYPT 40454547Sleres #ifdef KERBEROS 40554547Sleres if (doencrypt) 40654547Sleres fcc = des_read(f, fibuf, sizeof(fibuf)); 40754547Sleres else 40854547Sleres #endif 40954547Sleres #endif 41040917Skarels 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 } 43540917Skarels FD_SET(p, &obits); /* try write */ 43625423Skarels } 43725423Skarels } 43824723Smckusick 43940917Skarels if (FD_ISSET(p, &obits) && fcc > 0) { 44025423Skarels cc = write(p, fbp, fcc); 44124723Smckusick if (cc > 0) { 44224723Smckusick fcc -= cc; 44324723Smckusick fbp += cc; 4446446Swnj } 44518357Ssam } 44624723Smckusick 44740917Skarels if (FD_ISSET(p, &ibits)) { 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--; 45654547Sleres #ifdef CRYPT 45754547Sleres #ifdef KERBEROS 45854547Sleres if (!doencrypt) 45954547Sleres #endif 46054547Sleres #endif 46140917Skarels FD_SET(f, &obits); /* try write */ 46236517Skarels } else { 46318357Ssam if (pkcontrol(pibuf[0])) { 46425423Skarels pibuf[0] |= oobdata[0]; 46518357Ssam send(f, &pibuf[0], 1, MSG_OOB); 46616227Skarels } 46718357Ssam pcc = 0; 4686446Swnj } 46918357Ssam } 47040917Skarels if ((FD_ISSET(f, &obits)) && pcc > 0) { 47154547Sleres #ifdef CRYPT 47254547Sleres #ifdef KERBEROS 47354547Sleres if (doencrypt) 47454547Sleres cc = des_write(f, pbp, pcc); 47554547Sleres else 47654547Sleres #endif 47754547Sleres #endif 47840917Skarels cc = write(f, pbp, pcc); 47925423Skarels if (cc < 0 && errno == EWOULDBLOCK) { 48040917Skarels /* 48140917Skarels * This happens when we try write after read 48240917Skarels * from p, but some old kernels balk at large 48340917Skarels * writes even when select returns true. 48440917Skarels */ 48540917Skarels if (!FD_ISSET(p, &ibits)) 48640917Skarels sleep(5); 48725423Skarels continue; 48825423Skarels } 48918357Ssam if (cc > 0) { 49018357Ssam pcc -= cc; 49118357Ssam pbp += cc; 49218357Ssam } 4936446Swnj } 4946446Swnj } 4956446Swnj } 4966446Swnj 49746982Sbostic void 49854554Sbostic cleanup(signo) 49954554Sbostic int signo; 5006446Swnj { 50135440Sbostic char *p; 50235440Sbostic 50340917Skarels p = line + sizeof(_PATH_DEV) - 1; 50435440Sbostic if (logout(p)) 50535440Sbostic logwtmp(p, "", ""); 50648380Skarels (void)chmod(line, 0666); 50735440Sbostic (void)chown(line, 0, 0); 50835440Sbostic *p = 'p'; 50948380Skarels (void)chmod(line, 0666); 51035440Sbostic (void)chown(line, 0, 0); 51110192Ssam shutdown(netf, 2); 5126446Swnj exit(1); 5136446Swnj } 5146446Swnj 51554547Sleres void 51640917Skarels fatal(f, msg, syserr) 51754547Sleres int f; 5189242Ssam char *msg; 51954547Sleres int syserr; 5209242Ssam { 52140917Skarels int len; 52240917Skarels char buf[BUFSIZ], *bp = buf; 5239242Ssam 52440917Skarels /* 52540917Skarels * Prepend binary one to message if we haven't sent 52640917Skarels * the magic null as confirmation. 52740917Skarels */ 52840917Skarels if (!confirmed) 52940917Skarels *bp++ = '\01'; /* error indicator */ 53040917Skarels if (syserr) 53140917Skarels len = sprintf(bp, "rlogind: %s: %s.\r\n", 53240917Skarels msg, strerror(errno)); 53340917Skarels else 53440917Skarels len = sprintf(bp, "rlogind: %s.\r\n", msg); 53540917Skarels (void) write(f, buf, bp + len - buf); 5369242Ssam exit(1); 5379242Ssam } 5389242Ssam 53954547Sleres int 54054547Sleres do_rlogin(dest) 54154547Sleres struct sockaddr_in *dest; 54236453Skfall { 54336518Skarels getstr(rusername, sizeof(rusername), "remuser too long"); 54436518Skarels getstr(lusername, sizeof(lusername), "locuser too long"); 54536518Skarels getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type too long"); 54636518Skarels 54736453Skfall pwd = getpwnam(lusername); 54836518Skarels if (pwd == NULL) 54954547Sleres return (-1); 55042264Sbostic if (pwd->pw_uid == 0) 55154547Sleres return (-1); 55254547Sleres /* XXX why don't we syslog() failure? */ 55354547Sleres return (iruserok(dest->sin_addr.s_addr, 0, rusername, lusername)); 55436453Skfall } 55536453Skfall 55654547Sleres void 55736518Skarels getstr(buf, cnt, errmsg) 55836518Skarels char *buf; 55936518Skarels int cnt; 56036518Skarels char *errmsg; 56136453Skfall { 56236518Skarels char c; 56336518Skarels 56436453Skfall do { 56536518Skarels if (read(0, &c, 1) != 1) 56636453Skfall exit(1); 56736518Skarels if (--cnt < 0) 56840917Skarels fatal(STDOUT_FILENO, errmsg, 0); 56936453Skfall *buf++ = c; 57036518Skarels } while (c != 0); 57136453Skfall } 57236453Skfall 57336518Skarels extern char **environ; 57436453Skfall 57554547Sleres void 57636519Skarels setup_term(fd) 57736519Skarels int fd; 57836519Skarels { 57940917Skarels register char *cp = index(term+ENVSIZE, '/'); 58036519Skarels char *speed; 58139118Skarels struct termios tt; 58236519Skarels 58340917Skarels #ifndef notyet 58436711Skfall tcgetattr(fd, &tt); 58536519Skarels if (cp) { 58636519Skarels *cp++ = '\0'; 58736519Skarels speed = cp; 58836519Skarels cp = index(speed, '/'); 58936519Skarels if (cp) 59036519Skarels *cp++ = '\0'; 59136711Skfall cfsetspeed(&tt, atoi(speed)); 59236519Skarels } 59338710Skfall 59439118Skarels tt.c_iflag = TTYDEF_IFLAG; 59539118Skarels tt.c_oflag = TTYDEF_OFLAG; 59639118Skarels tt.c_lflag = TTYDEF_LFLAG; 59743272Sbostic tcsetattr(fd, TCSAFLUSH, &tt); 59839118Skarels #else 59939118Skarels if (cp) { 60039118Skarels *cp++ = '\0'; 60139118Skarels speed = cp; 60239118Skarels cp = index(speed, '/'); 60339118Skarels if (cp) 60439118Skarels *cp++ = '\0'; 60540917Skarels tcgetattr(fd, &tt); 60640917Skarels cfsetspeed(&tt, atoi(speed)); 60743272Sbostic tcsetattr(fd, TCSAFLUSH, &tt); 60838710Skfall } 60938710Skfall #endif 61036519Skarels 61136519Skarels env[0] = term; 61236519Skarels env[1] = 0; 61336519Skarels environ = env; 61436519Skarels } 61536609Skfall 61640917Skarels #ifdef KERBEROS 61740917Skarels #define VERSION_SIZE 9 61840917Skarels 61936609Skfall /* 62040917Skarels * Do the remote kerberos login to the named host with the 62140917Skarels * given inet address 62240917Skarels * 62340917Skarels * Return 0 on valid authorization 62440917Skarels * Return -1 on valid authentication, no authorization 62540917Skarels * Return >0 for error conditions 62640917Skarels */ 62754547Sleres int 62854547Sleres do_krb_login(dest) 62940917Skarels struct sockaddr_in *dest; 63040917Skarels { 63140917Skarels int rc; 63240917Skarels char instance[INST_SZ], version[VERSION_SIZE]; 63340917Skarels long authopts = 0L; /* !mutual */ 63440917Skarels struct sockaddr_in faddr; 63540917Skarels 63640917Skarels kdata = (AUTH_DAT *) auth_buf; 63740917Skarels ticket = (KTEXT) tick_buf; 63840917Skarels 63942264Sbostic instance[0] = '*'; 64042264Sbostic instance[1] = '\0'; 64142264Sbostic 64254547Sleres #ifdef CRYPT 64354547Sleres if (doencrypt) { 64454547Sleres rc = sizeof(faddr); 64554547Sleres if (getsockname(0, (struct sockaddr *)&faddr, &rc)) 64654547Sleres return (-1); 64754547Sleres authopts = KOPT_DO_MUTUAL; 64840917Skarels rc = krb_recvauth( 64940917Skarels authopts, 0, 65040917Skarels ticket, "rcmd", 65154547Sleres instance, dest, &faddr, 65254547Sleres kdata, "", schedule, version); 65354547Sleres des_set_key(kdata->session, schedule); 65454547Sleres 65554547Sleres } else 65654547Sleres #endif 65754547Sleres rc = krb_recvauth( 65854547Sleres authopts, 0, 65954547Sleres ticket, "rcmd", 66040917Skarels instance, dest, (struct sockaddr_in *) 0, 66140917Skarels kdata, "", (bit_64 *) 0, version); 66240917Skarels 66340917Skarels if (rc != KSUCCESS) 66454547Sleres return (rc); 66540917Skarels 66640917Skarels getstr(lusername, sizeof(lusername), "locuser"); 66740917Skarels /* get the "cmd" in the rcmd protocol */ 66840917Skarels getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type"); 66940917Skarels 67040917Skarels pwd = getpwnam(lusername); 67140917Skarels if (pwd == NULL) 67254547Sleres return (-1); 67340917Skarels 67440917Skarels /* returns nonzero for no access */ 67554547Sleres if (kuserok(kdata, lusername) != 0) 67654547Sleres return (-1); 67740917Skarels 67854547Sleres return (0); 67940917Skarels 68040917Skarels } 68140917Skarels #endif /* KERBEROS */ 68240917Skarels 68354547Sleres void 68440917Skarels usage() 68540917Skarels { 68640917Skarels #ifdef KERBEROS 68740917Skarels syslog(LOG_ERR, "usage: rlogind [-aln] [-k | -v]"); 68840917Skarels #else 68940917Skarels syslog(LOG_ERR, "usage: rlogind [-aln]"); 69040917Skarels #endif 69140917Skarels } 69240917Skarels 69340917Skarels /* 69436631Skarels * Check whether host h is in our local domain, 69539058Skarels * defined as sharing the last two components of the domain part, 69639058Skarels * or the entire domain part if the local domain has only one component. 69736631Skarels * If either name is unqualified (contains no '.'), 69836631Skarels * assume that the host is local, as it will be 69936631Skarels * interpreted as such. 70036631Skarels */ 70154547Sleres int 70236631Skarels local_domain(h) 70336631Skarels char *h; 70436625Skfall { 70536631Skarels char localhost[MAXHOSTNAMELEN]; 70654547Sleres char *p1, *p2; 70736631Skarels 70839058Skarels localhost[0] = 0; 70936631Skarels (void) gethostname(localhost, sizeof(localhost)); 71039058Skarels p1 = topdomain(localhost); 71139058Skarels p2 = topdomain(h); 71236631Skarels if (p1 == NULL || p2 == NULL || !strcasecmp(p1, p2)) 71354547Sleres return (1); 71454547Sleres return (0); 71536625Skfall } 71639058Skarels 71739058Skarels char * 71839058Skarels topdomain(h) 71939058Skarels char *h; 72039058Skarels { 72139058Skarels register char *p; 72239058Skarels char *maybe = NULL; 72339058Skarels int dots = 0; 72439058Skarels 72539058Skarels for (p = h + strlen(h); p >= h; p--) { 72639058Skarels if (*p == '.') { 72739058Skarels if (++dots == 2) 72839058Skarels return (p); 72939058Skarels maybe = p; 73039058Skarels } 73139058Skarels } 73239058Skarels return (maybe); 73339058Skarels } 734