home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / N / TCPIP / NETKIT-B.05 / NETKIT-B / NetKit-B-0.05 / rshd / rshd.c,v < prev    next >
Encoding:
Text File  |  1994-05-23  |  17.3 KB  |  789 lines

  1. head    1.1;
  2. access;
  3. symbols;
  4. locks
  5.     rzsfl:1.1; strict;
  6. comment    @ * @;
  7.  
  8.  
  9. 1.1
  10. date    94.05.23.09.09.44;    author rzsfl;    state Exp;
  11. branches;
  12. next    ;
  13.  
  14.  
  15. desc
  16. @Original
  17. @
  18.  
  19.  
  20. 1.1
  21. log
  22. @Initial revision
  23. @
  24. text
  25. @/*-
  26.  * Copyright (c) 1988, 1989 The Regents of the University of California.
  27.  * All rights reserved.
  28.  *
  29.  * Redistribution and use in source and binary forms, with or without
  30.  * modification, are permitted provided that the following conditions
  31.  * are met:
  32.  * 1. Redistributions of source code must retain the above copyright
  33.  *    notice, this list of conditions and the following disclaimer.
  34.  * 2. Redistributions in binary form must reproduce the above copyright
  35.  *    notice, this list of conditions and the following disclaimer in the
  36.  *    documentation and/or other materials provided with the distribution.
  37.  * 3. All advertising materials mentioning features or use of this software
  38.  *    must display the following acknowledgement:
  39.  *    This product includes software developed by the University of
  40.  *    California, Berkeley and its contributors.
  41.  * 4. Neither the name of the University nor the names of its contributors
  42.  *    may be used to endorse or promote products derived from this software
  43.  *    without specific prior written permission.
  44.  *
  45.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  46.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  47.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  48.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  49.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  50.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  51.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  52.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  53.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  54.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  55.  * SUCH DAMAGE.
  56.  */
  57.  
  58. #ifndef lint
  59. char copyright[] =
  60. "@@(#) Copyright (c) 1988, 1989 The Regents of the University of California.\n\
  61.  All rights reserved.\n";
  62. #endif /* not lint */
  63.  
  64. #ifndef lint
  65. /*static char sccsid[] = "from: @@(#)rshd.c    5.38 (Berkeley) 3/2/91";*/
  66. static char rcsid[] = "$Id: rshd.c,v 1.3 1993/12/23 09:06:01 cgd Exp $";
  67. #endif /* not lint */
  68.  
  69. /*
  70.  * From:
  71.  *    $Source: /b/source/CVS/src/libexec/rshd/rshd.c,v $
  72.  *    $Header: /mit/kerberos/ucb/mit/rshd/RCS/rshd.c,v 
  73.  *        5.2 89/07/31 19:30:04 kfall Exp $
  74.  */
  75.  
  76. /*
  77.  * remote shell server:
  78.  *    [port]\0
  79.  *    remuser\0
  80.  *    locuser\0
  81.  *    command\0
  82.  *    data
  83.  */
  84. #include <sys/param.h>
  85. #include <sys/ioctl.h>
  86. #include <sys/time.h>
  87. #include <fcntl.h>
  88. #include <signal.h>
  89.  
  90. #include <sys/socket.h>
  91. #include <netinet/in.h>
  92. #include <arpa/inet.h>
  93. #include <netdb.h>
  94.  
  95. #include <pwd.h>
  96. #include <syslog.h>
  97. #include <arpa/nameser.h>
  98. #include <resolv.h>
  99. #include <unistd.h>
  100. #include <errno.h>
  101. #include <stdio.h>
  102. #include <stdlib.h>
  103. #include <string.h>
  104. #include <paths.h>
  105.  
  106. int    keepalive = 1;
  107. int    check_all = 0;
  108. int    paranoid = 0;
  109. char    *index(), *rindex(), *strncat();
  110. /*VARARGS1*/
  111. int    error();
  112. int    sent_null;
  113.  
  114. #ifdef    KERBEROS
  115. #include <kerberosIV/des.h>
  116. #include <kerberosIV/krb.h>
  117. #define    VERSION_SIZE    9
  118. #define SECURE_MESSAGE  "This rsh session is using DES encryption for all transmissions.\r\n"
  119. #define    OPTIONS        "alknvxL"
  120. char    authbuf[sizeof(AUTH_DAT)];
  121. char    tickbuf[sizeof(KTEXT_ST)];
  122. int    doencrypt, use_kerberos, vacuous;
  123. Key_schedule    schedule;
  124. #else
  125. #define    OPTIONS    "alnL"
  126. #endif
  127.  
  128. /*ARGSUSED*/
  129. main(argc, argv)
  130.     int argc;
  131.     char **argv;
  132. {
  133.     extern int opterr, optind;
  134.     extern int _check_rhosts_file;
  135.     struct linger linger;
  136.     int ch, on = 1, fromlen;
  137.     struct sockaddr_in from;
  138.  
  139.     openlog("rshd", LOG_PID | LOG_ODELAY, LOG_DAEMON);
  140.  
  141.     opterr = 0;
  142.     while ((ch = getopt(argc, argv, OPTIONS)) != EOF)
  143.         switch (ch) {
  144.         case 'a':
  145.             check_all = 1;
  146.             break;
  147.  
  148.         case 'l':
  149.             _check_rhosts_file = 0;
  150.             break;
  151.  
  152.         case 'n':
  153.             keepalive = 0;
  154.             break;
  155. #ifdef    KERBEROS
  156.         case 'k':
  157.             use_kerberos = 1;
  158.             break;
  159.  
  160.         case 'v':
  161.             vacuous = 1;
  162.             break;
  163.  
  164. #ifdef CRYPT
  165.         case 'x':
  166.             doencrypt = 1;
  167.             break;
  168. #endif
  169. #endif
  170.  
  171.         case 'L':
  172.             paranoid = 1;
  173.             break;
  174.  
  175.         case '?':
  176.         default:
  177.             usage();
  178.             exit(2);
  179.         }
  180.  
  181.     argc -= optind;
  182.     argv += optind;
  183.  
  184. #ifdef    KERBEROS
  185.     if (use_kerberos && vacuous) {
  186.         syslog(LOG_ERR, "only one of -k and -v allowed");
  187.         exit(2);
  188.     }
  189. #ifdef CRYPT
  190.     if (doencrypt && !use_kerberos) {
  191.         syslog(LOG_ERR, "-k is required for -x");
  192.         exit(2);
  193.     }
  194. #endif
  195. #endif
  196.  
  197.     fromlen = sizeof (from);
  198.     if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
  199.         syslog(LOG_ERR, "getpeername: %m");
  200.         _exit(1);
  201.     }
  202.     if (keepalive &&
  203.         setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (char *)&on,
  204.         sizeof(on)) < 0)
  205.         syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
  206.     linger.l_onoff = 1;
  207.     linger.l_linger = 60;            /* XXX */
  208.     if (setsockopt(0, SOL_SOCKET, SO_LINGER, (char *)&linger,
  209.         sizeof (linger)) < 0)
  210.         syslog(LOG_WARNING, "setsockopt (SO_LINGER): %m");
  211.     doit(&from);
  212. }
  213.  
  214. char    username[20] = "USER=";
  215. char    homedir[64] = "HOME=";
  216. char    shell[64] = "SHELL=";
  217. char    path[100] = "PATH=";
  218. char    *envinit[] =
  219.         {homedir, shell, path, username, 0};
  220. char    **environ;
  221.  
  222. doit(fromp)
  223.     struct sockaddr_in *fromp;
  224. {
  225.     char cmdbuf[NCARGS+1], *cp;
  226.     char locuser[16], remuser[16];
  227.     struct passwd *pwd;
  228.     int s;
  229.     struct hostent *hp;
  230.     char *hostname, *errorstr = NULL, *errorhost;
  231.     u_short port;
  232.     int pv[2], pid, cc;
  233.     int nfd;
  234.     fd_set ready, readfrom;
  235.     char buf[BUFSIZ], sig;
  236.     int one = 1;
  237.     char remotehost[2 * MAXHOSTNAMELEN + 1];
  238.  
  239. #ifdef    KERBEROS
  240.     AUTH_DAT    *kdata = (AUTH_DAT *) NULL;
  241.     KTEXT        ticket = (KTEXT) NULL;
  242.     char        instance[INST_SZ], version[VERSION_SIZE];
  243.     struct        sockaddr_in    fromaddr;
  244.     int        rc;
  245.     long        authopts;
  246.     int        pv1[2], pv2[2];
  247.     fd_set        wready, writeto;
  248.  
  249.     fromaddr = *fromp;
  250. #endif
  251.  
  252.     (void) signal(SIGINT, SIG_DFL);
  253.     (void) signal(SIGQUIT, SIG_DFL);
  254.     (void) signal(SIGTERM, SIG_DFL);
  255. #ifdef DEBUG
  256.     { int t = open(_PATH_TTY, 2);
  257.       if (t >= 0) {
  258.         ioctl(t, TIOCNOTTY, (char *)0);
  259.         (void) close(t);
  260.       }
  261.     }
  262. #endif
  263.     fromp->sin_port = ntohs((u_short)fromp->sin_port);
  264.     if (fromp->sin_family != AF_INET) {
  265.         syslog(LOG_ERR, "malformed \"from\" address (af %d)\n",
  266.             fromp->sin_family);
  267.         exit(1);
  268.     }
  269. #ifdef IP_OPTIONS
  270.       {
  271.     u_char optbuf[BUFSIZ/3], *cp;
  272.     char lbuf[BUFSIZ], *lp;
  273.     int optsize = sizeof(optbuf), ipproto;
  274.     struct protoent *ip;
  275.  
  276.     if ((ip = getprotobyname("ip")) != NULL)
  277.         ipproto = ip->p_proto;
  278.     else
  279.         ipproto = IPPROTO_IP;
  280.     if (!getsockopt(0, ipproto, IP_OPTIONS, (char *)optbuf, &optsize) &&
  281.         optsize != 0) {
  282.         lp = lbuf;
  283.         for (cp = optbuf; optsize > 0; cp++, optsize--, lp += 3)
  284.             sprintf(lp, " %2.2x", *cp);
  285.         syslog(LOG_NOTICE,
  286.             "Connection received from %s using IP options (ignored):%s",
  287.             inet_ntoa(fromp->sin_addr), lbuf);
  288.         if (setsockopt(0, ipproto, IP_OPTIONS,
  289.             (char *)NULL, optsize) != 0) {
  290.             syslog(LOG_ERR, "setsockopt IP_OPTIONS NULL: %m");
  291.             exit(1);
  292.         }
  293.     }
  294.       }
  295. #endif
  296.  
  297. #ifdef    KERBEROS
  298.     if (!use_kerberos)
  299. #endif
  300.         if (fromp->sin_port >= IPPORT_RESERVED ||
  301.             fromp->sin_port < IPPORT_RESERVED/2) {
  302.             syslog(LOG_NOTICE|LOG_AUTH,
  303.                 "Connection from %s on illegal port",
  304.                 inet_ntoa(fromp->sin_addr));
  305.             exit(1);
  306.         }
  307.  
  308.     (void) alarm(60);
  309.     port = 0;
  310.     for (;;) {
  311.         char c;
  312.         if ((cc = read(0, &c, 1)) != 1) {
  313.             if (cc < 0)
  314.                 syslog(LOG_NOTICE, "read: %m");
  315.             shutdown(0, 1+1);
  316.             exit(1);
  317.         }
  318.         if (c== 0)
  319.             break;
  320.         port = port * 10 + c - '0';
  321.     }
  322.  
  323.     (void) alarm(0);
  324.     if (port != 0) {
  325.         int lport = IPPORT_RESERVED - 1;
  326.         s = rresvport(&lport);
  327.         if (s < 0) {
  328.             syslog(LOG_ERR, "can't get stderr port: %m");
  329.             exit(1);
  330.         }
  331. #ifdef    KERBEROS
  332.         if (!use_kerberos)
  333. #endif
  334.             if (port >= IPPORT_RESERVED) {
  335.                 syslog(LOG_ERR, "2nd port not reserved\n");
  336.                 exit(1);
  337.             }
  338.         fromp->sin_port = htons(port);
  339.         if (connect(s, (struct sockaddr *)fromp, sizeof (*fromp)) < 0) {
  340.             syslog(LOG_INFO, "connect second port: %m");
  341.             exit(1);
  342.         }
  343.     }
  344.  
  345. #ifdef    KERBEROS
  346.     if (vacuous) {
  347.         error("rshd: remote host requires Kerberos authentication\n");
  348.         exit(1);
  349.     }
  350. #endif
  351.  
  352. #ifdef notdef
  353.     /* from inetd, socket is already on 0, 1, 2 */
  354.     dup2(f, 0);
  355.     dup2(f, 1);
  356.     dup2(f, 2);
  357. #endif
  358.     hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof (struct in_addr),
  359.         fromp->sin_family);
  360.     if (hp) {
  361.         /*
  362.          * If name returned by gethostbyaddr is in our domain,
  363.          * attempt to verify that we haven't been fooled by someone
  364.          * in a remote net; look up the name and check that this
  365.          * address corresponds to the name.
  366.          */
  367.         hostname = hp->h_name;
  368. #ifdef    KERBEROS
  369.         if (!use_kerberos)
  370. #endif
  371.         if (check_all || local_domain(hp->h_name)) {
  372.             strncpy(remotehost, hp->h_name, sizeof(remotehost) - 1);
  373.             remotehost[sizeof(remotehost) - 1] = 0;
  374.             errorhost = remotehost;
  375. #ifdef    RES_DNSRCH
  376.             _res.options &= ~RES_DNSRCH;
  377. #endif
  378.             hp = gethostbyname(remotehost);
  379.             if (hp == NULL) {
  380.                 syslog(LOG_INFO,
  381.                     "Couldn't look up address for %s",
  382.                     remotehost);
  383.                 errorstr =
  384.                 "Couldn't look up address for your host (%s)\n";
  385.                 hostname = inet_ntoa(fromp->sin_addr);
  386.             } else for (; ; hp->h_addr_list++) {
  387.                 if (hp->h_addr_list[0] == NULL) {
  388.                     syslog(LOG_NOTICE,
  389.                       "Host addr %s not listed for host %s",
  390.                         inet_ntoa(fromp->sin_addr),
  391.                         hp->h_name);
  392.                     errorstr =
  393.                         "Host address mismatch for %s\n";
  394.                     hostname = inet_ntoa(fromp->sin_addr);
  395.                     break;
  396.                 }
  397.                 if (!bcmp(hp->h_addr_list[0],
  398.                     (caddr_t)&fromp->sin_addr,
  399.                     sizeof(fromp->sin_addr))) {
  400.                     hostname = hp->h_name;
  401.                     break;
  402.                 }
  403.             }
  404.         }
  405.     } else
  406.         errorhost = hostname = inet_ntoa(fromp->sin_addr);
  407.  
  408. #ifdef    KERBEROS
  409.     if (use_kerberos) {
  410.         kdata = (AUTH_DAT *) authbuf;
  411.         ticket = (KTEXT) tickbuf;
  412.         authopts = 0L;
  413.         strcpy(instance, "*");
  414.         version[VERSION_SIZE - 1] = '\0';
  415. #ifdef CRYPT
  416.         if (doencrypt) {
  417.             struct sockaddr_in local_addr;
  418.             rc = sizeof(local_addr);
  419.             if (getsockname(0, (struct sockaddr *)&local_addr,
  420.                 &rc) < 0) {
  421.                 syslog(LOG_ERR, "getsockname: %m");
  422.                 error("rlogind: getsockname: %m");
  423.                 exit(1);
  424.             }
  425.             authopts = KOPT_DO_MUTUAL;
  426.             rc = krb_recvauth(authopts, 0, ticket,
  427.                 "rcmd", instance, &fromaddr,
  428.                 &local_addr, kdata, "", schedule,
  429.                 version);
  430.             des_set_key(kdata->session, schedule);
  431.         } else
  432. #endif
  433.             rc = krb_recvauth(authopts, 0, ticket, "rcmd",
  434.                 instance, &fromaddr,
  435.                 (struct sockaddr_in *) 0,
  436.                 kdata, "", (bit_64 *) 0, version);
  437.         if (rc != KSUCCESS) {
  438.             error("Kerberos authentication failure: %s\n",
  439.                   krb_err_txt[rc]);
  440.             exit(1);
  441.         }
  442.     } else
  443. #endif
  444.         getstr(remuser, sizeof(remuser), "remuser");
  445.  
  446.     getstr(locuser, sizeof(locuser), "locuser");
  447.     getstr(cmdbuf, sizeof(cmdbuf), "command");
  448.     setpwent();
  449.     pwd = getpwnam(locuser);
  450.     if (pwd == NULL) {
  451.         if (errorstr == NULL)
  452.             errorstr = "Login incorrect.\n";
  453.         goto fail;
  454.     }
  455.     if (chdir(pwd->pw_dir) < 0) {
  456.         (void) chdir("/");
  457. #ifdef notdef
  458.         error("No remote directory.\n");
  459.         exit(1);
  460. #endif
  461.     }
  462.  
  463. #ifdef    KERBEROS
  464.     if (use_kerberos) {
  465.         if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0') {
  466.             if (kuserok(kdata, locuser) != 0) {
  467.                 syslog(LOG_NOTICE|LOG_AUTH,
  468.                     "Kerberos shell denied to %s.%s@@%s on %s as %s: cmd='%s'; %s",
  469.                     kdata->pname, kdata->pinst, kdata->prealm,
  470.                                 hostname, locuser, cmdbuf, errorstr);
  471.                 error("Permission denied.\n");
  472.                 exit(1);
  473.             }
  474.         }
  475.     } else
  476. #endif
  477.  
  478.         if (errorstr ||
  479.             pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' &&
  480.             ruserok(hostname, pwd->pw_uid == 0, remuser, locuser) < 0) {
  481. fail:
  482.             if (errorstr == NULL)
  483.                 errorstr = "Permission denied.\n";
  484.  
  485.             /* log the (failed) rsh request, if paranoid */
  486.             if (paranoid || pwd->pw_uid == 0)
  487.                     syslog(LOG_INFO|LOG_AUTH,
  488.                     "rsh denied to %s@@%s as %s: cmd='%s'; %s",
  489.                     remuser, hostname, locuser, cmdbuf,
  490.                     errorstr);
  491.  
  492.             error(errorstr, errorhost);
  493.             exit(1);
  494.         }
  495.  
  496.     if (pwd->pw_uid && !access(_PATH_NOLOGIN, F_OK)) {
  497.         error("Logins currently disabled.\n");
  498.         exit(1);
  499.     }
  500.  
  501.     (void) write(2, "\0", 1);
  502.     sent_null = 1;
  503.  
  504.     if (port) {
  505.         if (pipe(pv) < 0) {
  506.             error("Can't make pipe.\n");
  507.             exit(1);
  508.         }
  509. #ifdef CRYPT
  510. #ifdef KERBEROS
  511.         if (doencrypt) {
  512.             if (pipe(pv1) < 0) {
  513.                 error("Can't make 2nd pipe.\n");
  514.                 exit(1);
  515.             }
  516.             if (pipe(pv2) < 0) {
  517.                 error("Can't make 3rd pipe.\n");
  518.                 exit(1);
  519.             }
  520.         }
  521. #endif
  522. #endif
  523.         pid = fork();
  524.         if (pid == -1)  {
  525.             error("Can't fork; try again.\n");
  526.             exit(1);
  527.         }
  528.         if (pid) {
  529. #ifdef CRYPT
  530. #ifdef KERBEROS
  531.             if (doencrypt) {
  532.                 static char msg[] = SECURE_MESSAGE;
  533.                 (void) close(pv1[1]);
  534.                 (void) close(pv2[1]);
  535.                 des_write(s, msg, sizeof(msg));
  536.  
  537.             } else
  538. #endif
  539. #endif
  540.             {
  541.                 (void) close(0); (void) close(1);
  542.             }
  543.             (void) close(2); (void) close(pv[1]);
  544.  
  545.             FD_ZERO(&readfrom);
  546.             FD_SET(s, &readfrom);
  547.             FD_SET(pv[0], &readfrom);
  548.             if (pv[0] > s)
  549.                 nfd = pv[0];
  550.             else
  551.                 nfd = s;
  552. #ifdef CRYPT
  553. #ifdef KERBEROS
  554.             if (doencrypt) {
  555.                 FD_ZERO(&writeto);
  556.                 FD_SET(pv2[0], &writeto);
  557.                 FD_SET(pv1[0], &readfrom);
  558.  
  559.                 nfd = MAX(nfd, pv2[0]);
  560.                 nfd = MAX(nfd, pv1[0]);
  561.             } else
  562. #endif
  563. #endif
  564.                 ioctl(pv[0], FIONBIO, (char *)&one);
  565.  
  566.             /* should set s nbio! */
  567.             nfd++;
  568.             do {
  569.                 ready = readfrom;
  570. #ifdef CRYPT
  571. #ifdef KERBEROS
  572.                 if (doencrypt) {
  573.                     wready = writeto;
  574.                     if (select(nfd, &ready,
  575.                         &wready, (fd_set *) 0,
  576.                         (struct timeval *) 0) < 0)
  577.                         break;
  578.                 } else
  579. #endif
  580. #endif
  581.                     if (select(nfd, &ready, (fd_set *)0,
  582.                       (fd_set *)0, (struct timeval *)0) < 0)
  583.                         break;
  584.                 if (FD_ISSET(s, &ready)) {
  585.                     int    ret;
  586. #ifdef CRYPT
  587. #ifdef KERBEROS
  588.                     if (doencrypt)
  589.                         ret = des_read(s, &sig, 1);
  590.                     else
  591. #endif
  592. #endif
  593.                         ret = read(s, &sig, 1);
  594.                     if (ret <= 0)
  595.                         FD_CLR(s, &readfrom);
  596.                     else
  597.                         killpg(pid, sig);
  598.                 }
  599.                 if (FD_ISSET(pv[0], &ready)) {
  600.                     errno = 0;
  601.                     cc = read(pv[0], buf, sizeof(buf));
  602.                     if (cc <= 0) {
  603.                         shutdown(s, 1+1);
  604.                         FD_CLR(pv[0], &readfrom);
  605.                     } else {
  606. #ifdef CRYPT
  607. #ifdef KERBEROS
  608.                         if (doencrypt)
  609.                             (void)
  610.                               des_write(s, buf, cc);
  611.                         else
  612. #endif
  613. #endif
  614.                             (void)
  615.                               write(s, buf, cc);
  616.                     }
  617.                 }
  618. #ifdef CRYPT
  619. #ifdef KERBEROS
  620.                 if (doencrypt && FD_ISSET(pv1[0], &ready)) {
  621.                     errno = 0;
  622.                     cc = read(pv1[0], buf, sizeof(buf));
  623.                     if (cc <= 0) {
  624.                         shutdown(pv1[0], 1+1);
  625.                         FD_CLR(pv1[0], &readfrom);
  626.                     } else
  627.                         (void) des_write(1, buf, cc);
  628.                 }
  629.  
  630.                 if (doencrypt && FD_ISSET(pv2[0], &wready)) {
  631.                     errno = 0;
  632.                     cc = des_read(0, buf, sizeof(buf));
  633.                     if (cc <= 0) {
  634.                         shutdown(pv2[0], 1+1);
  635.                         FD_CLR(pv2[0], &writeto);
  636.                     } else
  637.                         (void) write(pv2[0], buf, cc);
  638.                 }
  639. #endif
  640. #endif
  641.  
  642.             } while (FD_ISSET(s, &readfrom) ||
  643. #ifdef CRYPT
  644. #ifdef KERBEROS
  645.                 (doencrypt && FD_ISSET(pv1[0], &readfrom)) ||
  646. #endif
  647. #endif
  648.                 FD_ISSET(pv[0], &readfrom));
  649.             exit(0);
  650.         }
  651.         setpgrp(0, getpid());
  652.         (void) close(s); (void) close(pv[0]);
  653. #ifdef CRYPT
  654. #ifdef KERBEROS
  655.         if (doencrypt) {
  656.             close(pv1[0]); close(pv2[0]);
  657.             dup2(pv1[1], 1);
  658.             dup2(pv2[1], 0);
  659.             close(pv1[1]);
  660.             close(pv2[1]);
  661.         }
  662. #endif
  663. #endif
  664.         dup2(pv[1], 2);
  665.         close(pv[1]);
  666.     }
  667.     if (*pwd->pw_shell == '\0')
  668.         pwd->pw_shell = _PATH_BSHELL;
  669. #if    BSD > 43
  670.     if (setlogin(pwd->pw_name) < 0)
  671.         syslog(LOG_ERR, "setlogin() failed: %m");
  672. #endif
  673.     (void) setgid((gid_t)pwd->pw_gid);
  674.     initgroups(pwd->pw_name, pwd->pw_gid);
  675.     (void) setuid((uid_t)pwd->pw_uid);
  676.     environ = envinit;
  677.     strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
  678.     strcat(path, _PATH_DEFPATH);
  679.     strncat(shell, pwd->pw_shell, sizeof(shell)-7);
  680.     strncat(username, pwd->pw_name, sizeof(username)-6);
  681.     cp = rindex(pwd->pw_shell, '/');
  682.     if (cp)
  683.         cp++;
  684.     else
  685.         cp = pwd->pw_shell;
  686.     endpwent();
  687.     if (paranoid || pwd->pw_uid == 0) {
  688. #ifdef    KERBEROS
  689.         if (use_kerberos)
  690.             syslog(LOG_INFO|LOG_AUTH,
  691.                         "Kerberos shell from %s.%s@@%s on %s as %s: cmd='%s'",
  692.                         kdata->pname, kdata->pinst, kdata->prealm,
  693.                         hostname, locuser, cmdbuf);
  694.         else
  695. #endif
  696.             syslog(LOG_INFO|LOG_AUTH, "%s@@%s as %s: cmd='%s'",
  697.             remuser, hostname, locuser, cmdbuf);
  698.     }
  699.  
  700.  
  701.     execl(pwd->pw_shell, cp, "-c", cmdbuf, 0);
  702.     perror(pwd->pw_shell);
  703.     exit(1);
  704. }
  705.  
  706. /*
  707.  * Report error to client.
  708.  * Note: can't be used until second socket has connected
  709.  * to client, or older clients will hang waiting
  710.  * for that connection first.
  711.  */
  712. /*VARARGS1*/
  713. error(fmt, a1, a2, a3)
  714.     char *fmt;
  715.     int a1, a2, a3;
  716. {
  717.     char buf[BUFSIZ], *bp = buf;
  718.  
  719.     if (sent_null == 0)
  720.         *bp++ = 1;
  721.     (void) sprintf(bp, fmt, a1, a2, a3);
  722.     (void) write(2, buf, strlen(buf));
  723. }
  724.  
  725. getstr(buf, cnt, err)
  726.     char *buf;
  727.     int cnt;
  728.     char *err;
  729. {
  730.     char c;
  731.  
  732.     do {
  733.         if (read(0, &c, 1) != 1)
  734.             exit(1);
  735.         *buf++ = c;
  736.         if (--cnt == 0) {
  737.             error("%s too long\n", err);
  738.             exit(1);
  739.         }
  740.     } while (c != 0);
  741. }
  742.  
  743. /*
  744.  * Check whether host h is in our local domain,
  745.  * defined as sharing the last two components of the domain part,
  746.  * or the entire domain part if the local domain has only one component.
  747.  * If either name is unqualified (contains no '.'),
  748.  * assume that the host is local, as it will be
  749.  * interpreted as such.
  750.  */
  751. local_domain(h)
  752.     char *h;
  753. {
  754.     char localhost[MAXHOSTNAMELEN];
  755.     char *p1, *p2, *topdomain();
  756.  
  757.     localhost[0] = 0;
  758.     (void) gethostname(localhost, sizeof(localhost));
  759.     p1 = topdomain(localhost);
  760.     p2 = topdomain(h);
  761.     if (p1 == NULL || p2 == NULL || !strcasecmp(p1, p2))
  762.         return(1);
  763.     return(0);
  764. }
  765.  
  766. char *
  767. topdomain(h)
  768.     char *h;
  769. {
  770.     register char *p;
  771.     char *maybe = NULL;
  772.     int dots = 0;
  773.  
  774.     for (p = h + strlen(h); p >= h; p--) {
  775.         if (*p == '.') {
  776.             if (++dots == 2)
  777.                 return (p);
  778.             maybe = p;
  779.         }
  780.     }
  781.     return (maybe);
  782. }
  783.  
  784. usage()
  785. {
  786.     syslog(LOG_ERR, "usage: rshd [-%s]", OPTIONS);
  787. }
  788. @
  789.