121174Sdist /* 236517Skarels * Copyright (c) 1983, 1988 The Regents of the University of California. 335441Sbostic * All rights reserved. 435441Sbostic * 535441Sbostic * Redistribution and use in source and binary forms are permitted 635441Sbostic * provided that the above copyright notice and this paragraph are 735441Sbostic * duplicated in all such forms and that any documentation, 835441Sbostic * advertising materials, and other materials related to such 935441Sbostic * distribution and use acknowledge that the software was developed 1035441Sbostic * by the University of California, Berkeley. The name of the 1135441Sbostic * University may not be used to endorse or promote products derived 1235441Sbostic * from this software without specific prior written permission. 1335441Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1435441Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1535441Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621174Sdist */ 1721174Sdist 186446Swnj #ifndef lint 1921174Sdist char copyright[] = 2036517Skarels "@(#) Copyright (c) 1983, 1988 The Regents of the University of California.\n\ 2121174Sdist All rights reserved.\n"; 2235441Sbostic #endif /* not lint */ 236446Swnj 2421174Sdist #ifndef lint 25*36631Skarels static char sccsid[] = "@(#)rlogind.c 5.26 (Berkeley) 01/25/89"; 2635441Sbostic #endif /* not lint */ 2721174Sdist 2816369Skarels /* 2916369Skarels * remote login server: 3036453Skfall * \0 3116369Skarels * remuser\0 3216369Skarels * locuser\0 3336453Skfall * terminal_type/speed\0 3436518Skarels * data 3516369Skarels */ 3616369Skarels 376446Swnj #include <stdio.h> 386446Swnj #include <sys/types.h> 396446Swnj #include <sys/stat.h> 406446Swnj #include <sys/socket.h> 4113554Ssam #include <sys/wait.h> 4218357Ssam #include <sys/file.h> 4336625Skfall #include <sys/param.h> 449208Ssam 459208Ssam #include <netinet/in.h> 469208Ssam 476446Swnj #include <errno.h> 486446Swnj #include <pwd.h> 496446Swnj #include <signal.h> 5036609Skfall #include <sys/ioctl.h> 5136609Skfall #include <sys/termios.h> 526446Swnj #include <stdio.h> 538380Ssam #include <netdb.h> 5417187Sralph #include <syslog.h> 5518357Ssam #include <strings.h> 566446Swnj 5736518Skarels #ifndef TIOCPKT_WINDOW 5836518Skarels #define TIOCPKT_WINDOW 0x80 5936518Skarels #endif 6036518Skarels 6136609Skfall #ifdef KERBEROS 6236609Skfall #include <kerberos/krb.h> 6336609Skfall #define SECURE_MESSAGE "This rlogin session is using DES encryption for all transmissions.\r\n" 6436609Skfall 6536609Skfall AUTH_DAT *kdata; 6636609Skfall KTEXT ticket; 6736609Skfall u_char auth_buf[sizeof(AUTH_DAT)]; 6836609Skfall u_char tick_buf[sizeof(KTEXT_ST)]; 6936609Skfall Key_schedule schedule; 7036609Skfall int encrypt, retval, use_kerberos = 0, vacuous = 0; 7136609Skfall int do_krb_login(); 7236609Skfall 7336609Skfall #define OLD_RCMD 0x00 7436609Skfall #define KERB_RCMD 0x00 7536609Skfall #define KERB_RCMD_MUTUAL 0x03 7636609Skfall 7736609Skfall #define ARGSTR "lnkv" 7836609Skfall #else 7936609Skfall #define ARGSTR "ln" 8036609Skfall #endif /* KERBEROS */ 8136609Skfall 8236518Skarels char *env[2]; 8336518Skarels #define NMAX 30 8436517Skarels char lusername[NMAX+1], rusername[NMAX+1]; 8536517Skarels static char term[64] = "TERM="; 8636517Skarels #define ENVSIZE (sizeof("TERM=")-1) /* skip null for concatenation */ 8736517Skarels int keepalive = 1; 8836453Skfall 8936453Skfall #define SUPERUSER(pwd) ((pwd)->pw_uid == 0) 9036453Skfall 9134424Sbostic extern int errno; 9210417Ssam int reapchild(); 9336453Skfall struct passwd *getpwnam(), *pwd; 9424723Smckusick char *malloc(); 9516369Skarels 966446Swnj main(argc, argv) 976446Swnj int argc; 986446Swnj char **argv; 996446Swnj { 10036319Sbostic extern int opterr, optind, _check_rhosts_file; 10136319Sbostic int ch; 10234424Sbostic int on = 1, fromlen; 1036446Swnj struct sockaddr_in from; 1046446Swnj 10536625Skfall openlog("rlogind", LOG_PID | LOG_CONS, LOG_AUTH); 10636319Sbostic 10736319Sbostic opterr = 0; 10836609Skfall while ((ch = getopt(argc, argv, ARGSTR)) != EOF) 10936517Skarels switch (ch) { 11036319Sbostic case 'l': 11136319Sbostic _check_rhosts_file = 0; 11236319Sbostic break; 11336517Skarels case 'n': 11436517Skarels keepalive = 0; 11536517Skarels break; 11636609Skfall #ifdef KERBEROS 11736609Skfall case 'k': 11836609Skfall use_kerberos = 1; 11936609Skfall break; 12036609Skfall case 'v': 12136609Skfall vacuous = 1; 12236609Skfall break; 12336609Skfall #endif 12436319Sbostic case '?': 12536319Sbostic default: 12636609Skfall usage(); 12736319Sbostic break; 12836319Sbostic } 12936319Sbostic argc -= optind; 13036319Sbostic argv += optind; 13136319Sbostic 13236609Skfall #ifdef KERBEROS 133*36631Skarels if (use_kerberos && vacuous) { 13436609Skfall fprintf(stderr, "%s: only one of -k and -v allowed\n", argv[0]); 13536609Skfall usage(); 13636609Skfall exit(1); 13736609Skfall } 13836609Skfall #endif 13916369Skarels fromlen = sizeof (from); 14016369Skarels if (getpeername(0, &from, &fromlen) < 0) { 14136625Skfall syslog(LOG_ERR,"Couldn't get peer name of remote host: %m"); 14236319Sbostic exit(1); 1438380Ssam } 14436517Skarels if (keepalive && 14536517Skarels setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) 14617187Sralph syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); 14716369Skarels doit(0, &from); 1486446Swnj } 1496446Swnj 1506446Swnj int child; 1516446Swnj int cleanup(); 1526446Swnj int netf; 1536446Swnj char *line; 15424724Smckusick extern char *inet_ntoa(); 1556446Swnj 15624889Smckusick struct winsize win = { 0, 0, 0, 0 }; 15724723Smckusick 15824889Smckusick 1596446Swnj doit(f, fromp) 1606446Swnj int f; 1616446Swnj struct sockaddr_in *fromp; 1626446Swnj { 16318357Ssam int i, p, t, pid, on = 1; 164*36631Skarels int authenticated = 0, hostok = 0; 16518357Ssam register struct hostent *hp; 166*36631Skarels char remotehost[2 * MAXHOSTNAMELEN + 1]; 16724724Smckusick struct hostent hostent; 1688380Ssam char c; 1696446Swnj 1706446Swnj alarm(60); 1716446Swnj read(f, &c, 1); 17236609Skfall 17336609Skfall #ifdef KERBEROS 17436609Skfall /* 17536609Skfall * XXX 1st char tells us which client we're talking to 17636609Skfall */ 17736609Skfall switch (c) { 17836609Skfall 17936609Skfall case OLD_RCMD: /* OLD_RCMD is same as KERB_RCMD */ 180*36631Skarels if (vacuous) 18136609Skfall fatal(f, "Remote host requires Kerberos authentication"); 18236609Skfall break; 18336609Skfall 18436609Skfall case KERB_RCMD_MUTUAL: 18536609Skfall encrypt = 1; 18636609Skfall break; 18736609Skfall 18836609Skfall default: 18936609Skfall fatal(f, "Remote protocol error"); 19036609Skfall } 19136609Skfall #else 1926446Swnj if (c != 0) 1936446Swnj exit(1); 19436609Skfall #endif 19536453Skfall 1966446Swnj alarm(0); 19716227Skarels fromp->sin_port = ntohs((u_short)fromp->sin_port); 1988380Ssam hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr), 1998380Ssam fromp->sin_family); 20011345Ssam if (hp == 0) { 20124724Smckusick /* 20224724Smckusick * Only the name is used below. 20324724Smckusick */ 20424724Smckusick hp = &hostent; 20524724Smckusick hp->h_name = inet_ntoa(fromp->sin_addr); 206*36631Skarels } else if (local_domain(hp->h_name)) { 207*36631Skarels /* 208*36631Skarels * If name returned by gethostbyaddr is in our domain, 209*36631Skarels * attempt to verify that we haven't been fooled by someone 210*36631Skarels * in a remote net; look up the name and check that this 211*36631Skarels * address corresponds to the name. 212*36631Skarels */ 213*36631Skarels strncpy(remotehost, hp->h_name, sizeof(remotehost) - 1); 214*36631Skarels remotehost[sizeof(remotehost) - 1] = 0; 215*36631Skarels hp = gethostbyname(remotehost); 216*36631Skarels if (hp) 217*36631Skarels for (; hp->h_addr_list[0]; hp->h_addr_list++) { 218*36631Skarels if (!bcmp(hp->h_addr_list[0], (caddr_t)&fromp->sin_addr, 219*36631Skarels sizeof(fromp->sin_addr))) { 220*36631Skarels hostok++; 221*36631Skarels break; 22236625Skfall } 22336625Skfall } 22411345Ssam } 22536453Skfall 22636609Skfall #ifdef KERBEROS 227*36631Skarels if (use_kerberos) { 22836609Skfall retval = do_krb_login(hp->h_name, fromp, encrypt); 22936609Skfall write(f, &c, 1); 230*36631Skarels if (retval == 0) 23136609Skfall authenticated++; 232*36631Skarels else if (retval > 0) 233*36631Skarels fatal(f, krb_err_txt[retval]); 23436609Skfall } else 23536519Skarels #endif 236*36631Skarels if (fromp->sin_family != AF_INET || 237*36631Skarels fromp->sin_port >= IPPORT_RESERVED || 238*36631Skarels fromp->sin_port < IPPORT_RESERVED/2) { 239*36631Skarels syslog(LOG_NOTICE, "Connection from %s on illegal port", 240*36631Skarels inet_ntoa(fromp->sin_addr)); 241*36631Skarels fatal(f, "Permission denied"); 242*36631Skarels } else { 243*36631Skarels write(f, "", 1); 24436453Skfall 245*36631Skarels if (do_rlogin(hp->h_name) == 0) { 246*36631Skarels if (hostok) 247*36631Skarels authenticated++; 248*36631Skarels else 249*36631Skarels write(f, "rlogind: Host address mismatch.\r\n", 250*36631Skarels sizeof("rlogind: Host address mismatch.\r\n") - 1); 25136609Skfall } 252*36631Skarels } 25336609Skfall 2546446Swnj for (c = 'p'; c <= 's'; c++) { 2556446Swnj struct stat stb; 2566446Swnj line = "/dev/ptyXX"; 2576446Swnj line[strlen("/dev/pty")] = c; 2586446Swnj line[strlen("/dev/ptyp")] = '0'; 2596446Swnj if (stat(line, &stb) < 0) 2606446Swnj break; 2616446Swnj for (i = 0; i < 16; i++) { 26234424Sbostic line[sizeof("/dev/ptyp") - 1] = "0123456789abcdef"[i]; 26334424Sbostic p = open(line, O_RDWR); 2646446Swnj if (p > 0) 2656446Swnj goto gotpty; 2666446Swnj } 2676446Swnj } 26824723Smckusick fatal(f, "Out of ptys"); 2699242Ssam /*NOTREACHED*/ 2706446Swnj gotpty: 27124889Smckusick (void) ioctl(p, TIOCSWINSZ, &win); 27216227Skarels netf = f; 2736446Swnj line[strlen("/dev/")] = 't'; 27434424Sbostic t = open(line, O_RDWR); 27534424Sbostic if (t < 0) 27634424Sbostic fatalperror(f, line); 27734424Sbostic if (fchmod(t, 0)) 27834424Sbostic fatalperror(f, line); 27934424Sbostic (void)signal(SIGHUP, SIG_IGN); 28034424Sbostic vhangup(); 28134424Sbostic (void)signal(SIGHUP, SIG_DFL); 28234424Sbostic t = open(line, O_RDWR); 28334424Sbostic if (t < 0) 28434424Sbostic fatalperror(f, line); 28536453Skfall setup_term(t); 2866446Swnj #ifdef DEBUG 28734424Sbostic { 28834424Sbostic int tt = open("/dev/tty", O_RDWR); 28934424Sbostic if (tt > 0) { 29034424Sbostic (void)ioctl(tt, TIOCNOTTY, 0); 29134424Sbostic (void)close(tt); 29234424Sbostic } 2936446Swnj } 2946446Swnj #endif 2959242Ssam pid = fork(); 2969242Ssam if (pid < 0) 29734424Sbostic fatalperror(f, ""); 29818357Ssam if (pid == 0) { 29936609Skfall if (setsid() < 0) 30036609Skfall fatalperror(f, "setsid"); 30136609Skfall if (ioctl(t, TIOCSCTTY, 0) < 0) 30236609Skfall fatalperror(f, "ioctl(sctty)"); 30318357Ssam close(f), close(p); 30418357Ssam dup2(t, 0), dup2(t, 1), dup2(t, 2); 30516227Skarels close(t); 306*36631Skarels if (authenticated) 30736609Skfall execl("/bin/login", "login", "-p", 30836609Skfall "-h", hp->h_name, "-f", lusername, 0); 30936525Skfall else 31036609Skfall execl("/bin/login", "login", "-p", 31136609Skfall "-h", hp->h_name, lusername, 0); 31234424Sbostic fatalperror(2, "/bin/login"); 31318357Ssam /*NOTREACHED*/ 31418357Ssam } 31518357Ssam close(t); 31636453Skfall 31736609Skfall #ifdef KERBEROS 31836609Skfall /* 31936609Skfall * If encrypted, don't turn on NBIO or the des read/write 32036609Skfall * routines will croak. 32136609Skfall */ 32236609Skfall 32336609Skfall if (encrypt) 32436609Skfall (void) des_write(f, SECURE_MESSAGE, sizeof(SECURE_MESSAGE)); 32536609Skfall else 32636609Skfall #endif 32736609Skfall ioctl(f, FIONBIO, &on); 32818357Ssam ioctl(p, FIONBIO, &on); 32918357Ssam ioctl(p, TIOCPKT, &on); 33018357Ssam signal(SIGTSTP, SIG_IGN); 33118357Ssam signal(SIGCHLD, cleanup); 33224724Smckusick setpgrp(0, 0); 33318357Ssam protocol(f, p); 33430600Smckusick signal(SIGCHLD, SIG_IGN); 33518357Ssam cleanup(); 33618357Ssam } 3379242Ssam 33818357Ssam char magic[2] = { 0377, 0377 }; 33925423Skarels char oobdata[] = {TIOCPKT_WINDOW}; 34018357Ssam 34118357Ssam /* 34218357Ssam * Handle a "control" request (signaled by magic being present) 34318357Ssam * in the data stream. For now, we are only willing to handle 34418357Ssam * window size changes. 34518357Ssam */ 34618357Ssam control(pty, cp, n) 34718357Ssam int pty; 34818357Ssam char *cp; 34918357Ssam int n; 35018357Ssam { 35128705Smckusick struct winsize w; 35218357Ssam 35328705Smckusick if (n < 4+sizeof (w) || cp[2] != 's' || cp[3] != 's') 35418357Ssam return (0); 35525423Skarels oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */ 35628705Smckusick bcopy(cp+4, (char *)&w, sizeof(w)); 35728705Smckusick w.ws_row = ntohs(w.ws_row); 35828705Smckusick w.ws_col = ntohs(w.ws_col); 35928705Smckusick w.ws_xpixel = ntohs(w.ws_xpixel); 36028705Smckusick w.ws_ypixel = ntohs(w.ws_ypixel); 36128705Smckusick (void)ioctl(pty, TIOCSWINSZ, &w); 36228705Smckusick return (4+sizeof (w)); 36318357Ssam } 36418357Ssam 36518357Ssam /* 36618357Ssam * rlogin "protocol" machine. 36718357Ssam */ 36818357Ssam protocol(f, p) 36918357Ssam int f, p; 37018357Ssam { 37118357Ssam char pibuf[1024], fibuf[1024], *pbp, *fbp; 37218357Ssam register pcc = 0, fcc = 0; 37336517Skarels int cc, nfd, pmask, fmask; 37425740Skarels char cntl; 37518357Ssam 37618482Ssam /* 37718484Ssam * Must ignore SIGTTOU, otherwise we'll stop 37818484Ssam * when we try and set slave pty's window shape 37925423Skarels * (our controlling tty is the master pty). 38018482Ssam */ 38118484Ssam (void) signal(SIGTTOU, SIG_IGN); 38225423Skarels send(f, oobdata, 1, MSG_OOB); /* indicate new rlogin */ 38336517Skarels if (f > p) 38436517Skarels nfd = f + 1; 38536517Skarels else 38636517Skarels nfd = p + 1; 38736517Skarels fmask = 1 << f; 38836517Skarels pmask = 1 << p; 38918357Ssam for (;;) { 39025740Skarels int ibits, obits, ebits; 39118357Ssam 39225740Skarels ibits = 0; 39325740Skarels obits = 0; 39418357Ssam if (fcc) 39536517Skarels obits |= pmask; 39618357Ssam else 39736517Skarels ibits |= fmask; 39818357Ssam if (pcc >= 0) 39918357Ssam if (pcc) 40036517Skarels obits |= fmask; 4019242Ssam else 40236517Skarels ibits |= pmask; 40336517Skarels ebits = pmask; 40436517Skarels if (select(nfd, &ibits, obits ? &obits : (int *)NULL, 40536517Skarels &ebits, 0) < 0) { 40618357Ssam if (errno == EINTR) 4076446Swnj continue; 40834424Sbostic fatalperror(f, "select"); 40918357Ssam } 41025740Skarels if (ibits == 0 && obits == 0 && ebits == 0) { 41118357Ssam /* shouldn't happen... */ 41218357Ssam sleep(5); 41318357Ssam continue; 41418357Ssam } 41525740Skarels #define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP)) 41636517Skarels if (ebits & pmask) { 41725740Skarels cc = read(p, &cntl, 1); 41825740Skarels if (cc == 1 && pkcontrol(cntl)) { 41925740Skarels cntl |= oobdata[0]; 42025740Skarels send(f, &cntl, 1, MSG_OOB); 42125740Skarels if (cntl & TIOCPKT_FLUSHWRITE) { 42225740Skarels pcc = 0; 42336517Skarels ibits &= ~pmask; 42425740Skarels } 42525740Skarels } 42625740Skarels } 42736517Skarels if (ibits & fmask) { 42836609Skfall #ifdef KERBEROS 42936609Skfall if (encrypt) 43036609Skfall fcc = des_read(f, fibuf, sizeof(fibuf)); 43136609Skfall else 43236609Skfall #endif 43336609Skfall fcc = read(f, fibuf, sizeof(fibuf)); 43418357Ssam if (fcc < 0 && errno == EWOULDBLOCK) 43518357Ssam fcc = 0; 43618357Ssam else { 43718357Ssam register char *cp; 43818357Ssam int left, n; 43918357Ssam 44018357Ssam if (fcc <= 0) 44116227Skarels break; 44218357Ssam fbp = fibuf; 44324723Smckusick 44418357Ssam top: 44525423Skarels for (cp = fibuf; cp < fibuf+fcc-1; cp++) 44618357Ssam if (cp[0] == magic[0] && 44718357Ssam cp[1] == magic[1]) { 44818357Ssam left = fcc - (cp-fibuf); 44918357Ssam n = control(p, cp, left); 45018357Ssam if (n) { 45118357Ssam left -= n; 45218357Ssam if (left > 0) 45325423Skarels bcopy(cp+n, cp, left); 45418357Ssam fcc -= n; 45518357Ssam goto top; /* n^2 */ 45625423Skarels } 45725423Skarels } 45836517Skarels obits |= pmask; /* try write */ 45925423Skarels } 46025423Skarels } 46124723Smckusick 46236517Skarels if ((obits & pmask) && fcc > 0) { 46325423Skarels cc = write(p, fbp, fcc); 46424723Smckusick if (cc > 0) { 46524723Smckusick fcc -= cc; 46624723Smckusick fbp += cc; 4676446Swnj } 46818357Ssam } 46924723Smckusick 47036517Skarels if (ibits & pmask) { 47118357Ssam pcc = read(p, pibuf, sizeof (pibuf)); 47218357Ssam pbp = pibuf; 47318357Ssam if (pcc < 0 && errno == EWOULDBLOCK) 47418357Ssam pcc = 0; 47518357Ssam else if (pcc <= 0) 47618357Ssam break; 47736517Skarels else if (pibuf[0] == 0) { 47818357Ssam pbp++, pcc--; 47936609Skfall #ifdef KERBEROS 48036609Skfall if (!encrypt) 48136609Skfall #endif 48236609Skfall obits |= fmask; /* try a write */ 48336517Skarels } else { 48418357Ssam if (pkcontrol(pibuf[0])) { 48525423Skarels pibuf[0] |= oobdata[0]; 48618357Ssam send(f, &pibuf[0], 1, MSG_OOB); 48716227Skarels } 48818357Ssam pcc = 0; 4896446Swnj } 49018357Ssam } 49136517Skarels if ((obits & fmask) && pcc > 0) { 49236609Skfall #ifdef KERBEROS 49336609Skfall if (encrypt) 49436609Skfall cc = des_write(f, pbp, pcc); 49536609Skfall else 49636609Skfall #endif 49736609Skfall cc = write(f, pbp, pcc); 49825423Skarels if (cc < 0 && errno == EWOULDBLOCK) { 49925423Skarels /* also shouldn't happen */ 50025423Skarels sleep(5); 50125423Skarels continue; 50225423Skarels } 50318357Ssam if (cc > 0) { 50418357Ssam pcc -= cc; 50518357Ssam pbp += cc; 50618357Ssam } 5076446Swnj } 5086446Swnj } 5096446Swnj } 5106446Swnj 5116446Swnj cleanup() 5126446Swnj { 51335440Sbostic char *p; 51435440Sbostic 51535440Sbostic p = line + sizeof("/dev/") - 1; 51635440Sbostic if (logout(p)) 51735440Sbostic logwtmp(p, "", ""); 51835440Sbostic (void)chmod(line, 0666); 51935440Sbostic (void)chown(line, 0, 0); 52035440Sbostic *p = 'p'; 52135440Sbostic (void)chmod(line, 0666); 52235440Sbostic (void)chown(line, 0, 0); 52310192Ssam shutdown(netf, 2); 5246446Swnj exit(1); 5256446Swnj } 5266446Swnj 5279242Ssam fatal(f, msg) 5289242Ssam int f; 5299242Ssam char *msg; 5309242Ssam { 5319242Ssam char buf[BUFSIZ]; 5329242Ssam 5339242Ssam buf[0] = '\01'; /* error indicator */ 53413554Ssam (void) sprintf(buf + 1, "rlogind: %s.\r\n", msg); 5359242Ssam (void) write(f, buf, strlen(buf)); 5369242Ssam exit(1); 5379242Ssam } 5389242Ssam 53934424Sbostic fatalperror(f, msg) 5409242Ssam int f; 5419242Ssam char *msg; 5429242Ssam { 5439242Ssam char buf[BUFSIZ]; 54416227Skarels extern int sys_nerr; 5459242Ssam extern char *sys_errlist[]; 5469242Ssam 54718357Ssam if ((unsigned)errno < sys_nerr) 54816227Skarels (void) sprintf(buf, "%s: %s", msg, sys_errlist[errno]); 54916227Skarels else 55016227Skarels (void) sprintf(buf, "%s: Error %d", msg, errno); 5519242Ssam fatal(f, buf); 5529242Ssam } 55336453Skfall 55436453Skfall do_rlogin(host) 55536518Skarels char *host; 55636453Skfall { 55736453Skfall 55836518Skarels getstr(rusername, sizeof(rusername), "remuser too long"); 55936518Skarels getstr(lusername, sizeof(lusername), "locuser too long"); 56036518Skarels getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type too long"); 56136518Skarels 56236518Skarels if (getuid()) 56336453Skfall return(-1); 56436453Skfall pwd = getpwnam(lusername); 56536518Skarels if (pwd == NULL) 56636453Skfall return(-1); 56736453Skfall return(ruserok(host, SUPERUSER(pwd), rusername, lusername)); 56836453Skfall } 56936453Skfall 57036453Skfall 57136518Skarels getstr(buf, cnt, errmsg) 57236518Skarels char *buf; 57336518Skarels int cnt; 57436518Skarels char *errmsg; 57536453Skfall { 57636518Skarels char c; 57736518Skarels 57836453Skfall do { 57936518Skarels if (read(0, &c, 1) != 1) 58036453Skfall exit(1); 58136518Skarels if (--cnt < 0) 58236518Skarels fatal(1, errmsg); 58336453Skfall *buf++ = c; 58436518Skarels } while (c != 0); 58536453Skfall } 58636453Skfall 58736518Skarels extern char **environ; 58836453Skfall 58936519Skarels setup_term(fd) 59036519Skarels int fd; 59136519Skarels { 59236609Skfall struct termios tt; 59336609Skfall register char *cp = index(term+ENVSIZE, '/'); 59436519Skarels char *speed; 59536519Skarels 59636609Skfall tcgetattr(fd, &tt); 59736519Skarels if (cp) { 59836519Skarels *cp++ = '\0'; 59936519Skarels speed = cp; 60036519Skarels cp = index(speed, '/'); 60136519Skarels if (cp) 60236519Skarels *cp++ = '\0'; 60336609Skfall cfsetspeed(&tt, atoi(speed)); 60436519Skarels } 60536609Skfall tt.c_iflag = BRKINT|ICRNL|IXON|ISTRIP|IEXTEN|IMAXBEL; 60636609Skfall tt.c_oflag = OPOST|ONLCR|OXTABS; 60736609Skfall tt.c_lflag = ISIG|ICANON|ECHO; 60836609Skfall tcsetattr(fd, TCSADFLUSH, &tt); 60936519Skarels 61036519Skarels env[0] = term; 61136519Skarels env[1] = 0; 61236519Skarels environ = env; 61336519Skarels } 61436609Skfall 61536609Skfall #ifdef KERBEROS 61636609Skfall #define VERSION_SIZE 9 61736609Skfall 61836609Skfall /* 61936609Skfall * Do the remote kerberos login to the named host with the 62036609Skfall * given inet address 62136609Skfall * 62236609Skfall * Return 0 on valid authorization 62336609Skfall * Return -1 on valid authentication, no authorization 62436609Skfall * Return >0 for error conditions 62536609Skfall */ 62636609Skfall do_krb_login(host, dest, encrypt) 62736609Skfall char *host; 62836609Skfall struct sockaddr_in *dest; 62936609Skfall int encrypt; 63036609Skfall { 63136609Skfall int rc; 63236609Skfall char instance[INST_SZ], version[VERSION_SIZE]; 63336609Skfall long authopts = 0L; /* !mutual */ 63436609Skfall struct sockaddr_in faddr; 63536609Skfall 63636609Skfall if (getuid()) 63736609Skfall return(KFAILURE); 63836609Skfall 63936609Skfall kdata = (AUTH_DAT *) auth_buf; 64036609Skfall ticket = (KTEXT) tick_buf; 64136609Skfall strcpy(instance, "*"); 64236609Skfall 64336609Skfall if (encrypt) { 64436609Skfall rc = sizeof(faddr); 64536609Skfall if (getsockname(0, &faddr, &rc)) 64636609Skfall return(-1); 64736609Skfall authopts = KOPT_DO_MUTUAL; 64836609Skfall rc = krb_recvauth( 64936609Skfall authopts, 0, 65036609Skfall ticket, "rcmd", 65136609Skfall instance, dest, &faddr, 65236609Skfall kdata, "", schedule, version); 65336609Skfall des_set_key(kdata->session, schedule); 65436609Skfall 65536609Skfall } else { 65636609Skfall rc = krb_recvauth( 65736609Skfall authopts, 0, 65836609Skfall ticket, "rcmd", 65936609Skfall instance, dest, (struct sockaddr_in *) 0, 66036609Skfall kdata, "", (bit_64 *) 0, version); 66136609Skfall } 66236609Skfall 66336609Skfall if (rc != KSUCCESS) 66436609Skfall return(rc); 66536609Skfall 66636609Skfall if ((rc = krb_kntoln(kdata, rusername)) != KSUCCESS) 66736609Skfall return(rc); 66836609Skfall 66936609Skfall getstr(lusername, sizeof(lusername), "locuser"); 67036609Skfall /* get the "cmd" in the rcmd protocol */ 67136609Skfall getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type"); 67236609Skfall 67336609Skfall pwd = getpwnam(lusername); 67436609Skfall if (pwd == NULL) 67536609Skfall return(-1); 67636609Skfall 67736609Skfall /* returns nonzero for no access */ 67836609Skfall /* return(ruserok(host, SUPERUSER(pwd), rusername, lusername)); */ 679*36631Skarels if (kuserok(kdata,lusername) != 0) 68036609Skfall return(-1); 68136609Skfall 68236609Skfall return(0); 68336609Skfall 68436609Skfall } 68536609Skfall 68636609Skfall #endif /* KERBEROS */ 68736609Skfall 68836609Skfall usage() 68936609Skfall { 69036609Skfall #ifdef KERBEROS 69136609Skfall syslog(LOG_ERR, "usage: rlogind [-k | -v] [-l] [-n]"); 69236609Skfall #else 69336609Skfall syslog(LOG_ERR, "usage: rlogind [-l] [-n]"); 69436609Skfall #endif 69536609Skfall } 69636625Skfall 697*36631Skarels /* 698*36631Skarels * Check whether host h is in our local domain, 699*36631Skarels * as determined by the part of the name following 700*36631Skarels * the first '.' in its name and in ours. 701*36631Skarels * If either name is unqualified (contains no '.'), 702*36631Skarels * assume that the host is local, as it will be 703*36631Skarels * interpreted as such. 704*36631Skarels */ 705*36631Skarels local_domain(h) 706*36631Skarels char *h; 70736625Skfall { 708*36631Skarels char localhost[MAXHOSTNAMELEN]; 709*36631Skarels char *p1, *p2 = index(h, '.'); 710*36631Skarels 711*36631Skarels (void) gethostname(localhost, sizeof(localhost)); 712*36631Skarels p1 = index(localhost, '.'); 713*36631Skarels if (p1 == NULL || p2 == NULL || !strcasecmp(p1, p2)) 71436625Skfall return(1); 71536625Skfall return(0); 71636625Skfall } 717