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*36639Skfall static char sccsid[] = "@(#)rlogind.c 5.30 (Berkeley) 01/26/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> 3836636Skarels #include <sys/types.h> 396446Swnj #include <sys/stat.h> 406446Swnj #include <sys/socket.h> 4113554Ssam #include <sys/wait.h> 4218357Ssam #include <sys/file.h> 4336636Skarels #include <sys/param.h> 449208Ssam 459208Ssam #include <netinet/in.h> 469208Ssam 476446Swnj #include <errno.h> 486446Swnj #include <pwd.h> 496446Swnj #include <signal.h> 5036636Skarels #include <sys/ioctl.h> 5136636Skarels #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 6136636Skarels #ifdef KERBEROS 6236636Skarels #include <kerberos/krb.h> 6336636Skarels #define SECURE_MESSAGE "This rlogin session is using DES encryption for all transmissions.\r\n" 6436636Skarels 6536636Skarels AUTH_DAT *kdata; 6636636Skarels KTEXT ticket; 6736636Skarels u_char auth_buf[sizeof(AUTH_DAT)]; 6836636Skarels u_char tick_buf[sizeof(KTEXT_ST)]; 6936636Skarels Key_schedule schedule; 70*36639Skfall int encrypt = 0, retval, use_kerberos = 0, vacuous = 0; 7136636Skarels int do_krb_login(); 7236636Skarels 7336636Skarels #define OLD_RCMD 0x00 7436636Skarels #define KERB_RCMD 0x00 7536636Skarels #define KERB_RCMD_MUTUAL 0x03 7636636Skarels 7736636Skarels #define ARGSTR "lnkv" 7836636Skarels #else 7936636Skarels #define ARGSTR "ln" 8036636Skarels #endif /* KERBEROS */ 8136636Skarels 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; 10836636Skarels 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; 11636636Skarels #ifdef KERBEROS 11736636Skarels case 'k': 11836636Skarels use_kerberos = 1; 11936636Skarels break; 12036636Skarels case 'v': 12136636Skarels vacuous = 1; 12236636Skarels break; 12336636Skarels #endif 12436319Sbostic case '?': 12536319Sbostic default: 12636636Skarels usage(); 12736319Sbostic break; 12836319Sbostic } 12936319Sbostic argc -= optind; 13036319Sbostic argv += optind; 13136319Sbostic 13236636Skarels #ifdef KERBEROS 13336636Skarels if (use_kerberos && vacuous) { 13436636Skarels usage(); 13536636Skarels fatal("only one of -k and -v allowed\n"); 13636636Skarels } 13736636Skarels #endif 13816369Skarels fromlen = sizeof (from); 13916369Skarels if (getpeername(0, &from, &fromlen) < 0) { 14036636Skarels syslog(LOG_ERR,"Can't get peer name of remote host: %m"); 14136636Skarels fatalperror("Can't get peer name of remote host"); 1428380Ssam } 14336517Skarels if (keepalive && 14436517Skarels setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) 14517187Sralph syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); 14616369Skarels doit(0, &from); 1476446Swnj } 1486446Swnj 1496446Swnj int child; 1506446Swnj int cleanup(); 1516446Swnj int netf; 1526446Swnj char *line; 15324724Smckusick extern char *inet_ntoa(); 1546446Swnj 15524889Smckusick struct winsize win = { 0, 0, 0, 0 }; 15624723Smckusick 15724889Smckusick 1586446Swnj doit(f, fromp) 1596446Swnj int f; 1606446Swnj struct sockaddr_in *fromp; 1616446Swnj { 16218357Ssam int i, p, t, pid, on = 1; 16336631Skarels int authenticated = 0, hostok = 0; 16436636Skarels register struct hostent *hp; 16536635Skarels char remotehost[2 * MAXHOSTNAMELEN + 1]; 16624724Smckusick struct hostent hostent; 1678380Ssam char c; 1686446Swnj 1696446Swnj alarm(60); 1706446Swnj read(f, &c, 1); 17136636Skarels 17236636Skarels #ifdef KERBEROS 17336636Skarels /* 174*36639Skfall * XXX: 1st char tells us which client we're talking to 17536636Skarels */ 17636636Skarels switch (c) { 17736636Skarels 178*36639Skfall case OLD_RCMD: /* NB: OLD_RCMD == KERB_RCMD */ 17936636Skarels if (vacuous) 18036636Skarels fatal(f, "Remote host requires Kerberos authentication"); 18136636Skarels break; 18236636Skarels 18336636Skarels case KERB_RCMD_MUTUAL: 18436636Skarels encrypt = 1; 18536636Skarels break; 18636636Skarels 18736636Skarels default: 18836636Skarels fatal(f, "Remote protocol error"); 18936636Skarels } 19036636Skarels #else 1916446Swnj if (c != 0) 1926446Swnj exit(1); 19336636Skarels #endif 19436453Skfall 1956446Swnj alarm(0); 19616227Skarels fromp->sin_port = ntohs((u_short)fromp->sin_port); 1978380Ssam hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr), 1988380Ssam fromp->sin_family); 19911345Ssam if (hp == 0) { 20024724Smckusick /* 20124724Smckusick * Only the name is used below. 20224724Smckusick */ 20324724Smckusick hp = &hostent; 20424724Smckusick hp->h_name = inet_ntoa(fromp->sin_addr); 20536635Skarels hostok++; 20636636Skarels } else if (local_domain(hp->h_name)) { 20736635Skarels /* 20836635Skarels * If name returned by gethostbyaddr is in our domain, 20936635Skarels * attempt to verify that we haven't been fooled by someone 21036635Skarels * in a remote net; look up the name and check that this 21136635Skarels * address corresponds to the name. 21236635Skarels */ 21336635Skarels strncpy(remotehost, hp->h_name, sizeof(remotehost) - 1); 21436635Skarels remotehost[sizeof(remotehost) - 1] = 0; 21536635Skarels hp = gethostbyname(remotehost); 21636635Skarels if (hp) 21736635Skarels for (; hp->h_addr_list[0]; hp->h_addr_list++) 21836635Skarels if (!bcmp(hp->h_addr_list[0], (caddr_t)&fromp->sin_addr, 21936635Skarels sizeof(fromp->sin_addr))) { 22036635Skarels hostok++; 22136635Skarels break; 22236635Skarels } 22336633Skarels } else 22436635Skarels hostok++; 22536636Skarels 22636636Skarels #ifdef KERBEROS 22736636Skarels if (use_kerberos) { 22836636Skarels retval = do_krb_login(hp->h_name, fromp, encrypt); 22936636Skarels write(f, &c, 1); 230*36639Skfall if (retval == 0 && hostok) 23136636Skarels authenticated++; 23236636Skarels else if (retval > 0) 23336636Skarels fatal(f, krb_err_txt[retval]); 234*36639Skfall else if(!hostok) 235*36639Skfall fatal(f, "krlogind: Host address mismatch.\r\n"); 23636636Skarels } else 23736633Skarels #endif 238*36639Skfall { 239*36639Skfall if (fromp->sin_family != AF_INET || 240*36639Skfall fromp->sin_port >= IPPORT_RESERVED || 241*36639Skfall fromp->sin_port < IPPORT_RESERVED/2) { 242*36639Skfall syslog(LOG_NOTICE, "Connection from %s on illegal port", 243*36639Skfall inet_ntoa(fromp->sin_addr)); 244*36639Skfall fatal(f, "Permission denied"); 245*36639Skfall } 246*36639Skfall write(f, "", 1); 247*36639Skfall 248*36639Skfall if (do_rlogin(hp->h_name) == 0) { 249*36639Skfall if (hostok) 250*36639Skfall authenticated++; 251*36639Skfall else 252*36639Skfall write(f, "rlogind: Host address mismatch.\r\n", 253*36639Skfall sizeof("rlogind: Host address mismatch.\r\n") - 1); 254*36639Skfall } 25536631Skarels } 25636636Skarels 2576446Swnj for (c = 'p'; c <= 's'; c++) { 2586446Swnj struct stat stb; 2596446Swnj line = "/dev/ptyXX"; 2606446Swnj line[strlen("/dev/pty")] = c; 2616446Swnj line[strlen("/dev/ptyp")] = '0'; 2626446Swnj if (stat(line, &stb) < 0) 2636446Swnj break; 2646446Swnj for (i = 0; i < 16; i++) { 26534424Sbostic line[sizeof("/dev/ptyp") - 1] = "0123456789abcdef"[i]; 26634424Sbostic p = open(line, O_RDWR); 2676446Swnj if (p > 0) 2686446Swnj goto gotpty; 2696446Swnj } 2706446Swnj } 27124723Smckusick fatal(f, "Out of ptys"); 2729242Ssam /*NOTREACHED*/ 2736446Swnj gotpty: 27424889Smckusick (void) ioctl(p, TIOCSWINSZ, &win); 27516227Skarels netf = f; 2766446Swnj line[strlen("/dev/")] = 't'; 27734424Sbostic t = open(line, O_RDWR); 27834424Sbostic if (t < 0) 27934424Sbostic fatalperror(f, line); 28034424Sbostic if (fchmod(t, 0)) 28134424Sbostic fatalperror(f, line); 28234424Sbostic (void)signal(SIGHUP, SIG_IGN); 28334424Sbostic vhangup(); 28434424Sbostic (void)signal(SIGHUP, SIG_DFL); 28534424Sbostic t = open(line, O_RDWR); 28634424Sbostic if (t < 0) 28734424Sbostic fatalperror(f, line); 28836453Skfall setup_term(t); 2896446Swnj #ifdef DEBUG 29034424Sbostic { 29134424Sbostic int tt = open("/dev/tty", O_RDWR); 29234424Sbostic if (tt > 0) { 29334424Sbostic (void)ioctl(tt, TIOCNOTTY, 0); 29434424Sbostic (void)close(tt); 29534424Sbostic } 2966446Swnj } 2976446Swnj #endif 2989242Ssam pid = fork(); 2999242Ssam if (pid < 0) 30034424Sbostic fatalperror(f, ""); 30118357Ssam if (pid == 0) { 30236636Skarels if (setsid() < 0) 30336636Skarels fatalperror(f, "setsid"); 30436636Skarels if (ioctl(t, TIOCSCTTY, 0) < 0) 30536636Skarels fatalperror(f, "ioctl(sctty)"); 30618357Ssam close(f), close(p); 30718357Ssam dup2(t, 0), dup2(t, 1), dup2(t, 2); 30816227Skarels close(t); 30936631Skarels if (authenticated) 31036636Skarels execl("/bin/login", "login", "-p", 31136636Skarels "-h", hp->h_name, "-f", lusername, 0); 31236525Skfall else 31336636Skarels execl("/bin/login", "login", "-p", 31436636Skarels "-h", hp->h_name, lusername, 0); 31534424Sbostic fatalperror(2, "/bin/login"); 31618357Ssam /*NOTREACHED*/ 31718357Ssam } 31818357Ssam close(t); 31936453Skfall 32036636Skarels #ifdef KERBEROS 32136636Skarels /* 32236636Skarels * If encrypted, don't turn on NBIO or the des read/write 32336636Skarels * routines will croak. 32436636Skarels */ 32536636Skarels 32636636Skarels if (encrypt) 32736636Skarels (void) des_write(f, SECURE_MESSAGE, sizeof(SECURE_MESSAGE)); 32836636Skarels else 32936636Skarels #endif 33036636Skarels ioctl(f, FIONBIO, &on); 33118357Ssam ioctl(p, FIONBIO, &on); 33218357Ssam ioctl(p, TIOCPKT, &on); 33318357Ssam signal(SIGTSTP, SIG_IGN); 33418357Ssam signal(SIGCHLD, cleanup); 33524724Smckusick setpgrp(0, 0); 33618357Ssam protocol(f, p); 33730600Smckusick signal(SIGCHLD, SIG_IGN); 33818357Ssam cleanup(); 33918357Ssam } 3409242Ssam 34118357Ssam char magic[2] = { 0377, 0377 }; 34225423Skarels char oobdata[] = {TIOCPKT_WINDOW}; 34318357Ssam 34418357Ssam /* 34518357Ssam * Handle a "control" request (signaled by magic being present) 34618357Ssam * in the data stream. For now, we are only willing to handle 34718357Ssam * window size changes. 34818357Ssam */ 34918357Ssam control(pty, cp, n) 35018357Ssam int pty; 35118357Ssam char *cp; 35218357Ssam int n; 35318357Ssam { 35428705Smckusick struct winsize w; 35518357Ssam 35628705Smckusick if (n < 4+sizeof (w) || cp[2] != 's' || cp[3] != 's') 35718357Ssam return (0); 35825423Skarels oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */ 35928705Smckusick bcopy(cp+4, (char *)&w, sizeof(w)); 36028705Smckusick w.ws_row = ntohs(w.ws_row); 36128705Smckusick w.ws_col = ntohs(w.ws_col); 36228705Smckusick w.ws_xpixel = ntohs(w.ws_xpixel); 36328705Smckusick w.ws_ypixel = ntohs(w.ws_ypixel); 36428705Smckusick (void)ioctl(pty, TIOCSWINSZ, &w); 36528705Smckusick return (4+sizeof (w)); 36618357Ssam } 36718357Ssam 36818357Ssam /* 36918357Ssam * rlogin "protocol" machine. 37018357Ssam */ 37118357Ssam protocol(f, p) 37218357Ssam int f, p; 37318357Ssam { 37418357Ssam char pibuf[1024], fibuf[1024], *pbp, *fbp; 37518357Ssam register pcc = 0, fcc = 0; 37636517Skarels int cc, nfd, pmask, fmask; 37725740Skarels char cntl; 37818357Ssam 37918482Ssam /* 38018484Ssam * Must ignore SIGTTOU, otherwise we'll stop 38118484Ssam * when we try and set slave pty's window shape 38225423Skarels * (our controlling tty is the master pty). 38318482Ssam */ 38418484Ssam (void) signal(SIGTTOU, SIG_IGN); 38525423Skarels send(f, oobdata, 1, MSG_OOB); /* indicate new rlogin */ 38636517Skarels if (f > p) 38736517Skarels nfd = f + 1; 38836517Skarels else 38936517Skarels nfd = p + 1; 39036517Skarels fmask = 1 << f; 39136517Skarels pmask = 1 << p; 39218357Ssam for (;;) { 39325740Skarels int ibits, obits, ebits; 39418357Ssam 39525740Skarels ibits = 0; 39625740Skarels obits = 0; 39718357Ssam if (fcc) 39836517Skarels obits |= pmask; 39918357Ssam else 40036517Skarels ibits |= fmask; 40118357Ssam if (pcc >= 0) 40218357Ssam if (pcc) 40336517Skarels obits |= fmask; 4049242Ssam else 40536517Skarels ibits |= pmask; 40636517Skarels ebits = pmask; 40736517Skarels if (select(nfd, &ibits, obits ? &obits : (int *)NULL, 40836517Skarels &ebits, 0) < 0) { 40918357Ssam if (errno == EINTR) 4106446Swnj continue; 41134424Sbostic fatalperror(f, "select"); 41218357Ssam } 41325740Skarels if (ibits == 0 && obits == 0 && ebits == 0) { 41418357Ssam /* shouldn't happen... */ 41518357Ssam sleep(5); 41618357Ssam continue; 41718357Ssam } 41825740Skarels #define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP)) 41936517Skarels if (ebits & pmask) { 42025740Skarels cc = read(p, &cntl, 1); 42125740Skarels if (cc == 1 && pkcontrol(cntl)) { 42225740Skarels cntl |= oobdata[0]; 42325740Skarels send(f, &cntl, 1, MSG_OOB); 42425740Skarels if (cntl & TIOCPKT_FLUSHWRITE) { 42525740Skarels pcc = 0; 42636517Skarels ibits &= ~pmask; 42725740Skarels } 42825740Skarels } 42925740Skarels } 43036517Skarels if (ibits & fmask) { 43136636Skarels #ifdef KERBEROS 43236636Skarels if (encrypt) 43336636Skarels fcc = des_read(f, fibuf, sizeof(fibuf)); 43436636Skarels else 43536636Skarels #endif 43636636Skarels fcc = read(f, fibuf, sizeof(fibuf)); 43718357Ssam if (fcc < 0 && errno == EWOULDBLOCK) 43818357Ssam fcc = 0; 43918357Ssam else { 44018357Ssam register char *cp; 44118357Ssam int left, n; 44218357Ssam 44318357Ssam if (fcc <= 0) 44416227Skarels break; 44518357Ssam fbp = fibuf; 44624723Smckusick 44718357Ssam top: 44825423Skarels for (cp = fibuf; cp < fibuf+fcc-1; cp++) 44918357Ssam if (cp[0] == magic[0] && 45018357Ssam cp[1] == magic[1]) { 45118357Ssam left = fcc - (cp-fibuf); 45218357Ssam n = control(p, cp, left); 45318357Ssam if (n) { 45418357Ssam left -= n; 45518357Ssam if (left > 0) 45625423Skarels bcopy(cp+n, cp, left); 45718357Ssam fcc -= n; 45818357Ssam goto top; /* n^2 */ 45925423Skarels } 46025423Skarels } 46136517Skarels obits |= pmask; /* try write */ 46225423Skarels } 46325423Skarels } 46424723Smckusick 46536517Skarels if ((obits & pmask) && fcc > 0) { 46625423Skarels cc = write(p, fbp, fcc); 46724723Smckusick if (cc > 0) { 46824723Smckusick fcc -= cc; 46924723Smckusick fbp += cc; 4706446Swnj } 47118357Ssam } 47224723Smckusick 47336517Skarels if (ibits & pmask) { 47418357Ssam pcc = read(p, pibuf, sizeof (pibuf)); 47518357Ssam pbp = pibuf; 47618357Ssam if (pcc < 0 && errno == EWOULDBLOCK) 47718357Ssam pcc = 0; 47818357Ssam else if (pcc <= 0) 47918357Ssam break; 48036517Skarels else if (pibuf[0] == 0) { 48118357Ssam pbp++, pcc--; 48236636Skarels #ifdef KERBEROS 48336636Skarels if (!encrypt) 48436636Skarels #endif 48536636Skarels obits |= fmask; /* try a write */ 48636517Skarels } else { 48718357Ssam if (pkcontrol(pibuf[0])) { 48825423Skarels pibuf[0] |= oobdata[0]; 48918357Ssam send(f, &pibuf[0], 1, MSG_OOB); 49016227Skarels } 49118357Ssam pcc = 0; 4926446Swnj } 49318357Ssam } 49436517Skarels if ((obits & fmask) && pcc > 0) { 49536636Skarels #ifdef KERBEROS 49636636Skarels if (encrypt) 49736636Skarels cc = des_write(f, pbp, pcc); 49836636Skarels else 49936636Skarels #endif 50036636Skarels cc = write(f, pbp, pcc); 50125423Skarels if (cc < 0 && errno == EWOULDBLOCK) { 50225423Skarels /* also shouldn't happen */ 50325423Skarels sleep(5); 50425423Skarels continue; 50525423Skarels } 50618357Ssam if (cc > 0) { 50718357Ssam pcc -= cc; 50818357Ssam pbp += cc; 50918357Ssam } 5106446Swnj } 5116446Swnj } 5126446Swnj } 5136446Swnj 5146446Swnj cleanup() 5156446Swnj { 51635440Sbostic char *p; 51735440Sbostic 51835440Sbostic p = line + sizeof("/dev/") - 1; 51935440Sbostic if (logout(p)) 52035440Sbostic logwtmp(p, "", ""); 52135440Sbostic (void)chmod(line, 0666); 52235440Sbostic (void)chown(line, 0, 0); 52335440Sbostic *p = 'p'; 52435440Sbostic (void)chmod(line, 0666); 52535440Sbostic (void)chown(line, 0, 0); 52610192Ssam shutdown(netf, 2); 5276446Swnj exit(1); 5286446Swnj } 5296446Swnj 5309242Ssam fatal(f, msg) 5319242Ssam int f; 5329242Ssam char *msg; 5339242Ssam { 5349242Ssam char buf[BUFSIZ]; 5359242Ssam 5369242Ssam buf[0] = '\01'; /* error indicator */ 53713554Ssam (void) sprintf(buf + 1, "rlogind: %s.\r\n", msg); 5389242Ssam (void) write(f, buf, strlen(buf)); 5399242Ssam exit(1); 5409242Ssam } 5419242Ssam 54234424Sbostic fatalperror(f, msg) 5439242Ssam int f; 5449242Ssam char *msg; 5459242Ssam { 5469242Ssam char buf[BUFSIZ]; 54716227Skarels extern int sys_nerr; 5489242Ssam extern char *sys_errlist[]; 5499242Ssam 55018357Ssam if ((unsigned)errno < sys_nerr) 55116227Skarels (void) sprintf(buf, "%s: %s", msg, sys_errlist[errno]); 55216227Skarels else 55316227Skarels (void) sprintf(buf, "%s: Error %d", msg, errno); 5549242Ssam fatal(f, buf); 5559242Ssam } 55636453Skfall 55736453Skfall do_rlogin(host) 55836518Skarels char *host; 55936453Skfall { 56036453Skfall 56136518Skarels getstr(rusername, sizeof(rusername), "remuser too long"); 56236518Skarels getstr(lusername, sizeof(lusername), "locuser too long"); 56336518Skarels getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type too long"); 56436518Skarels 56536518Skarels if (getuid()) 56636453Skfall return(-1); 56736453Skfall pwd = getpwnam(lusername); 56836518Skarels if (pwd == NULL) 56936453Skfall return(-1); 57036453Skfall return(ruserok(host, SUPERUSER(pwd), rusername, lusername)); 57136453Skfall } 57236453Skfall 57336453Skfall 57436518Skarels getstr(buf, cnt, errmsg) 57536518Skarels char *buf; 57636518Skarels int cnt; 57736518Skarels char *errmsg; 57836453Skfall { 57936518Skarels char c; 58036518Skarels 58136453Skfall do { 58236518Skarels if (read(0, &c, 1) != 1) 58336453Skfall exit(1); 58436518Skarels if (--cnt < 0) 58536518Skarels fatal(1, errmsg); 58636453Skfall *buf++ = c; 58736518Skarels } while (c != 0); 58836453Skfall } 58936453Skfall 59036518Skarels extern char **environ; 59136453Skfall 59236519Skarels setup_term(fd) 59336519Skarels int fd; 59436519Skarels { 59536636Skarels struct termios tt; 59636636Skarels register char *cp = index(term+ENVSIZE, '/'); 59736519Skarels char *speed; 59836519Skarels 59936636Skarels tcgetattr(fd, &tt); 60036519Skarels if (cp) { 60136519Skarels *cp++ = '\0'; 60236519Skarels speed = cp; 60336519Skarels cp = index(speed, '/'); 60436519Skarels if (cp) 60536519Skarels *cp++ = '\0'; 60636636Skarels cfsetspeed(&tt, atoi(speed)); 60736519Skarels } 60836636Skarels tt.c_iflag = BRKINT|ICRNL|IXON|ISTRIP|IEXTEN|IMAXBEL; 60936636Skarels tt.c_oflag = OPOST|ONLCR|OXTABS; 61036636Skarels tt.c_lflag = ISIG|ICANON|ECHO; 61136636Skarels tcsetattr(fd, TCSADFLUSH, &tt); 61236519Skarels 61336519Skarels env[0] = term; 61436519Skarels env[1] = 0; 61536519Skarels environ = env; 61636519Skarels } 61736609Skfall 61836636Skarels #ifdef KERBEROS 61936636Skarels #define VERSION_SIZE 9 62036636Skarels 62136609Skfall /* 62236636Skarels * Do the remote kerberos login to the named host with the 62336636Skarels * given inet address 62436636Skarels * 62536636Skarels * Return 0 on valid authorization 62636636Skarels * Return -1 on valid authentication, no authorization 62736636Skarels * Return >0 for error conditions 62836636Skarels */ 62936636Skarels do_krb_login(host, dest, encrypt) 63036636Skarels char *host; 63136636Skarels struct sockaddr_in *dest; 63236636Skarels int encrypt; 63336636Skarels { 63436636Skarels int rc; 63536636Skarels char instance[INST_SZ], version[VERSION_SIZE]; 63636636Skarels long authopts = 0L; /* !mutual */ 63736636Skarels struct sockaddr_in faddr; 63836636Skarels 63936636Skarels if (getuid()) 64036636Skarels return(KFAILURE); 64136636Skarels 64236636Skarels kdata = (AUTH_DAT *) auth_buf; 64336636Skarels ticket = (KTEXT) tick_buf; 64436636Skarels strcpy(instance, "*"); 64536636Skarels 64636636Skarels if (encrypt) { 64736636Skarels rc = sizeof(faddr); 64836636Skarels if (getsockname(0, &faddr, &rc)) 64936636Skarels return(-1); 65036636Skarels authopts = KOPT_DO_MUTUAL; 65136636Skarels rc = krb_recvauth( 65236636Skarels authopts, 0, 65336636Skarels ticket, "rcmd", 65436636Skarels instance, dest, &faddr, 65536636Skarels kdata, "", schedule, version); 65636636Skarels des_set_key(kdata->session, schedule); 65736636Skarels 65836636Skarels } else { 65936636Skarels rc = krb_recvauth( 66036636Skarels authopts, 0, 66136636Skarels ticket, "rcmd", 66236636Skarels instance, dest, (struct sockaddr_in *) 0, 66336636Skarels kdata, "", (bit_64 *) 0, version); 66436636Skarels } 66536636Skarels 66636636Skarels if (rc != KSUCCESS) 66736636Skarels return(rc); 66836636Skarels 66936636Skarels if ((rc = krb_kntoln(kdata, rusername)) != KSUCCESS) 67036636Skarels return(rc); 67136636Skarels 67236636Skarels getstr(lusername, sizeof(lusername), "locuser"); 67336636Skarels /* get the "cmd" in the rcmd protocol */ 67436636Skarels getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type"); 67536636Skarels 67636636Skarels pwd = getpwnam(lusername); 67736636Skarels if (pwd == NULL) 67836636Skarels return(-1); 67936636Skarels 68036636Skarels /* returns nonzero for no access */ 68136636Skarels /* return(ruserok(host, SUPERUSER(pwd), rusername, lusername)); */ 68236636Skarels if (kuserok(kdata,lusername) != 0) 68336636Skarels return(-1); 68436636Skarels 68536636Skarels return(0); 68636636Skarels 68736636Skarels } 68836636Skarels 68936636Skarels #endif /* KERBEROS */ 69036636Skarels 69136636Skarels usage() 69236636Skarels { 69336636Skarels #ifdef KERBEROS 69436636Skarels syslog(LOG_ERR, "usage: rlogind [-k | -v] [-l] [-n]"); 69536636Skarels #else 69636636Skarels syslog(LOG_ERR, "usage: rlogind [-l] [-n]"); 69736636Skarels #endif 69836636Skarels } 69936636Skarels 70036636Skarels /* 70136631Skarels * Check whether host h is in our local domain, 70236631Skarels * as determined by the part of the name following 70336631Skarels * the first '.' in its name and in ours. 70436631Skarels * If either name is unqualified (contains no '.'), 70536631Skarels * assume that the host is local, as it will be 70636631Skarels * interpreted as such. 70736631Skarels */ 70836631Skarels local_domain(h) 70936631Skarels char *h; 71036625Skfall { 71136631Skarels char localhost[MAXHOSTNAMELEN]; 71236631Skarels char *p1, *p2 = index(h, '.'); 71336631Skarels 71436631Skarels (void) gethostname(localhost, sizeof(localhost)); 71536631Skarels p1 = index(localhost, '.'); 71636631Skarels if (p1 == NULL || p2 == NULL || !strcasecmp(p1, p2)) 71736625Skfall return(1); 71836625Skfall return(0); 71936625Skfall } 720