diff options
Diffstat (limited to 'crypto/kerberosIV/appl/bsd/rlogind.c')
-rw-r--r-- | crypto/kerberosIV/appl/bsd/rlogind.c | 970 |
1 files changed, 0 insertions, 970 deletions
diff --git a/crypto/kerberosIV/appl/bsd/rlogind.c b/crypto/kerberosIV/appl/bsd/rlogind.c deleted file mode 100644 index eae2dd6..0000000 --- a/crypto/kerberosIV/appl/bsd/rlogind.c +++ /dev/null @@ -1,970 +0,0 @@ -/*- - * Copyright (c) 1983, 1988, 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * remote login server: - * \0 - * remuser\0 - * locuser\0 - * terminal_type/speed\0 - * data - */ - -#include "bsd_locl.h" - -RCSID("$Id: rlogind.c,v 1.109.2.2 2000/06/23 02:37:06 assar Exp $"); - -extern int __check_rhosts_file; - -char *INSECURE_MESSAGE = -"\r\n*** Connection not encrypted! Communication may be eavesdropped. ***" -"\r\n*** Use telnet or rlogin -x instead! ***\r\n"; - -#ifndef NOENCRYPTION -char *SECURE_MESSAGE = -"This rlogin session is using DES encryption for all transmissions.\r\n"; -#else -#define SECURE_MESSAGE INSECURE_MESSAGE -#endif - -AUTH_DAT *kdata; -KTEXT ticket; -u_char auth_buf[sizeof(AUTH_DAT)]; -u_char tick_buf[sizeof(KTEXT_ST)]; -Key_schedule schedule; -int doencrypt, retval, use_kerberos, vacuous; - -#define ARGSTR "Daip:lnkvxL:" - -char *env[2]; -#define NMAX 30 -char lusername[NMAX+1], rusername[NMAX+1]; -static char term[64] = "TERM="; -#define ENVSIZE (sizeof("TERM=")-1) /* skip null for concatenation */ -int keepalive = 1; -int check_all = 0; -int no_delay = 0; - -struct passwd *pwd; - -static const char *new_login = _PATH_LOGIN; - -static void doit (int, struct sockaddr_in *); -static int control (int, char *, int); -static void protocol (int, int); -static RETSIGTYPE cleanup (int); -void fatal (int, const char *, int); -static int do_rlogin (struct sockaddr_in *); -static void setup_term (int); -static int do_krb_login (struct sockaddr_in *); -static void usage (void); - -static int -readstream(int p, char *ibuf, int bufsize) -{ -#ifndef HAVE_GETMSG - return read(p, ibuf, bufsize); -#else - static int flowison = -1; /* current state of flow: -1 is unknown */ - static struct strbuf strbufc, strbufd; - static unsigned char ctlbuf[BUFSIZ]; - static int use_read = 1; - - int flags = 0; - int ret; - struct termios tsp; - - struct iocblk ip; - char vstop, vstart; - int ixon; - int newflow; - - if (use_read) - { - ret = read(p, ibuf, bufsize); - if (ret < 0 && errno == EBADMSG) - use_read = 0; - else - return ret; - } - - strbufc.maxlen = BUFSIZ; - strbufc.buf = (char *)ctlbuf; - strbufd.maxlen = bufsize-1; - strbufd.len = 0; - strbufd.buf = ibuf+1; - ibuf[0] = 0; - - ret = getmsg(p, &strbufc, &strbufd, &flags); - if (ret < 0) /* error of some sort -- probably EAGAIN */ - return(-1); - - if (strbufc.len <= 0 || ctlbuf[0] == M_DATA) { - /* data message */ - if (strbufd.len > 0) { /* real data */ - return(strbufd.len + 1); /* count header char */ - } else { - /* nothing there */ - errno = EAGAIN; - return(-1); - } - } - - /* - * It's a control message. Return 1, to look at the flag we set - */ - - switch (ctlbuf[0]) { - case M_FLUSH: - if (ibuf[1] & FLUSHW) - ibuf[0] = TIOCPKT_FLUSHWRITE; - return(1); - - case M_IOCTL: - memcpy(&ip, (ibuf+1), sizeof(ip)); - - switch (ip.ioc_cmd) { -#ifdef TCSETS - case TCSETS: - case TCSETSW: - case TCSETSF: - memcpy(&tsp, - (ibuf+1 + sizeof(struct iocblk)), - sizeof(tsp)); - vstop = tsp.c_cc[VSTOP]; - vstart = tsp.c_cc[VSTART]; - ixon = tsp.c_iflag & IXON; - break; -#endif - default: - errno = EAGAIN; - return(-1); - } - - newflow = (ixon && (vstart == 021) && (vstop == 023)) ? 1 : 0; - if (newflow != flowison) { /* it's a change */ - flowison = newflow; - ibuf[0] = newflow ? TIOCPKT_DOSTOP : TIOCPKT_NOSTOP; - return(1); - } - } - - /* nothing worth doing anything about */ - errno = EAGAIN; - return(-1); -#endif -} - -#ifdef HAVE_UTMPX_H -static int -rlogind_logout(const char *line) -{ - struct utmpx utmpx, *utxp; - int ret = 1; - - setutxent (); - memset(&utmpx, 0, sizeof(utmpx)); - utmpx.ut_type = USER_PROCESS; - strncpy(utmpx.ut_line, line, sizeof(utmpx.ut_line)); - utxp = getutxline(&utmpx); - if (utxp) { - utxp->ut_user[0] = '\0'; - utxp->ut_type = DEAD_PROCESS; -#ifdef HAVE_STRUCT_UTMPX_UT_EXIT -#ifdef _STRUCT___EXIT_STATUS - utxp->ut_exit.__e_termination = 0; - utxp->ut_exit.__e_exit = 0; -#elif defined(__osf__) /* XXX */ - utxp->ut_exit.ut_termination = 0; - utxp->ut_exit.ut_exit = 0; -#else - utxp->ut_exit.e_termination = 0; - utxp->ut_exit.e_exit = 0; -#endif -#endif - gettimeofday(&utxp->ut_tv, NULL); - pututxline(utxp); -#ifdef WTMPX_FILE - updwtmpx(WTMPX_FILE, utxp); -#else - ret = 0; -#endif - } - endutxent(); - return ret; -} -#else -static int -rlogind_logout(const char *line) -{ - FILE *fp; - struct utmp ut; - int rval; - - if (!(fp = fopen(_PATH_UTMP, "r+"))) - return(0); - rval = 1; - while (fread(&ut, sizeof(struct utmp), 1, fp) == 1) { - if (!ut.ut_name[0] || - strncmp(ut.ut_line, line, sizeof(ut.ut_line))) - continue; - memset(ut.ut_name, 0, sizeof(ut.ut_name)); -#ifdef HAVE_STRUCT_UTMP_UT_HOST - memset(ut.ut_host, 0, sizeof(ut.ut_host)); -#endif -#ifdef HAVE_STRUCT_UTMP_UT_TYPE - ut.ut_type = DEAD_PROCESS; -#endif -#ifdef HAVE_STRUCT_UTMP_UT_EXIT -#ifdef _STRUCT___EXIT_STATUS - ut.ut_exit.__e_termination = 0; - ut.ut_exit.__e_exit = 0; -#elif defined(__osf__) /* XXX */ - ut.ut_exit.ut_termination = 0; - ut.ut_exit.ut_exit = 0; -#else - ut.ut_exit.e_termination = 0; - ut.ut_exit.e_exit = 0; -#endif -#endif - ut.ut_time = time(NULL); - fseek(fp, (long)-sizeof(struct utmp), SEEK_CUR); - fwrite(&ut, sizeof(struct utmp), 1, fp); - fseek(fp, (long)0, SEEK_CUR); - rval = 0; - } - fclose(fp); - return(rval); -} -#endif - -#ifndef HAVE_LOGWTMP -static void -logwtmp(const char *line, const char *name, const char *host) -{ - struct utmp ut; - struct stat buf; - int fd; - - memset (&ut, 0, sizeof(ut)); - if ((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0)) < 0) - return; - if (!fstat(fd, &buf)) { - strncpy(ut.ut_line, line, sizeof(ut.ut_line)); - strncpy(ut.ut_name, name, sizeof(ut.ut_name)); -#ifdef HAVE_STRUCT_UTMP_UT_ID - strncpy(ut.ut_id, make_id((char *)line), sizeof(ut.ut_id)); -#endif -#ifdef HAVE_STRUCT_UTMP_UT_HOST - strncpy(ut.ut_host, host, sizeof(ut.ut_host)); -#endif -#ifdef HAVE_STRUCT_UTMP_UT_PID - ut.ut_pid = getpid(); -#endif -#ifdef HAVE_STRUCT_UTMP_UT_TYPE - if(name[0]) - ut.ut_type = USER_PROCESS; - else - ut.ut_type = DEAD_PROCESS; -#endif - ut.ut_time = time(NULL); - if (write(fd, &ut, sizeof(struct utmp)) != - sizeof(struct utmp)) - ftruncate(fd, buf.st_size); - } - close(fd); -} -#endif - -int -main(int argc, char **argv) -{ - struct sockaddr_in from; - int ch, fromlen, on; - int interactive = 0; - int portnum = 0; - - set_progname(argv[0]); - - openlog("rlogind", LOG_PID | LOG_CONS, LOG_AUTH); - - opterr = 0; - while ((ch = getopt(argc, argv, ARGSTR)) != -1) - switch (ch) { - case 'D': - no_delay = 1; - break; - case 'a': - break; - case 'i': - interactive = 1; - break; - case 'p': - portnum = htons(atoi(optarg)); - break; - case 'l': - __check_rhosts_file = 0; - break; - case 'n': - keepalive = 0; - break; - case 'k': - use_kerberos = 1; - break; - case 'v': - vacuous = 1; - break; - case 'x': - doencrypt = 1; - break; - case 'L': - new_login = optarg; - break; - case '?': - default: - usage(); - break; - } - argc -= optind; - argv += optind; - - if (use_kerberos && vacuous) { - usage(); - fatal(STDERR_FILENO, "only one of -k and -v allowed", 0); - } - if (interactive) { - if(portnum == 0) - portnum = get_login_port (use_kerberos, doencrypt); - mini_inetd (portnum); - } - - fromlen = sizeof (from); - if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { - syslog(LOG_ERR,"Can't get peer name of remote host: %m"); - fatal(STDERR_FILENO, "Can't get peer name of remote host", 1); - } - on = 1; -#ifdef HAVE_SETSOCKOPT -#ifdef SO_KEEPALIVE - if (keepalive && - setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, - sizeof (on)) < 0) - syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); -#endif -#ifdef TCP_NODELAY - if (no_delay && - setsockopt(0, IPPROTO_TCP, TCP_NODELAY, (void *)&on, - sizeof(on)) < 0) - syslog(LOG_WARNING, "setsockopt (TCP_NODELAY): %m"); -#endif - -#ifdef IP_TOS - on = IPTOS_LOWDELAY; - if (setsockopt(0, IPPROTO_IP, IP_TOS, (void *)&on, sizeof(int)) < 0) - syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); -#endif -#endif /* HAVE_SETSOCKOPT */ - doit(0, &from); - return 0; -} - -int child; -int netf; -char line[MaxPathLen]; -int confirmed; - -struct winsize win = { 0, 0, 0, 0 }; - - -static void -doit(int f, struct sockaddr_in *fromp) -{ - int master, pid, on = 1; - int authenticated = 0; - char hostname[2 * MaxHostNameLen + 1]; - char c; - - alarm(60); - read(f, &c, 1); - - if (c != 0) - exit(1); - if (vacuous) - fatal(f, "Remote host requires Kerberos authentication", 0); - - alarm(0); - inaddr2str (fromp->sin_addr, hostname, sizeof(hostname)); - - if (use_kerberos) { - retval = do_krb_login(fromp); - if (retval == 0) - authenticated++; - else if (retval > 0) - fatal(f, krb_get_err_text(retval), 0); - write(f, &c, 1); - confirmed = 1; /* we sent the null! */ - } else { - fromp->sin_port = ntohs((u_short)fromp->sin_port); - if (fromp->sin_family != AF_INET || - fromp->sin_port >= IPPORT_RESERVED || - fromp->sin_port < IPPORT_RESERVED/2) { - syslog(LOG_NOTICE, "Connection from %s on illegal port", - inet_ntoa(fromp->sin_addr)); - fatal(f, "Permission denied", 0); - } - ip_options_and_die (0, fromp); - if (do_rlogin(fromp) == 0) - authenticated++; - } - if (confirmed == 0) { - write(f, "", 1); - confirmed = 1; /* we sent the null! */ - } -#ifndef NOENCRYPTION - if (doencrypt) - des_enc_write(f, SECURE_MESSAGE, - strlen(SECURE_MESSAGE), - schedule, &kdata->session); - else -#endif - write(f, INSECURE_MESSAGE, strlen(INSECURE_MESSAGE)); - netf = f; - -#ifdef HAVE_FORKPTY - pid = forkpty(&master, line, NULL, NULL); -#else - pid = forkpty_truncate(&master, line, sizeof(line), NULL, NULL); -#endif - if (pid < 0) { - if (errno == ENOENT) - fatal(f, "Out of ptys", 0); - else - fatal(f, "Forkpty", 1); - } - if (pid == 0) { - if (f > 2) /* f should always be 0, but... */ - close(f); - setup_term(0); - if (lusername[0] == '-'){ - syslog(LOG_ERR, "tried to pass user \"%s\" to login", - lusername); - fatal(STDERR_FILENO, "invalid user", 0); - } - if (authenticated) { - if (use_kerberos && (pwd->pw_uid == 0)) - syslog(LOG_INFO|LOG_AUTH, - "ROOT Kerberos login from %s on %s\n", - krb_unparse_name_long(kdata->pname, - kdata->pinst, - kdata->prealm), - hostname); - - execl(new_login, "login", "-p", - "-h", hostname, "-f", "--", lusername, 0); - } else if (use_kerberos) { - fprintf(stderr, "User `%s' is not authorized to login as `%s'!\n", - krb_unparse_name_long(kdata->pname, - kdata->pinst, - kdata->prealm), - lusername); - exit(1); - } else - execl(new_login, "login", "-p", - "-h", hostname, "--", lusername, 0); - fatal(STDERR_FILENO, new_login, 1); - /*NOTREACHED*/ - } - /* - * If encrypted, don't turn on NBIO or the des read/write - * routines will croak. - */ - - if (!doencrypt) - ioctl(f, FIONBIO, &on); - ioctl(master, FIONBIO, &on); - ioctl(master, TIOCPKT, &on); -#ifdef SIGTSTP - signal(SIGTSTP, SIG_IGN); -#endif - signal(SIGCHLD, cleanup); - setsid(); - protocol(f, master); - signal(SIGCHLD, SIG_IGN); - cleanup(0); -} - -const char magic[2] = { 0377, 0377 }; - -/* - * Handle a "control" request (signaled by magic being present) - * in the data stream. For now, we are only willing to handle - * window size changes. - */ -static int -control(int master, char *cp, int n) -{ - struct winsize w; - char *p; - u_int32_t tmp; - - if (n < 4 + 4 * sizeof (u_int16_t) || cp[2] != 's' || cp[3] != 's') - return (0); -#ifdef TIOCSWINSZ - p = cp + 4; - p += krb_get_int(p, &tmp, 2, 0); - w.ws_row = tmp; - p += krb_get_int(p, &tmp, 2, 0); - w.ws_col = tmp; - - p += krb_get_int(p, &tmp, 2, 0); -#ifdef HAVE_WS_XPIXEL - w.ws_xpixel = tmp; -#endif - p += krb_get_int(p, &tmp, 2, 0); -#ifdef HAVE_WS_YPIXEL - w.ws_ypixel = tmp; -#endif - ioctl(master, TIOCSWINSZ, &w); -#endif - return p - cp; -} - -static -void -send_oob(int fd, char c) -{ - static char last_oob = 0xFF; - -#if (SunOS >= 50) || defined(__hpux) - /* - * PSoriasis and HP-UX always send TIOCPKT_DOSTOP at startup so we - * can avoid sending OOB data and thus not break on Linux by merging - * TIOCPKT_DOSTOP into the first TIOCPKT_WINDOW. - */ - static int oob_kludge = 2; - if (oob_kludge == 2) - { - oob_kludge--; /* First time send nothing */ - return; - } - else if (oob_kludge == 1) - { - oob_kludge--; /* Second time merge TIOCPKT_WINDOW */ - c |= TIOCPKT_WINDOW; - } -#endif - -#define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP)) - c = pkcontrol(c); - /* Multiple OOB data breaks on Linux, avoid it when possible. */ - if (c != last_oob) - send(fd, &c, 1, MSG_OOB); - last_oob = c; -} - -/* - * rlogin "protocol" machine. - */ -static void -protocol(int f, int master) -{ - char pibuf[1024+1], fibuf[1024], *pbp, *fbp; - int pcc = 0, fcc = 0; - int cc, nfd, n; - char cntl; - unsigned char oob_queue = 0; - -#ifdef SIGTTOU - /* - * Must ignore SIGTTOU, otherwise we'll stop - * when we try and set slave pty's window shape - * (our controlling tty is the master pty). - */ - signal(SIGTTOU, SIG_IGN); -#endif - - send_oob(f, TIOCPKT_WINDOW); /* indicate new rlogin */ - - if (f > master) - nfd = f + 1; - else - nfd = master + 1; - if (nfd > FD_SETSIZE) { - syslog(LOG_ERR, "select mask too small, increase FD_SETSIZE"); - fatal(f, "internal error (select mask too small)", 0); - } - for (;;) { - fd_set ibits, obits, ebits, *omask; - - FD_ZERO(&ebits); - FD_ZERO(&ibits); - FD_ZERO(&obits); - omask = (fd_set *)NULL; - if (fcc) { - FD_SET(master, &obits); - omask = &obits; - } else - FD_SET(f, &ibits); - if (pcc >= 0) { - if (pcc) { - FD_SET(f, &obits); - omask = &obits; - } else - FD_SET(master, &ibits); - } - FD_SET(master, &ebits); - if ((n = select(nfd, &ibits, omask, &ebits, 0)) < 0) { - if (errno == EINTR) - continue; - fatal(f, "select", 1); - } - if (n == 0) { - /* shouldn't happen... */ - sleep(5); - continue; - } - if (FD_ISSET(master, &ebits)) { - cc = readstream(master, &cntl, 1); - if (cc == 1 && pkcontrol(cntl)) { -#if 0 /* Kludge around */ - send_oob(f, cntl); -#endif - oob_queue = cntl; - if (cntl & TIOCPKT_FLUSHWRITE) { - pcc = 0; - FD_CLR(master, &ibits); - } - } - } - if (FD_ISSET(f, &ibits)) { -#ifndef NOENCRYPTION - if (doencrypt) - fcc = des_enc_read(f, fibuf, - sizeof(fibuf), - schedule, &kdata->session); - else -#endif - fcc = read(f, fibuf, sizeof(fibuf)); - if (fcc < 0 && errno == EWOULDBLOCK) - fcc = 0; - else { - char *cp; - int left, n; - - if (fcc <= 0) - break; - fbp = fibuf; - - top: - for (cp = fibuf; cp < fibuf+fcc-1; cp++) - if (cp[0] == magic[0] && - cp[1] == magic[1]) { - left = fcc - (cp-fibuf); - n = control(master, cp, left); - if (n) { - left -= n; - if (left > 0) - memmove(cp, cp+n, left); - fcc -= n; - goto top; /* n^2 */ - } - } - FD_SET(master, &obits); /* try write */ - } - } - - if (FD_ISSET(master, &obits) && fcc > 0) { - cc = write(master, fbp, fcc); - if (cc > 0) { - fcc -= cc; - fbp += cc; - } - } - - if (FD_ISSET(master, &ibits)) { - pcc = readstream(master, pibuf, sizeof (pibuf)); - pbp = pibuf; - if (pcc < 0 && errno == EWOULDBLOCK) - pcc = 0; - else if (pcc <= 0) - break; - else if (pibuf[0] == 0) { - pbp++, pcc--; - if (!doencrypt) - FD_SET(f, &obits); /* try write */ - } else { - if (pkcontrol(pibuf[0])) { - oob_queue = pibuf[0]; -#if 0 /* Kludge around */ - send_oob(f, pibuf[0]); -#endif - } - pcc = 0; - } - } - if ((FD_ISSET(f, &obits)) && pcc > 0) { -#ifndef NOENCRYPTION - if (doencrypt) - cc = des_enc_write(f, pbp, pcc, schedule, &kdata->session); - else -#endif - cc = write(f, pbp, pcc); - if (cc < 0 && errno == EWOULDBLOCK) { - /* - * This happens when we try write after read - * from p, but some old kernels balk at large - * writes even when select returns true. - */ - if (!FD_ISSET(master, &ibits)) - sleep(5); - continue; - } - if (cc > 0) { - pcc -= cc; - pbp += cc; - /* Only send urg data when normal data - * has just been sent. - * Linux has deep problems with more - * than one byte of OOB data. - */ - if (oob_queue) { - send_oob (f, oob_queue); - oob_queue = 0; - } - } - } - } -} - -static RETSIGTYPE -cleanup(int signo) -{ - char *p = clean_ttyname (line); - - if (rlogind_logout(p) == 0) - logwtmp(p, "", ""); - chmod(line, 0666); - chown(line, 0, 0); - *p = 'p'; - chmod(line, 0666); - chown(line, 0, 0); - shutdown(netf, 2); - signal(SIGHUP, SIG_IGN); -#ifdef HAVE_VHANGUP - vhangup(); -#endif /* HAVE_VHANGUP */ - exit(1); -} - -void -fatal(int f, const char *msg, int syserr) -{ - int len; - char buf[BUFSIZ], *bp = buf; - - /* - * Prepend binary one to message if we haven't sent - * the magic null as confirmation. - */ - if (!confirmed) - *bp++ = '\01'; /* error indicator */ - if (syserr) - snprintf(bp, sizeof(buf) - (bp - buf), - "rlogind: %s: %s.\r\n", - msg, strerror(errno)); - else - snprintf(bp, sizeof(buf) - (bp - buf), - "rlogind: %s.\r\n", msg); - len = strlen(bp); -#ifndef NOENCRYPTION - if (doencrypt) - des_enc_write(f, buf, bp + len - buf, schedule, &kdata->session); - else -#endif - write(f, buf, bp + len - buf); - exit(1); -} - -static void -xgetstr(char *buf, int cnt, char *errmsg) -{ - char c; - - do { - if (read(0, &c, 1) != 1) - exit(1); - if (--cnt < 0) - fatal(STDOUT_FILENO, errmsg, 0); - *buf++ = c; - } while (c != 0); -} - -static int -do_rlogin(struct sockaddr_in *dest) -{ - xgetstr(rusername, sizeof(rusername), "remuser too long"); - xgetstr(lusername, sizeof(lusername), "locuser too long"); - xgetstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type too long"); - - pwd = k_getpwnam(lusername); - if (pwd == NULL) - return (-1); - if (pwd->pw_uid == 0 && strcmp("root", lusername) != 0) - { - syslog(LOG_ALERT, "NIS attack, user %s has uid 0", lusername); - return (-1); - } - return (iruserok(dest->sin_addr.s_addr, - (pwd->pw_uid == 0), - rusername, - lusername)); -} - -static void -setup_term(int fd) -{ - char *cp = strchr(term+ENVSIZE, '/'); - char *speed; - struct termios tt; - - tcgetattr(fd, &tt); - if (cp) { - int s; - - *cp++ = '\0'; - speed = cp; - cp = strchr(speed, '/'); - if (cp) - *cp++ = '\0'; - s = int2speed_t (atoi (speed)); - if (s > 0) { - cfsetospeed (&tt, s); - cfsetispeed (&tt, s); - } - } - - tt.c_iflag &= ~INPCK; - tt.c_iflag |= ICRNL|IXON; - tt.c_oflag |= OPOST|ONLCR; -#ifdef TAB3 - tt.c_oflag |= TAB3; -#endif /* TAB3 */ -#ifdef ONLRET - tt.c_oflag &= ~ONLRET; -#endif /* ONLRET */ - tt.c_lflag |= (ECHO|ECHOE|ECHOK|ISIG|ICANON); - tt.c_cflag &= ~PARENB; - tt.c_cflag |= CS8; - tt.c_cc[VMIN] = 1; - tt.c_cc[VTIME] = 0; - tt.c_cc[VEOF] = CEOF; - tcsetattr(fd, TCSAFLUSH, &tt); - - env[0] = term; - env[1] = 0; - environ = env; -} - -#define VERSION_SIZE 9 - -/* - * Do the remote kerberos login to the named host with the - * given inet address - * - * Return 0 on valid authorization - * Return -1 on valid authentication, no authorization - * Return >0 for error conditions - */ -static int -do_krb_login(struct sockaddr_in *dest) -{ - int rc; - char instance[INST_SZ], version[VERSION_SIZE]; - long authopts = 0L; /* !mutual */ - struct sockaddr_in faddr; - - kdata = (AUTH_DAT *) auth_buf; - ticket = (KTEXT) tick_buf; - - k_getsockinst(0, instance, sizeof(instance)); - - if (doencrypt) { - rc = sizeof(faddr); - if (getsockname(0, (struct sockaddr *)&faddr, &rc)) - return (-1); - authopts = KOPT_DO_MUTUAL; - rc = krb_recvauth( - authopts, 0, - ticket, "rcmd", - instance, dest, &faddr, - kdata, "", schedule, version); - des_set_key(&kdata->session, schedule); - - } else - rc = krb_recvauth( - authopts, 0, - ticket, "rcmd", - instance, dest, (struct sockaddr_in *) 0, - kdata, "", 0, version); - - if (rc != KSUCCESS) - return (rc); - - xgetstr(lusername, sizeof(lusername), "locuser"); - /* get the "cmd" in the rcmd protocol */ - xgetstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type"); - - pwd = k_getpwnam(lusername); - if (pwd == NULL) - return (-1); - if (pwd->pw_uid == 0 && strcmp("root", lusername) != 0) - { - syslog(LOG_ALERT, "NIS attack, user %s has uid 0", lusername); - return (-1); - } - - /* returns nonzero for no access */ - if (kuserok(kdata, lusername) != 0) - return (-1); - - return (0); - -} - -static void -usage(void) -{ - syslog(LOG_ERR, - "usage: rlogind [-Dailn] [-p port] [-x] [-L login] [-k | -v]"); - exit(1); -} |