home *** CD-ROM | disk | FTP | other *** search
/ Serving the Web / ServingTheWeb1995.disc1of1.iso / linux / slacksrce / d / libc / libc-4.6 / libc-4 / libc-linux / inet / rcmd.c.new < prev    next >
Encoding:
Text File  |  1994-09-18  |  15.3 KB  |  644 lines

  1. /*
  2.  * Copyright (c) 1983, 1993, 1994
  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. #if defined(LIBC_SCCS) && !defined(lint)
  35. static char sccsid[] = "@(#)rcmd.c    8.3 (Berkeley) 3/26/94";
  36. #endif /* LIBC_SCCS and not lint */
  37.  
  38. #include "inetprivate.h"
  39. #include <paths.h>
  40. #include <pwd.h>
  41. #include <sys/file.h>
  42. #include <sys/signal.h>
  43. #include <sys/stat.h>
  44.  
  45. #if NLS
  46. #include "nl_types.h"
  47. #endif
  48.  
  49. #ifdef YP
  50. #include <rpcsvc/ypclnt.h>
  51. extern void setnetgrent(const char *);
  52. extern void endnetgrent(void);
  53. extern int getnetgrent(char **, char **, char **);
  54. static char *nisdomain = NULL;
  55. static int __ichecknetgrouphost(u_long, const char *);
  56. static int _checknetgroupuser(const char *, const char *);
  57. #endif
  58.  
  59. int
  60. rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
  61.     char **ahost;
  62.     u_short rport;
  63.     const char *locuser, *remuser, *cmd;
  64.     int *fd2p;
  65. {
  66.     struct hostent *hp;
  67.     struct sockaddr_in sin, from;
  68.     fd_set reads;
  69. #ifdef _POSIX_SOURCE
  70.     sigset_t set, oset;
  71. #else
  72.     long oldmask;
  73. #endif
  74.     int s, lport, timo;
  75. #ifdef F_SETOWN
  76.     pid_t pid;
  77. #endif
  78.     char c;
  79.  
  80. #if NLS
  81.     libc_nls_init();
  82. #endif
  83.  
  84. #ifdef F_SETOWN
  85.     pid = getpid();
  86. #endif
  87.     hp = gethostbyname(*ahost);
  88.     if (hp == 0) {
  89. #if NLS
  90.         fprintf(stderr, "%s: %s\n", *ahost,
  91.                               catgets(_libc_cat, HerrorListSet,
  92.                       2, "unknown host"));
  93. #else
  94.         fprintf(stderr, "%s: unknown host\n", *ahost);
  95. #endif
  96.         return (-1);
  97.     }
  98.     *ahost = hp->h_name;
  99. #ifdef SIGURG
  100. #ifdef _POSIX_SOURCE
  101.     sigemptyset (&set);
  102.     sigaddset (&set, SIGURG);
  103.     sigprocmask (SIG_BLOCK, &set, &oset);
  104. #else
  105.     oldmask = sigblock(sigmask(SIGURG));
  106. #endif
  107. #endif
  108.     for (timo = 1, lport = IPPORT_RESERVED - 1;;) {
  109.         s = rresvport(&lport);
  110.         if (s < 0) {
  111.             if (errno == EAGAIN)
  112. #if NLS
  113.                 fprintf(stderr, "socket: %s\n",
  114.                     catgets(_libc_cat, NetMiscSet,
  115.                         NetMiscAllPortsInUse,
  116.                         "All ports in use"));
  117. #else
  118.                 fprintf(stderr, "socket: All ports in use\n");
  119. #endif
  120.             else
  121. #if NLS
  122.                 perror(catgets(_libc_cat, NetMiscSet,
  123.                            NetMiscRcmdSocket,
  124.                            "rcmd: socket"));
  125. #else
  126.                 perror("rcmd: socket");
  127. #endif
  128. #ifdef SIGURG
  129. #ifdef _POSIX_SOURCE
  130.              sigprocmask (SIG_SETMASK, &oset,
  131.                 (sigset_t *)NULL);
  132. #else
  133.             sigsetmask(oldmask);
  134. #endif
  135. #endif
  136.             return (-1);
  137.         }
  138. #ifdef F_SETOWN
  139.         fcntl(s, F_SETOWN, pid);
  140. #endif
  141.         sin.sin_family = hp->h_addrtype;
  142.         bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr, hp->h_length);
  143.         sin.sin_port = rport;
  144.         if (connect(s, (struct sockaddr *)&sin, sizeof (sin)) >= 0)
  145.             break;
  146.         (void) close(s);
  147.         if (errno == EADDRINUSE) {
  148.             lport--;
  149.             continue;
  150.         }
  151.         if (errno == ECONNREFUSED && timo <= 16) {
  152.             sleep(timo);
  153.             timo *= 2;
  154.             continue;
  155.         }
  156.         if (hp->h_addr_list[1] != NULL) {
  157.             int oerrno = errno;
  158.  
  159.             fprintf(stderr,
  160. #if NLS
  161.                 "%s %s: ", catgets(_libc_cat, NetMiscSet,
  162.                            NetMiscAllPortsInUse,
  163.                            "connect to address"),
  164.                        inet_ntoa(sin.sin_addr));
  165.  
  166. #else
  167.  
  168.                 "connect to address %s: ", inet_ntoa(sin.sin_addr));
  169. #endif
  170.             errno = oerrno;
  171.             perror(0);
  172.             hp->h_addr_list++;
  173.             bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr,
  174.                 hp->h_length);
  175.  
  176. #if NLS
  177.             fprintf(stderr, catgets(_libc_cat, NetMiscSet,
  178.                         NetMiscTrying,
  179.                         "Trying %s...\n"),
  180. #else
  181.             fprintf(stderr,    "Trying %s...\n",
  182. #endif
  183.                 inet_ntoa(sin.sin_addr));
  184.             continue;
  185.         }
  186.         perror(hp->h_name);
  187. #ifdef SIGURG
  188. #ifdef _POSIX_SOURCE
  189.         sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
  190. #else
  191.         sigsetmask(oldmask);
  192. #endif
  193. #endif
  194.         return (-1);
  195.     }
  196.     lport--;
  197.     if (fd2p == 0) {
  198.         write(s, "", 1);
  199.         lport = 0;
  200.     } else {
  201.         char num[8];
  202.         int s2 = rresvport(&lport), s3;
  203.         int len = sizeof (from);
  204.  
  205.         if (s2 < 0)
  206.             goto bad;
  207.         listen(s2, 1);
  208.         (void) sprintf(num, "%d", lport);
  209.         /* void) snprintf(num, sizeof(num), "%d", lport); XXX */
  210.         if (write(s, num, strlen(num)+1) != strlen(num)+1) {
  211. #if NLS
  212.             perror(catgets(_libc_cat, NetMiscSet,
  213.                        NetMiscSettingUpStderr,
  214.                        "write: setting up stderr"));
  215. #else
  216.             perror("write: setting up stderr");
  217. #endif
  218.             (void) close(s2);
  219.             goto bad;
  220.         }
  221.         FD_ZERO(&reads);
  222.         FD_SET(s, &reads);
  223.         FD_SET(s2, &reads);
  224.         errno = 0;
  225.         if (select(1 + (s > s2 ? s : s2), &reads, 0, 0, 0) < 1 ||
  226.             !FD_ISSET(s2, &reads)) {
  227.             if (errno != 0)
  228. #if NLS
  229.                 perror(catgets(_libc_cat, NetMiscSet,
  230.                            NetMiscSelectSetup,
  231.                            "rcmd: select (setting up stderr)"));
  232. #else
  233.                 perror("rcmd: select (setting up stderr): ");
  234. #endif
  235.             else
  236.                 fprintf(stderr,
  237. #if NLS
  238.                         "%s\n",
  239.                         catgets(_libc_cat, NetMiscSet,
  240.                         NetMiscRcmdProtocolError,
  241.                         "select: protocol failure in circuit setup"));
  242. #else
  243.                     "select: protocol failure in circuit setup.\n");
  244. #endif
  245.             (void)close(s2);
  246.             goto bad;
  247.         }
  248.         s3 = accept(s2, (struct sockaddr *)&from, &len);
  249.         (void) close(s2);
  250.         if (s3 < 0) {
  251. #if NLS
  252.             perror(catgets(_libc_cat, NetMiscSet,
  253.                        NetMiscAccept,
  254.                        "accept"));
  255. #else
  256.             perror("accept");
  257. #endif
  258.             lport = 0;
  259.             goto bad;
  260.         }
  261.         *fd2p = s3;
  262.         from.sin_port = ntohs((u_short)from.sin_port);
  263.         if (from.sin_family != AF_INET ||
  264.             from.sin_port >= IPPORT_RESERVED ||
  265.             from.sin_port < IPPORT_RESERVED / 2) {
  266.             fprintf(stderr,
  267. #if NLS
  268.                 "%s\n",
  269.                 catgets(_libc_cat, NetMiscSet,
  270.                     NetMiscProtocolFailure,
  271.                     "socket: protocol failure in circuit setup."));
  272. #else
  273.                 "socket: protocol failure in circuit setup.\n");
  274. #endif
  275.             goto bad2;
  276.         }
  277.     }
  278.     (void) write(s, locuser, strlen(locuser)+1);
  279.     (void) write(s, remuser, strlen(remuser)+1);
  280.     (void) write(s, cmd, strlen(cmd)+1);
  281.     if (read(s, &c, 1) != 1) {
  282.         perror(*ahost);
  283.         goto bad2;
  284.     }
  285.     if (c != 0) {
  286.         while (read(s, &c, 1) == 1) {
  287.             (void) write(STDERR_FILENO, &c, 1);
  288.             if (c == '\n')
  289.                 break;
  290.         }
  291.         goto bad2;
  292.     }
  293. #ifdef SIGURG
  294. #ifdef _POSIX_SOURCE
  295.     sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
  296. #else
  297.     sigsetmask(oldmask);
  298. #endif
  299. #endif
  300.     return (s);
  301. bad2:
  302.     if (lport)
  303.         (void) close(*fd2p);
  304. bad:
  305.     (void) close(s);
  306. #ifdef SIGURG
  307. #ifdef _POSIX_SOURCE
  308.     sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
  309. #else
  310.     sigsetmask(oldmask);
  311. #endif
  312. #endif
  313.     return (-1);
  314. }
  315.  
  316. int
  317. rresvport(alport)
  318.     int *alport;
  319. {
  320.     struct sockaddr_in sin;
  321.     int s;
  322.  
  323.     sin.sin_family = AF_INET;
  324.     sin.sin_addr.s_addr = INADDR_ANY;
  325.     s = socket(AF_INET, SOCK_STREAM, 0);
  326.     if (s < 0)
  327.         return (-1);
  328.     for (;;) {
  329.         sin.sin_port = htons((u_short)*alport);
  330.         if (bind(s, (struct sockaddr *)&sin, sizeof (sin)) >= 0)
  331.             return (s);
  332.         if (errno != EADDRINUSE) {
  333.             (void) close(s);
  334.             return (-1);
  335.         }
  336.         (*alport)--;
  337.         if (*alport == IPPORT_RESERVED/2) {
  338.             (void) close(s);
  339.             errno = EAGAIN;        /* close */
  340.             return (-1);
  341.         }
  342.     }
  343. }
  344.  
  345. int     __check_rhosts_file = 1;
  346. char    *__rcmd_errstr;
  347.  
  348. int
  349. ruserok(const char *rhost, int superuser, const char *ruser,
  350.     const char *luser)
  351. {
  352.     struct hostent *hp;
  353.     u_long addr;
  354.     char **ap;
  355.  
  356.     if ((hp = gethostbyname(rhost)) == NULL)
  357.         return (-1);
  358.     for (ap = hp->h_addr_list; *ap; ++ap) {
  359.         bcopy(*ap, &addr, sizeof(addr));
  360.         if (iruserok(addr, superuser, ruser, luser) == 0)
  361.             return (0);
  362.     }
  363.     return (-1);
  364. }
  365.  
  366. /*
  367.  * New .rhosts strategy: We are passed an ip address. We spin through
  368.  * hosts.equiv and .rhosts looking for a match. When the .rhosts only
  369.  * has ip addresses, we don't have to trust a nameserver.  When it
  370.  * contains hostnames, we spin through the list of addresses the nameserver
  371.  * gives us and look for a match.
  372.  *
  373.  * Returns 0 if ok, -1 if not ok.
  374.  */
  375. int
  376. iruserok(u_long raddr, int superuser, const char *ruser, const char *luser)
  377. {
  378.     register char *cp;
  379.     struct stat sbuf;
  380.     struct passwd *pwd;
  381.     FILE *hostf;
  382.     uid_t uid;
  383.     int first = 1;
  384.     char pbuf[MAXPATHLEN];
  385.  
  386.     first = 1;
  387.     hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r");
  388. again:
  389.     if (hostf) {
  390.         if (__ivaliduser(hostf, raddr, luser, ruser) == 0) {
  391.             (void) fclose(hostf);
  392.             return(0);
  393.         }
  394.         (void) fclose(hostf);
  395.     }
  396.     if (first == 1 && (__check_rhosts_file || superuser)) {
  397.         first = 0;
  398.         if ((pwd = getpwnam(luser)) == NULL)
  399.             return(-1);
  400.         (void)strcpy(pbuf, pwd->pw_dir);
  401.         (void)strcat(pbuf, "/.rhosts");
  402.  
  403.         /*
  404.          * Change effective uid while opening .rhosts.  If root and
  405.          * reading an NFS mounted file system, can't read files that
  406.          * are protected read/write owner only.
  407.          */
  408.         uid = geteuid();
  409.         (void)seteuid(pwd->pw_uid);
  410.         hostf = fopen(pbuf, "r");
  411.         (void)seteuid(uid);
  412.  
  413.         if (hostf == NULL)
  414.             return(-1);
  415.         /*
  416.          * If not a regular file, or is owned by someone other than
  417.          * user or root or if writeable by anyone but the owner, quit.
  418.          */
  419.         cp = NULL;
  420.         if (lstat(pbuf, &sbuf) < 0)
  421. #if NLS
  422.             cp = catgets(_libc_cat, NetMiscSet,
  423.                      NetMiscRhostLstat,
  424.                      ".rhosts not regular file");
  425. #else
  426.             cp = ".rhosts not regular file";
  427. #endif
  428.         else if (!S_ISREG(sbuf.st_mode))
  429. #if NLS
  430.             cp = catgets(_libc_cat, NetMiscSet,
  431.                      NetMiscRhostNotRegular,
  432.                      ".rhosts not regular file");
  433. #else
  434.             cp = ".rhosts not regular file";
  435. #endif
  436.         else if (fstat(fileno(hostf), &sbuf) < 0)
  437. #if NLS
  438.             cp = catgets(_libc_cat, NetMiscSet,
  439.                      NetMiscRhostFstatFailed,
  440.                      ".rhosts fstat failed");
  441. #else
  442.             cp = ".rhosts fstat failed";
  443. #endif
  444.         else if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid)
  445. #if NLS
  446.             cp = catgets(_libc_cat, NetMiscSet,
  447.                      NetMiscBadRhostsOwner,
  448.                      "bad .rhosts owner");
  449. #else
  450.             cp = "bad .rhosts owner";
  451. #endif
  452.         else if (sbuf.st_mode & (S_IWGRP|S_IWOTH))
  453. #if NLS
  454.             cp = catgets(_libc_cat, NetMiscSet,
  455.                      NetMiscRhostWritable,
  456.                      ".rhosts writeable by other than owner");
  457. #else
  458.             cp = ".rhosts writeable by other than owner";
  459. #endif
  460.         /* If there were any problems, quit. */
  461.         if (cp) {
  462.             __rcmd_errstr = cp;
  463.             fclose(hostf);
  464.             return(-1);
  465.         }
  466.         goto again;
  467.     }
  468.     return (-1);
  469. }
  470.  
  471. /*
  472.  * XXX
  473.  * Don't make static, used by lpd(8).
  474.  *
  475.  * Returns 0 if ok, -1 if not ok.
  476.  */
  477. int
  478. __ivaliduser(FILE *hostf, u_long raddr, const char *luser, const char *ruser)
  479. {
  480.     register char *user, *p;
  481.     int ch;
  482.     char buf[MAXHOSTNAMELEN + 128];        /* host + login */
  483. #ifdef YP
  484.     int hostvalid = 0;
  485.     int uservalid = 0;
  486. #endif
  487.  
  488.     while (fgets(buf, sizeof (buf), hostf)) {
  489.         p = buf;
  490.         /* Skip lines that are too long. */
  491.         if (strchr(p, '\n') == NULL) {
  492.             while ((ch = getc(hostf)) != '\n' && ch != EOF);
  493.             continue;
  494.         }
  495.         while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') {
  496.             /* *p = isupper(*p) ? tolower(*p) : *p;  -- Uli */
  497.             *p = tolower(*p);    /* works for linux libc */
  498.             p++;
  499.         }
  500.         if (*p == ' ' || *p == '\t') {
  501.             *p++ = '\0';
  502.             while (*p == ' ' || *p == '\t')
  503.                 p++;
  504.             user = p;
  505.             while (*p != '\n' && *p != ' ' &&
  506.                 *p != '\t' && *p != '\0')
  507.                 p++;
  508.         } else
  509.             user = p;
  510.         *p = '\0';
  511. #ifdef YP
  512.             /* disable host from -hostname entry */
  513.         if ('-' == buf[0] && '@' != buf[1]
  514.             && __icheckhost(raddr, &buf[1]))
  515.           return -1;
  516.             /* disable host from -@netgroup entry for host */
  517.         if ('-' == buf[0] && '@' == buf[1] && '\0' != buf[2]
  518.             && __ichecknetgrouphost(raddr, &buf[2]))
  519.           return -1;
  520.             /* disable user from -user entry */
  521.         if ('\0' != *user && user[0] == '-' && user[1] != '@'
  522.             && !strcmp(&user[1], ruser))
  523.           return -1;
  524.             /* disable user from -@netgroup entry for user */
  525.         if ('\0' != *user && user[0] == '-' && user[1] == '@'
  526.             && user[2] != '\0' && _checknetgroupuser(ruser, &user[2]))
  527.           return -1;
  528.             /* enable host from +@netgroup entry for host */
  529.         if ('+' == buf[0] && '@' == buf[1] && '\0' != buf[2])
  530.           hostvalid = __ichecknetgrouphost(raddr, &buf[2]);
  531.         else
  532.           hostvalid = __icheckhost(raddr, buf);
  533.             /* enable user from +@netgroup entry for user */
  534.         if ('\0' != *user && user[0] == '+'
  535.             && user[1] == '@' && user[2] != '\0')
  536.           uservalid = _checknetgroupuser(ruser, &user[2]);
  537.         else
  538.           uservalid = !strcmp(ruser, *user ? user : luser);
  539.         
  540.         if (hostvalid && uservalid)
  541.           return 0;
  542. #else
  543.         if (__icheckhost(raddr, buf) &&
  544.             !strcmp(ruser, *user ? user : luser)) {
  545.                   return (0);
  546.         }
  547. #endif /* YP */
  548.     }
  549.     return (-1);
  550. }
  551.  
  552. /*
  553.  * Returns "true" if match, 0 if no match.
  554.  */
  555. int
  556. __icheckhost(u_long raddr, register char *lhost)
  557. {
  558.     register struct hostent *hp;
  559.     register u_long laddr;
  560.     register char **pp;
  561.  
  562.     /* Try for raw ip address first. */
  563.     if (isdigit(*lhost) && (long)(laddr = inet_addr(lhost)) != -1)
  564.         return (raddr == laddr);
  565.  
  566.     /* Better be a hostname. */
  567.     if ((hp = gethostbyname(lhost)) == NULL)
  568.         return (0);
  569.  
  570.     /* Spin through ip addresses. */
  571.     for (pp = hp->h_addr_list; *pp; ++pp)
  572.         if (!bcmp(&raddr, *pp, sizeof(u_long)))
  573.             return (1);
  574.  
  575.     /* No match. */
  576.     return (0);
  577. }
  578.  
  579. #ifdef YP
  580. static int
  581. __ichecknetgrouphost(u_long raddr, const char *netgr)
  582. {
  583.   char *host, *user, *domain;
  584.   int status;
  585.   
  586.   if (NULL == nisdomain)
  587.     yp_get_default_domain(&nisdomain);
  588.   
  589.   setnetgrent(netgr);
  590.   while (1)
  591.     {
  592.       while (1 == (status = getnetgrent(&host, &user, &domain))
  593.              && NULL == host
  594.              && NULL != domain
  595.              && 0 != strcmp(domain, nisdomain))
  596.         ;  /* find valid host entry */
  597.       
  598.       if (0 == status || NULL == host)
  599.         {
  600.           endnetgrent();
  601.           return 0;
  602.         }
  603.  
  604.       if(__icheckhost(raddr, host))
  605.         {
  606.           endnetgrent();
  607.           return 1;
  608.         }
  609.     }
  610. }
  611.  
  612. static int
  613. _checknetgroupuser(const char *ruser, const char *netgr)
  614. {
  615.   char *host, *user, *domain;
  616.   int status;
  617.   
  618.   if (NULL == nisdomain)
  619.     yp_get_default_domain(&nisdomain);
  620.   
  621.   setnetgrent(netgr);
  622.   while (1)
  623.     {
  624.       while (1 == (status = getnetgrent(&host, &user, &domain))
  625.              && NULL == user
  626.              && NULL != domain
  627.              && 0 != strcmp(domain, nisdomain))
  628.         ;  /* find valid user entry */
  629.       
  630.       if (0 == status || NULL == user)
  631.         {
  632.           endnetgrent();
  633.           return 0;
  634.         }
  635.  
  636.       if(0 == strcmp(ruser, user))
  637.         {
  638.           endnetgrent();
  639.           return 1;
  640.         }
  641.     }
  642. }
  643. #endif /* YP */
  644.