home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / mint / netlib / lib / rcmd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-27  |  9.2 KB  |  378 lines

  1. /*
  2.  * Copyright (c) 1983 Regents of the University of California.
  3.  * 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    5.24 (Berkeley) 2/24/91";
  36. #endif /* LIBC_SCCS and not lint */
  37.  
  38. #include "socklib.h"
  39. #include <sys/param.h>
  40. #include <sys/socket.h>
  41. #include <sys/stat.h>
  42. #include <netinet/in.h>
  43. #include <arpa/inet.h>
  44. #include <signal.h>
  45. #include <fcntl.h>
  46. #include <ioctl.h>
  47. #include <netdb.h>
  48. #include <pwd.h>
  49. #include <errno.h>
  50. #include <stdio.h>
  51. #include <ctype.h>
  52. #include <unistd.h>
  53. #include <string.h>
  54.  
  55. #ifdef __MINT__
  56. #include <support.h>
  57. #include <sys/types.h>
  58. #include "sockios.h"
  59. #ifndef EAGAIN
  60. #define EAGAIN        EWOULDBLOCK
  61. #endif
  62. #ifndef MAXHOSTNAMELEN
  63. #define MAXHOSTNAMELEN    64
  64. #endif
  65. #endif
  66.  
  67. extern int rresvport (int *);
  68. extern int ruserok(const char *, int, const char *, const char *);
  69. extern int _validuser(FILE *, const char *, const char *, const char *, int);
  70. static int _checkhost(const char *, const char *, int);
  71.  
  72. int
  73. rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
  74.     char **ahost;
  75.     u_short rport;
  76.     const char *locuser, *remuser, *cmd;
  77.     int *fd2p;
  78. {
  79.     int s, timo = 1, pid;
  80.     long oldmask;
  81.     struct sockaddr_in sin, sin2, from;
  82.     char c;
  83.     int lport = IPPORT_RESERVED - 1;
  84.     struct hostent *hp;
  85.     fd_set reads;
  86.  
  87.     pid = getpid();
  88.     hp = gethostbyname(*ahost);
  89.     if (hp == 0) {
  90.         herror(*ahost);
  91.         return (-1);
  92.     }
  93.     *ahost = hp->h_name;
  94.     oldmask = sigblock(sigmask(SIGURG));
  95.     for (;;) {
  96.         s = rresvport(&lport);
  97.         if (s < 0) {
  98.             if (errno == EAGAIN)
  99.                 fprintf(stderr, "socket: All ports in use\n");
  100.             else
  101.                 perror("rcmd: socket");
  102.             sigsetmask(oldmask);
  103.             return (-1);
  104.         }
  105. #ifdef __MINT__
  106.         ioctl(s, SIOCSPGRP, &pid);
  107. #else
  108.         fcntl(s, F_SETOWN, pid);
  109. #endif
  110.         sin.sin_family = hp->h_addrtype;
  111.         bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr, hp->h_length);
  112.         sin.sin_port = rport;
  113.         if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
  114.             break;
  115.         (void) close(s);
  116.         if (errno == EADDRINUSE) {
  117.             lport--;
  118.             continue;
  119.         }
  120.         if (errno == ECONNREFUSED && timo <= 16) {
  121.             sleep(timo);
  122.             timo *= 2;
  123.             continue;
  124.         }
  125.         if (hp->h_addr_list[1] != NULL) {
  126.             int oerrno = errno;
  127.  
  128.             fprintf(stderr,
  129.                 "connect to address %s: ", inet_ntoa(sin.sin_addr));
  130.             errno = oerrno;
  131.             perror(0);
  132.             hp->h_addr_list++;
  133.             bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr,
  134.                 hp->h_length);
  135.             fprintf(stderr, "Trying %s...\n",
  136.                 inet_ntoa(sin.sin_addr));
  137.             continue;
  138.         }
  139.         perror(hp->h_name);
  140.         sigsetmask(oldmask);
  141.         return (-1);
  142.     }
  143.     lport--;
  144.     if (fd2p == 0) {
  145.         write(s, "", 1);
  146.         lport = 0;
  147.     } else {
  148.         char num[8];
  149.         int s2 = rresvport(&lport), s3;
  150.         int len = sizeof (from);
  151.  
  152.         if (s2 < 0)
  153.             goto bad;
  154.         listen(s2, 1);
  155.         (void) sprintf(num, "%d", lport);
  156.         if (write(s, num, strlen(num)+1) != strlen(num)+1) {
  157.             perror("write: setting up stderr");
  158.             (void) close(s2);
  159.             goto bad;
  160.         }
  161.         FD_ZERO(&reads);
  162.         FD_SET(s, &reads);
  163.         FD_SET(s2, &reads);
  164.         errno = 0;
  165.         if (select(32, &reads, 0, 0, 0) < 1 ||
  166.             !FD_ISSET(s2, &reads)) {
  167.             if (errno != 0)
  168.                 perror("select: setting up stderr");
  169.             else
  170.                 fprintf(stderr,
  171.                 "select: protocol failure in circuit setup.\n");
  172.             (void) close(s2);
  173.             goto bad;
  174.         }
  175.         s3 = accept(s2, (struct sockaddr *)&from, &len);
  176.         (void) close(s2);
  177.         if (s3 < 0) {
  178.             perror("accept");
  179.             lport = 0;
  180.             goto bad;
  181.         }
  182.         *fd2p = s3;
  183.         from.sin_port = ntohs((u_short)from.sin_port);
  184.         if (from.sin_family != AF_INET ||
  185.             from.sin_port >= IPPORT_RESERVED ||
  186.             from.sin_port < IPPORT_RESERVED / 2) {
  187.             fprintf(stderr,
  188.                 "socket: protocol failure in circuit setup.\n");
  189.             goto bad2;
  190.         }
  191.     }
  192.     (void) write(s, locuser, strlen(locuser)+1);
  193.     (void) write(s, remuser, strlen(remuser)+1);
  194.     (void) write(s, cmd, strlen(cmd)+1);
  195.     if (read(s, &c, 1) != 1) {
  196.         perror(*ahost);
  197.         goto bad2;
  198.     }
  199.     if (c != 0) {
  200.         while (read(s, &c, 1) == 1) {
  201.             (void) write(2, &c, 1);
  202.             if (c == '\n')
  203.                 break;
  204.         }
  205.         goto bad2;
  206.     }
  207.     sigsetmask(oldmask);
  208.     return (s);
  209. bad2:
  210.     if (lport)
  211.         (void) close(*fd2p);
  212. bad:
  213.     (void) close(s);
  214.     sigsetmask(oldmask);
  215.     return (-1);
  216. }
  217.  
  218. int
  219. rresvport(alport)
  220.     int *alport;
  221. {
  222.     struct sockaddr_in sin;
  223.     int s;
  224.  
  225.     sin.sin_family = AF_INET;
  226.     sin.sin_addr.s_addr = INADDR_ANY;
  227.     s = socket(AF_INET, SOCK_STREAM, 0);
  228.     if (s < 0)
  229.         return (-1);
  230.     for (;;) {
  231.         sin.sin_port = htons((u_short)*alport);
  232.         if (bind(s, (struct sockaddr *)&sin, sizeof (sin)) >= 0)
  233.             return (s);
  234.         if (errno != EADDRINUSE) {
  235.             (void) close(s);
  236.             return (-1);
  237.         }
  238.         (*alport)--;
  239.         if (*alport == IPPORT_RESERVED/2) {
  240.             (void) close(s);
  241.             errno = EAGAIN;        /* close */
  242.             return (-1);
  243.         }
  244.     }
  245. }
  246.  
  247. int    _check_rhosts_file = 1;
  248.  
  249. int
  250. ruserok(rhost, superuser, ruser, luser)
  251.     const char *rhost, *ruser, *luser;
  252.     int superuser;
  253. {
  254.     FILE *hostf;
  255.     char fhost[MAXHOSTNAMELEN];
  256.     int first = 1;
  257.     register char *sp, *p;
  258.     int baselen = -1;
  259.  
  260.     sp = (char *)rhost;
  261.     p = fhost;
  262.     while (*sp) {
  263.         if (*sp == '.') {
  264.             if (baselen == -1)
  265.                 baselen = sp - rhost;
  266.             *p++ = *sp++;
  267.         } else {
  268.             *p++ = isupper(*sp) ? tolower(*sp++) : *sp++;
  269.         }
  270.     }
  271.     *p = '\0';
  272.     hostf = superuser ? (FILE *)0 : fopen(_PATH_HEQUIV, "rt");
  273. again:
  274.     if (hostf) {
  275.         if (!_validuser(hostf, fhost, luser, ruser, baselen)) {
  276.             (void) fclose(hostf);
  277.             return(0);
  278.         }
  279.         (void) fclose(hostf);
  280.     }
  281.     if (first == 1 && (_check_rhosts_file || superuser)) {
  282.         struct stat sbuf;
  283.         struct passwd *pwd;
  284.         char pbuf[MAXPATHLEN];
  285.  
  286.         first = 0;
  287.         if ((pwd = getpwnam(luser)) == NULL)
  288.             return(-1);
  289.         (void)strcpy(pbuf, pwd->pw_dir);
  290.         (void)strcat(pbuf, "/.rhosts");
  291.         if ((hostf = fopen(pbuf, "rt")) == NULL)
  292.             return(-1);
  293.         /*
  294.          * if owned by someone other than user or root or if
  295.          * writeable by anyone but the owner, quit
  296.          */
  297.         if (fstat(fileno(hostf), &sbuf) ||
  298.             sbuf.st_uid && sbuf.st_uid != pwd->pw_uid ||
  299.             sbuf.st_mode&022) {
  300.             fclose(hostf);
  301.             return(-1);
  302.         }
  303.         goto again;
  304.     }
  305.     return (-1);
  306. }
  307.  
  308. /* don't make static, used by lpd(8) */
  309. int
  310. _validuser(hostf, rhost, luser, ruser, baselen)
  311.     const char *rhost, *luser, *ruser;
  312.     FILE *hostf;
  313.     int baselen;
  314. {
  315.     register char *p;
  316.     char *user, ahost[MAXHOSTNAMELEN];
  317.  
  318.     while (fgets(ahost, sizeof (ahost), hostf)) {
  319.         p = ahost;
  320.         while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') {
  321.             *p = isupper(*p) ? tolower(*p) : *p;
  322.             p++;
  323.         }
  324.         if (*p == ' ' || *p == '\t') {
  325.             *p++ = '\0';
  326.             while (*p == ' ' || *p == '\t')
  327.                 p++;
  328.             user = p;
  329.             while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0')
  330.                 p++;
  331.         } else
  332.             user = p;
  333.         *p = '\0';
  334.         if (_checkhost(rhost, ahost, baselen) &&
  335.             !strcmp(ruser, *user ? user : luser)) {
  336.             return (0);
  337.         }
  338.     }
  339.     return (-1);
  340. }
  341.  
  342. static int
  343. _checkhost(rhost, lhost, len)
  344.     const char *rhost, *lhost;
  345.     int len;
  346. {
  347.     static char ldomain[MAXHOSTNAMELEN + 1];
  348.     static char *domainp = NULL;
  349.     static int nodomain = 0;
  350.     register char *cp;
  351.  
  352.     if (len == -1)
  353.         return(!strcmp(rhost, lhost));
  354.     if (strncmp(rhost, lhost, len))
  355.         return(0);
  356.     if (!strcmp(rhost, lhost))
  357.         return(1);
  358.     if (*(lhost + len) != '\0')
  359.         return(0);
  360.     if (nodomain)
  361.         return(0);
  362.     if (!domainp) {
  363.         if (gethostname(ldomain, sizeof(ldomain)) == -1) {
  364.             nodomain = 1;
  365.             return(0);
  366.         }
  367.         ldomain[MAXHOSTNAMELEN] = 0;
  368.         if ((domainp = index(ldomain, '.')) == (char *)NULL) {
  369.             nodomain = 1;
  370.             return(0);
  371.         }
  372.         for (cp = ++domainp; *cp; ++cp)
  373.             if (isupper(*cp))
  374.                 *cp = tolower(*cp);
  375.     }
  376.     return(!strcmp(domainp, rhost + len +1));
  377. }
  378.