home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / inetutils-1.2-src.tgz / tar.out / fsf / inetutils / rlogind / rlogind.c < prev   
C/C++ Source or Header  |  1996-09-28  |  17KB  |  799 lines

  1. /*-
  2.  * Copyright (c) 1983, 1988, 1989, 1993
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char copyright[] =
  36. "@(#) Copyright (c) 1983, 1988, 1989, 1993\n\
  37.     The Regents of the University of California.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. static char sccsid[] = "@(#)rlogind.c    8.2 (Berkeley) 4/28/95";
  42. #endif /* not lint */
  43.  
  44. /*
  45.  * remote login server:
  46.  *    \0
  47.  *    remuser\0
  48.  *    locuser\0
  49.  *    terminal_type/speed\0
  50.  *    data
  51.  */
  52.  
  53. #ifdef HAVE_CONFIG_H
  54. #include <config.h>
  55. #endif
  56.  
  57. #define    FD_SETSIZE    16        /* don't need many bits for select */
  58. #include <sys/param.h>
  59. #include <sys/stat.h>
  60. #include <sys/ioctl.h>
  61. #include <signal.h>
  62. #include <termios.h>
  63. #ifdef HAVE_FD_SET_MACROS_IN_SYS_TIME_H
  64. #include <sys/time.h>
  65. #endif
  66.  
  67. #include <sys/socket.h>
  68. #include <netinet/in.h>
  69. #ifdef HAVE_NETINET_IN_SYSTM_H
  70. #include <netinet/in_systm.h>
  71. #endif
  72. #ifdef HAVE_NETINET_IP_H
  73. #include <netinet/ip.h>
  74. #endif
  75. #include <arpa/inet.h>
  76. #include <netdb.h>
  77.  
  78. #include <pwd.h>
  79. #include <syslog.h>
  80. #include <errno.h>
  81. #include <stdio.h>
  82. #include <unistd.h>
  83. #include <stdlib.h>
  84. #include <string.h>
  85. #include <getopt.h>
  86.  
  87. #ifndef TIOCPKT_WINDOW
  88. #define TIOCPKT_WINDOW 0x80
  89. #endif
  90.  
  91. /* `defaults' for tty settings.  */
  92. #ifndef TTYDEF_IFLAG
  93. #define    TTYDEF_IFLAG    (BRKINT | ISTRIP | ICRNL | IMAXBEL | IXON | IXANY)
  94. #endif
  95. #ifndef TTYDEF_OFLAG
  96. #ifndef OXTABS
  97. #define OXTABS 0
  98. #endif
  99. #define TTYDEF_OFLAG    (OPOST | ONLCR | OXTABS)
  100. #endif
  101. #ifndef TTYDEF_LFLAG
  102. #define TTYDEF_LFLAG    (ECHO | ICANON | ISIG | IEXTEN | ECHOE|ECHOKE|ECHOCTL)
  103. #endif
  104.  
  105. #ifdef    KERBEROS
  106. #include <kerberosIV/des.h>
  107. #include <kerberosIV/krb.h>
  108. #define    SECURE_MESSAGE "This rlogin session is using DES encryption for all transmissions.\r\n"
  109.  
  110. AUTH_DAT    *kdata;
  111. KTEXT        ticket;
  112. u_char        auth_buf[sizeof(AUTH_DAT)];
  113. u_char        tick_buf[sizeof(KTEXT_ST)];
  114. Key_schedule    schedule;
  115. int        doencrypt, retval, use_kerberos, vacuous;
  116.  
  117. #define        ARGSTR            "alnkvx"
  118. #else
  119. #define        ARGSTR            "aln"
  120. #endif    /* KERBEROS */
  121.  
  122. char    *env[2];
  123. #define    NMAX 30
  124. char    lusername[NMAX+1], rusername[NMAX+1];
  125. static    char term[64] = "TERM=";
  126. #define    ENVSIZE    (sizeof("TERM=")-1)    /* skip null for concatenation */
  127. int    keepalive = 1;
  128. int    check_all = 0;
  129.  
  130. struct    passwd *pwd;
  131.  
  132. void    doit __P((int, struct sockaddr_in *));
  133. int    control __P((int, char *, int));
  134. void    protocol __P((int, int));
  135. void    cleanup __P((int));
  136. void    fatal __P((int, char *, int));
  137. int    do_rlogin __P((struct sockaddr_in *));
  138. void    getstr __P((char *, int, char *));
  139. void    setup_term __P((int));
  140. int    do_krb_login __P((struct sockaddr_in *));
  141. void    usage __P((void));
  142. int    local_domain __P((char *));
  143. char    *topdomain __P((char *));
  144.  
  145. int
  146. main(argc, argv)
  147.     int argc;
  148.     char *argv[];
  149. {
  150.     extern int __check_rhosts_file;
  151.     struct sockaddr_in from;
  152.     int ch, fromlen, on;
  153.  
  154.     openlog("rlogind", LOG_PID | LOG_CONS, LOG_AUTH);
  155.  
  156.     opterr = 0;
  157.     while ((ch = getopt(argc, argv, ARGSTR)) != EOF)
  158.         switch (ch) {
  159.         case 'a':
  160.             check_all = 1;
  161.             break;
  162.         case 'l':
  163.             __check_rhosts_file = 0;
  164.             break;
  165.         case 'n':
  166.             keepalive = 0;
  167.             break;
  168. #ifdef KERBEROS
  169.         case 'k':
  170.             use_kerberos = 1;
  171.             break;
  172.         case 'v':
  173.             vacuous = 1;
  174.             break;
  175. #ifdef CRYPT
  176.         case 'x':
  177.             doencrypt = 1;
  178.             break;
  179. #endif
  180. #endif
  181.         case '?':
  182.         default:
  183.             usage();
  184.             break;
  185.         }
  186.     argc -= optind;
  187.     argv += optind;
  188.  
  189. #ifdef    KERBEROS
  190.     if (use_kerberos && vacuous) {
  191.         usage();
  192.         fatal(STDERR_FILENO, "only one of -k and -v allowed", 0);
  193.     }
  194. #endif
  195.     fromlen = sizeof (from);
  196.     if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
  197.         syslog(LOG_ERR,"Can't get peer name of remote host: %m");
  198.         fatal(STDERR_FILENO, "Can't get peer name of remote host", 1);
  199.     }
  200.  
  201.     on = 1;
  202.     if (keepalive &&
  203.         setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0)
  204.         syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
  205.  
  206. #if defined (IP_TOS) && defined (IPPROTO_IP) && defined (IPTOS_LOWDELAY)
  207.     on = IPTOS_LOWDELAY;
  208.     if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
  209.         syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
  210. #endif
  211.  
  212.     doit(0, &from);
  213. }
  214.  
  215. int    child;
  216. int    netf;
  217. char    line[1024];        /* XXX */
  218. int    confirmed;
  219.  
  220. struct winsize win = { 0, 0, 0, 0 };
  221.  
  222.  
  223. void
  224. doit(f, fromp)
  225.     int f;
  226.     struct sockaddr_in *fromp;
  227. {
  228.     int master, pid, on = 1;
  229.     int authenticated = 0;
  230.     register struct hostent *hp;
  231.     char *hostname, *raw_hostname;
  232.     char c;
  233.  
  234.     alarm(60);
  235.     read(f, &c, 1);
  236.  
  237.     if (c != 0)
  238.         exit(1);
  239. #ifdef    KERBEROS
  240.     if (vacuous)
  241.         fatal(f, "Remote host requires Kerberos authentication", 0);
  242. #endif
  243.  
  244.     alarm(0);
  245.     fromp->sin_port = ntohs((u_short)fromp->sin_port);
  246.     hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof(struct in_addr),
  247.         fromp->sin_family);
  248.     if (hp)
  249.         raw_hostname = hp->h_name;
  250.     else
  251.         raw_hostname = inet_ntoa(fromp->sin_addr);
  252.     hostname = malloc (strlen (raw_hostname) + 1);
  253.     if (! hostname)
  254.         fatal (f, "Out of memory", 0);
  255.     strcpy (hostname, raw_hostname);
  256.  
  257. #ifdef    KERBEROS
  258.     if (use_kerberos) {
  259.         retval = do_krb_login(fromp);
  260.         if (retval == 0)
  261.             authenticated++;
  262.         else if (retval > 0)
  263.             fatal(f, krb_err_txt[retval], 0);
  264.         write(f, &c, 1);
  265.         confirmed = 1;        /* we sent the null! */
  266.     } else
  267. #endif
  268.     {
  269.         if (fromp->sin_family != AF_INET ||
  270.             fromp->sin_port >= IPPORT_RESERVED ||
  271.             fromp->sin_port < IPPORT_RESERVED/2) {
  272.             syslog(LOG_NOTICE, "Connection from %s on illegal port",
  273.                 inet_ntoa(fromp->sin_addr));
  274.             fatal(f, "Permission denied", 0);
  275.         }
  276. #ifdef IP_OPTIONS
  277.         {
  278.         u_char optbuf[BUFSIZ/3], *cp;
  279.         char lbuf[BUFSIZ], *lp;
  280.         int optsize = sizeof(optbuf), ipproto;
  281.         struct protoent *ip;
  282.  
  283.         if ((ip = getprotobyname("ip")) != NULL)
  284.             ipproto = ip->p_proto;
  285.         else
  286.             ipproto = IPPROTO_IP;
  287.         if (getsockopt(0, ipproto, IP_OPTIONS, (char *)optbuf,
  288.             &optsize) == 0 && optsize != 0) {
  289.             lp = lbuf;
  290.             for (cp = optbuf; optsize > 0; cp++, optsize--, lp += 3)
  291.                 sprintf(lp, " %2.2x", *cp);
  292.             syslog(LOG_NOTICE,
  293.                 "Connection received using IP options (ignored):%s",
  294.                 lbuf);
  295.             if (setsockopt(0, ipproto, IP_OPTIONS,
  296.                 (char *)NULL, optsize) != 0) {
  297.                 syslog(LOG_ERR,
  298.                     "setsockopt IP_OPTIONS NULL: %m");
  299.                 exit(1);
  300.             }
  301.         }
  302.         }
  303. #endif
  304.         if (do_rlogin(fromp) == 0)
  305.             authenticated++;
  306.     }
  307.     if (confirmed == 0) {
  308.         write(f, "", 1);
  309.         confirmed = 1;        /* we sent the null! */
  310.     }
  311. #ifdef    KERBEROS
  312. #ifdef    CRYPT
  313.     if (doencrypt)
  314.         (void) des_write(f, SECURE_MESSAGE, sizeof(SECURE_MESSAGE) - 1);
  315. #endif
  316. #endif
  317.     netf = f;
  318.  
  319.     pid = forkpty(&master, line, NULL, &win);
  320.     if (pid < 0) {
  321.         if (errno == ENOENT)
  322.             fatal(f, "Out of ptys", 0);
  323.         else
  324.             fatal(f, "Forkpty", 1);
  325.     }
  326.     if (pid == 0) {
  327.         if (f > 2)    /* f should always be 0, but... */
  328.             (void) close(f);
  329.         setup_term(0);
  330.         if (authenticated) {
  331. #ifdef    KERBEROS
  332.             if (use_kerberos && (pwd->pw_uid == 0))
  333.                 syslog(LOG_INFO|LOG_AUTH,
  334.                     "ROOT Kerberos login from %s.%s@%s on %s\n",
  335.                     kdata->pname, kdata->pinst, kdata->prealm,
  336.                     hostname);
  337. #endif
  338.  
  339.             execle(PATH_LOGIN, "login", "-p",
  340.                 "-h", hostname, "-f", "--", lusername, NULL, env);
  341.         } else
  342.             execle(PATH_LOGIN, "login", "-p",
  343.                 "-h", hostname, "--", lusername, NULL, env);
  344.         fatal(STDERR_FILENO, PATH_LOGIN, 1);
  345.         /*NOTREACHED*/
  346.     }
  347. #ifdef    CRYPT
  348. #ifdef    KERBEROS
  349.     /*
  350.      * If encrypted, don't turn on NBIO or the des read/write
  351.      * routines will croak.
  352.      */
  353.  
  354.     if (!doencrypt)
  355. #endif
  356. #endif
  357.         ioctl(f, FIONBIO, &on);
  358.     ioctl(master, FIONBIO, &on);
  359.     ioctl(master, TIOCPKT, &on);
  360.     signal(SIGCHLD, cleanup);
  361.     protocol(f, master);
  362.     signal(SIGCHLD, SIG_IGN);
  363.     cleanup(0);
  364. }
  365.  
  366. char    magic[2] = { 0377, 0377 };
  367. char    oobdata[] = {TIOCPKT_WINDOW};
  368.  
  369. /*
  370.  * Handle a "control" request (signaled by magic being present)
  371.  * in the data stream.  For now, we are only willing to handle
  372.  * window size changes.
  373.  */
  374. int
  375. control(pty, cp, n)
  376.     int pty;
  377.     char *cp;
  378.     int n;
  379. {
  380.     struct winsize w;
  381.  
  382.     if (n < 4+sizeof (w) || cp[2] != 's' || cp[3] != 's')
  383.         return (0);
  384.     oobdata[0] &= ~TIOCPKT_WINDOW;    /* we know he heard */
  385.     memmove(&w, cp+4, sizeof(w));
  386.     w.ws_row = ntohs(w.ws_row);
  387.     w.ws_col = ntohs(w.ws_col);
  388.     w.ws_xpixel = ntohs(w.ws_xpixel);
  389.     w.ws_ypixel = ntohs(w.ws_ypixel);
  390.     (void)ioctl(pty, TIOCSWINSZ, &w);
  391.     return (4+sizeof (w));
  392. }
  393.  
  394. /*
  395.  * rlogin "protocol" machine.
  396.  */
  397. void
  398. protocol(f, p)
  399.     register int f, p;
  400. {
  401.     char pibuf[1024+1], fibuf[1024], *pbp, *fbp;
  402.     register pcc = 0, fcc = 0;
  403.     int cc, nfd, n;
  404.     char cntl;
  405.  
  406.     /*
  407.      * Must ignore SIGTTOU, otherwise we'll stop
  408.      * when we try and set slave pty's window shape
  409.      * (our controlling tty is the master pty).
  410.      */
  411.     (void) signal(SIGTTOU, SIG_IGN);
  412.     send(f, oobdata, 1, MSG_OOB);    /* indicate new rlogin */
  413.     if (f > p)
  414.         nfd = f + 1;
  415.     else
  416.         nfd = p + 1;
  417.     if (nfd > FD_SETSIZE) {
  418.         syslog(LOG_ERR, "select mask too small, increase FD_SETSIZE");
  419.         fatal(f, "internal error (select mask too small)", 0);
  420.     }
  421.     for (;;) {
  422.         fd_set ibits, obits, ebits, *omask;
  423.  
  424.         FD_ZERO(&ebits);
  425.         FD_ZERO(&ibits);
  426.         FD_ZERO(&obits);
  427.         omask = (fd_set *)NULL;
  428.         if (fcc) {
  429.             FD_SET(p, &obits);
  430.             omask = &obits;
  431.         } else
  432.             FD_SET(f, &ibits);
  433.         if (pcc >= 0)
  434.             if (pcc) {
  435.                 FD_SET(f, &obits);
  436.                 omask = &obits;
  437.             } else
  438.                 FD_SET(p, &ibits);
  439.         FD_SET(p, &ebits);
  440.         if ((n = select(nfd, &ibits, omask, &ebits, 0)) < 0) {
  441.             if (errno == EINTR)
  442.                 continue;
  443.             fatal(f, "select", 1);
  444.         }
  445.         if (n == 0) {
  446.             /* shouldn't happen... */
  447.             sleep(5);
  448.             continue;
  449.         }
  450. #define    pkcontrol(c)    ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))
  451.         if (FD_ISSET(p, &ebits)) {
  452.             cc = read(p, &cntl, 1);
  453.             if (cc == 1 && pkcontrol(cntl)) {
  454.                 cntl |= oobdata[0];
  455.                 send(f, &cntl, 1, MSG_OOB);
  456.                 if (cntl & TIOCPKT_FLUSHWRITE) {
  457.                     pcc = 0;
  458.                     FD_CLR(p, &ibits);
  459.                 }
  460.             }
  461.         }
  462.         if (FD_ISSET(f, &ibits)) {
  463. #ifdef    CRYPT
  464. #ifdef    KERBEROS
  465.             if (doencrypt)
  466.                 fcc = des_read(f, fibuf, sizeof(fibuf));
  467.             else
  468. #endif
  469. #endif
  470.                 fcc = read(f, fibuf, sizeof(fibuf));
  471.             if (fcc < 0 && errno == EWOULDBLOCK)
  472.                 fcc = 0;
  473.             else {
  474.                 register char *cp;
  475.                 int left, n;
  476.  
  477.                 if (fcc <= 0)
  478.                     break;
  479.                 fbp = fibuf;
  480.  
  481.             top:
  482.                 for (cp = fibuf; cp < fibuf+fcc-1; cp++)
  483.                     if (cp[0] == magic[0] &&
  484.                         cp[1] == magic[1]) {
  485.                         left = fcc - (cp-fibuf);
  486.                         n = control(p, cp, left);
  487.                         if (n) {
  488.                             left -= n;
  489.                             if (left > 0)
  490.                                 bcopy(cp+n, cp, left);
  491.                             fcc -= n;
  492.                             goto top; /* n^2 */
  493.                         }
  494.                     }
  495.                 FD_SET(p, &obits);        /* try write */
  496.             }
  497.         }
  498.  
  499.         if (FD_ISSET(p, &obits) && fcc > 0) {
  500.             cc = write(p, fbp, fcc);
  501.             if (cc > 0) {
  502.                 fcc -= cc;
  503.                 fbp += cc;
  504.             }
  505.         }
  506.  
  507.         if (FD_ISSET(p, &ibits)) {
  508.             pcc = read(p, pibuf, sizeof (pibuf));
  509.             pbp = pibuf;
  510.             if (pcc < 0 && errno == EWOULDBLOCK)
  511.                 pcc = 0;
  512.             else if (pcc <= 0)
  513.                 break;
  514.             else if (pibuf[0] == 0) {
  515.                 pbp++, pcc--;
  516. #ifdef    CRYPT
  517. #ifdef    KERBEROS
  518.                 if (!doencrypt)
  519. #endif
  520. #endif
  521.                     FD_SET(f, &obits);    /* try write */
  522.             } else {
  523.                 if (pkcontrol(pibuf[0])) {
  524.                     pibuf[0] |= oobdata[0];
  525.                     send(f, &pibuf[0], 1, MSG_OOB);
  526.                 }
  527.                 pcc = 0;
  528.             }
  529.         }
  530.         if ((FD_ISSET(f, &obits)) && pcc > 0) {
  531. #ifdef    CRYPT
  532. #ifdef    KERBEROS
  533.             if (doencrypt)
  534.                 cc = des_write(f, pbp, pcc);
  535.             else
  536. #endif
  537. #endif
  538.                 cc = write(f, pbp, pcc);
  539.             if (cc < 0 && errno == EWOULDBLOCK) {
  540.                 /*
  541.                  * This happens when we try write after read
  542.                  * from p, but some old kernels balk at large
  543.                  * writes even when select returns true.
  544.                  */
  545.                 if (!FD_ISSET(p, &ibits))
  546.                     sleep(5);
  547.                 continue;
  548.             }
  549.             if (cc > 0) {
  550.                 pcc -= cc;
  551.                 pbp += cc;
  552.             }
  553.         }
  554.     }
  555. }
  556.  
  557. void
  558. cleanup(signo)
  559.     int signo;
  560. {
  561.     char *p;
  562.  
  563.     p = line + sizeof(PATH_DEV) - 1;
  564.     if (logout(p))
  565.         logwtmp(p, "", "");
  566.     (void)chmod(line, 0666);
  567.     (void)chown(line, 0, 0);
  568.     *p = 'p';
  569.     (void)chmod(line, 0666);
  570.     (void)chown(line, 0, 0);
  571.     shutdown(netf, 2);
  572.     exit(1);
  573. }
  574.  
  575. void
  576. fatal(f, msg, syserr)
  577.     int f;
  578.     char *msg;
  579.     int syserr;
  580. {
  581.     int len;
  582.     char buf[BUFSIZ], *bp = buf;
  583.  
  584.     /*
  585.      * Prepend binary one to message if we haven't sent
  586.      * the magic null as confirmation.
  587.      */
  588.     if (!confirmed)
  589.         *bp++ = '\01';        /* error indicator */
  590.     if (syserr)
  591.         sprintf(bp, "rlogind: %s: %s.\r\n",
  592.             msg, strerror(errno));
  593.     else
  594.         sprintf(bp, "rlogind: %s.\r\n", msg);
  595.     len = strlen (bp);
  596.     (void) write(f, buf, bp + len - buf);
  597.     exit(1);
  598. }
  599.  
  600. int
  601. do_rlogin(dest)
  602.     struct sockaddr_in *dest;
  603. {
  604.     getstr(rusername, sizeof(rusername), "remuser too long");
  605.     getstr(lusername, sizeof(lusername), "locuser too long");
  606.     getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type too long");
  607.  
  608.     pwd = getpwnam(lusername);
  609.     if (pwd == NULL)
  610.         return (-1);
  611.     if (pwd->pw_uid == 0)
  612.         return (-1);
  613.     /* XXX why don't we syslog() failure? */
  614.     return (iruserok(dest->sin_addr.s_addr, 0, rusername, lusername));
  615. }
  616.  
  617. void
  618. getstr(buf, cnt, errmsg)
  619.     char *buf;
  620.     int cnt;
  621.     char *errmsg;
  622. {
  623.     char c;
  624.  
  625.     do {
  626.         if (read(0, &c, 1) != 1)
  627.             exit(1);
  628.         if (--cnt < 0)
  629.             fatal(STDOUT_FILENO, errmsg, 0);
  630.         *buf++ = c;
  631.     } while (c != 0);
  632. }
  633.  
  634. void
  635. setup_term(fd)
  636.     int fd;
  637. {
  638.     register char *cp = index(term+ENVSIZE, '/');
  639.     char *speed;
  640.     struct termios tt;
  641.  
  642. #ifndef notyet
  643.     tcgetattr(fd, &tt);
  644.     if (cp) {
  645.         *cp++ = '\0';
  646.         speed = cp;
  647.         cp = index(speed, '/');
  648.         if (cp)
  649.             *cp++ = '\0';
  650.         cfsetspeed(&tt, atoi(speed));
  651.     }
  652.  
  653.     tt.c_iflag = TTYDEF_IFLAG;
  654.     tt.c_oflag = TTYDEF_OFLAG;
  655.     tt.c_lflag = TTYDEF_LFLAG;
  656.     tcsetattr(fd, TCSAFLUSH, &tt);
  657. #else
  658.     if (cp) {
  659.         *cp++ = '\0';
  660.         speed = cp;
  661.         cp = index(speed, '/');
  662.         if (cp)
  663.             *cp++ = '\0';
  664.         tcgetattr(fd, &tt);
  665.         cfsetspeed(&tt, atoi(speed));
  666.         tcsetattr(fd, TCSAFLUSH, &tt);
  667.     }
  668. #endif
  669.  
  670.     env[0] = term;
  671.     env[1] = 0;
  672. }
  673.  
  674. #ifdef    KERBEROS
  675. #define    VERSION_SIZE    9
  676.  
  677. /*
  678.  * Do the remote kerberos login to the named host with the
  679.  * given inet address
  680.  *
  681.  * Return 0 on valid authorization
  682.  * Return -1 on valid authentication, no authorization
  683.  * Return >0 for error conditions
  684.  */
  685. int
  686. do_krb_login(dest)
  687.     struct sockaddr_in *dest;
  688. {
  689.     int rc;
  690.     char instance[INST_SZ], version[VERSION_SIZE];
  691.     long authopts = 0L;    /* !mutual */
  692.     struct sockaddr_in faddr;
  693.  
  694.     kdata = (AUTH_DAT *) auth_buf;
  695.     ticket = (KTEXT) tick_buf;
  696.  
  697.     instance[0] = '*';
  698.     instance[1] = '\0';
  699.  
  700. #ifdef    CRYPT
  701.     if (doencrypt) {
  702.         rc = sizeof(faddr);
  703.         if (getsockname(0, (struct sockaddr *)&faddr, &rc))
  704.             return (-1);
  705.         authopts = KOPT_DO_MUTUAL;
  706.         rc = krb_recvauth(
  707.             authopts, 0,
  708.             ticket, "rcmd",
  709.             instance, dest, &faddr,
  710.             kdata, "", schedule, version);
  711.          des_set_key(kdata->session, schedule);
  712.  
  713.     } else
  714. #endif
  715.         rc = krb_recvauth(
  716.             authopts, 0,
  717.             ticket, "rcmd",
  718.             instance, dest, (struct sockaddr_in *) 0,
  719.             kdata, "", (bit_64 *) 0, version);
  720.  
  721.     if (rc != KSUCCESS)
  722.         return (rc);
  723.  
  724.     getstr(lusername, sizeof(lusername), "locuser");
  725.     /* get the "cmd" in the rcmd protocol */
  726.     getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type");
  727.  
  728.     pwd = getpwnam(lusername);
  729.     if (pwd == NULL)
  730.         return (-1);
  731.  
  732.     /* returns nonzero for no access */
  733.     if (kuserok(kdata, lusername) != 0)
  734.         return (-1);
  735.     
  736.     return (0);
  737.  
  738. }
  739. #endif /* KERBEROS */
  740.  
  741. void
  742. usage()
  743. {
  744. #ifdef KERBEROS
  745.     syslog(LOG_ERR, "usage: rlogind [-aln] [-k | -v]");
  746. #else
  747.     syslog(LOG_ERR, "usage: rlogind [-aln]");
  748. #endif
  749. }
  750.  
  751. /*
  752.  * Check whether host h is in our local domain,
  753.  * defined as sharing the last two components of the domain part,
  754.  * or the entire domain part if the local domain has only one component.
  755.  * If either name is unqualified (contains no '.'),
  756.  * assume that the host is local, as it will be
  757.  * interpreted as such.
  758.  */
  759. int
  760. local_domain(h)
  761.     char *h;
  762. {
  763.     extern char *localhost ();
  764.     char *hostname = localhost ();
  765.  
  766.     if (! hostname)
  767.         return 0;
  768.     else {
  769.         int is_local = 0;
  770.         char *p1 = topdomain (hostname);
  771.         char *p2 = topdomain (h);
  772.  
  773.         if (p1 == NULL || p2 == NULL || !strcasecmp(p1, p2))
  774.             is_local = 1;
  775.  
  776.         free (hostname);
  777.  
  778.         return is_local;
  779.     }
  780. }
  781.  
  782. char *
  783. topdomain(h)
  784.     char *h;
  785. {
  786.     register char *p;
  787.     char *maybe = NULL;
  788.     int dots = 0;
  789.  
  790.     for (p = h + strlen(h); p >= h; p--) {
  791.         if (*p == '.') {
  792.             if (++dots == 2)
  793.                 return (p);
  794.             maybe = p;
  795.         }
  796.     }
  797.     return (maybe);
  798. }
  799.