home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (c) 1983 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
- #if defined(LIBC_SCCS) && !defined(lint)
- static char sccsid[] = "@(#)rcmd.c 5.17 (Berkeley) 6/27/88";
- #endif /* LIBC_SCCS and not lint */
-
- #include "inetprivate.h"
- #include <pwd.h>
- #include <sys/file.h>
- #include <sys/signal.h>
- #include <sys/stat.h>
-
- #if NLS
- #include "nl_types.h"
- #endif
-
- #ifdef YP
- #include <rpcsvc/ypclnt.h>
- extern void setnetgrent(const char *);
- extern void endnetgrent(void);
- extern int getnetgrent(char **, char **, char **);
- static char *nisdomain = NULL;
- static int _checknetgrouphost(const char *, const char *, int);
- static int _checknetgroupuser(const char *, const char *);
- #endif
-
- int
- rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
- char **ahost;
- unsigned short rport;
- const char *locuser, *remuser, *cmd;
- int *fd2p;
- {
- int s, timo = 1;
- #ifdef F_SETOWN
- pid_t pid;
- #endif
- #ifdef _POSIX_SOURCE
- sigset_t set, oset;
- #else
- long oldmask;
- #endif
- struct sockaddr_in sin, from;
- char c;
- int lport = IPPORT_RESERVED - 1;
- struct hostent *hp;
-
- #if NLS
- libc_nls_init();
- #endif
-
- #ifdef F_SETOWN
- pid = getpid();
- #endif
- hp = gethostbyname(*ahost);
- if (hp == 0) {
- #if NLS
- fprintf(stderr, "%s: %s\n", *ahost,
- catgets(_libc_cat, HerrorListSet,
- 2, "unknown host"));
- #else
- fprintf(stderr, "%s: unknown host\n", *ahost);
- #endif
- return (-1);
- }
- *ahost = hp->h_name;
- #ifdef SIGURG
- #ifdef _POSIX_SOURCE
- sigemptyset (&set);
- sigaddset (&set, SIGURG);
- sigprocmask (SIG_BLOCK, &set, &oset);
- #else
- oldmask = sigblock(sigmask(SIGURG));
- #endif
- #endif
- for (;;) {
- s = rresvport(&lport);
- if (s < 0) {
- if (errno == EAGAIN)
- #if NLS
- fprintf(stderr, "socket: %s\n",
- catgets(_libc_cat, NetMiscSet,
- NetMiscAllPortsInUse,
- "All ports in use"));
- #else
- fprintf(stderr, "socket: All ports in use\n");
- #endif
- else
- #if NLS
- perror(catgets(_libc_cat, NetMiscSet,
- NetMiscRcmdSocket,
- "rcmd: socket"));
- #else
- perror("rcmd: socket");
- #endif
- #ifdef SIGURG
- #ifdef _POSIX_SOURCE
- sigprocmask (SIG_SETMASK, &oset,
- (sigset_t *)NULL);
- #else
- sigsetmask(oldmask);
- #endif
- #endif
- return (-1);
- }
- #ifdef F_SETOWN
- fcntl(s, F_SETOWN, pid);
- #endif
- sin.sin_family = hp->h_addrtype;
- bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr, hp->h_length);
- sin.sin_port = rport;
- if (connect(s, (struct sockaddr *)&sin, sizeof (sin)) >= 0)
- break;
- (void) close(s);
- if (errno == EADDRINUSE) {
- lport--;
- continue;
- }
- if (errno == ECONNREFUSED && timo <= 16) {
- sleep(timo);
- timo *= 2;
- continue;
- }
- if (hp->h_addr_list[1] != NULL) {
- int oerrno = errno;
-
- fprintf(stderr,
- #if NLS
- "%s %s: ", catgets(_libc_cat, NetMiscSet,
- NetMiscAllPortsInUse,
- "connect to address"),
- inet_ntoa(sin.sin_addr));
-
- #else
-
- "connect to address %s: ", inet_ntoa(sin.sin_addr));
- #endif
- errno = oerrno;
- perror(0);
- hp->h_addr_list++;
- bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr,
- hp->h_length);
-
- #if NLS
- fprintf(stderr, catgets(_libc_cat, NetMiscSet,
- NetMiscTrying,
- "Trying %s...\n"),
- #else
- fprintf(stderr, "Trying %s...\n",
- #endif
- inet_ntoa(sin.sin_addr));
- continue;
- }
- perror(hp->h_name);
- #ifdef SIGURG
- #ifdef _POSIX_SOURCE
- sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
- #else
- sigsetmask(oldmask);
- #endif
- #endif
- return (-1);
- }
- lport--;
- if (fd2p == 0) {
- write(s, "", 1);
- lport = 0;
- } else {
- char num[8];
- int s2 = rresvport(&lport), s3;
- int len = sizeof (from);
-
- if (s2 < 0)
- goto bad;
- listen(s2, 1);
- (void) snprintf(num, sizeof(num), "%d", lport);
- if (write(s, num, strlen(num)+1) != strlen(num)+1) {
- #if NLS
- perror(catgets(_libc_cat, NetMiscSet,
- NetMiscSettingUpStderr,
- "write: setting up stderr"));
- #else
- perror("write: setting up stderr");
- #endif
- (void) close(s2);
- goto bad;
- }
- s3 = accept(s2, (struct sockaddr *)&from, &len);
- (void) close(s2);
- if (s3 < 0) {
- #if NLS
- perror(catgets(_libc_cat, NetMiscSet,
- NetMiscAccept,
- "accept"));
- #else
- perror("accept");
- #endif
- lport = 0;
- goto bad;
- }
- *fd2p = s3;
- from.sin_port = ntohs((u_short)from.sin_port);
- if (from.sin_family != AF_INET ||
- from.sin_port >= IPPORT_RESERVED) {
- fprintf(stderr,
- #if NLS
- "%s\n",
- catgets(_libc_cat, NetMiscSet,
- NetMiscProtocolFailure,
- "socket: protocol failure in circuit setup."));
- #else
- "socket: protocol failure in circuit setup.\n");
- #endif
- goto bad2;
- }
- }
- (void) write(s, locuser, strlen(locuser)+1);
- (void) write(s, remuser, strlen(remuser)+1);
- (void) write(s, cmd, strlen(cmd)+1);
- if (read(s, &c, 1) != 1) {
- perror(*ahost);
- goto bad2;
- }
- if (c != 0) {
- while (read(s, &c, 1) == 1) {
- (void) write(2, &c, 1);
- if (c == '\n')
- break;
- }
- goto bad2;
- }
- #ifdef SIGURG
- #ifdef _POSIX_SOURCE
- sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
- #else
- sigsetmask(oldmask);
- #endif
- #endif
- return (s);
- bad2:
- if (lport)
- (void) close(*fd2p);
- bad:
- (void) close(s);
- #ifdef SIGURG
- #ifdef _POSIX_SOURCE
- sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
- #else
- sigsetmask(oldmask);
- #endif
- #endif
- return (-1);
- }
-
- int
- rresvport(alport)
- int *alport;
- {
- struct sockaddr_in sin;
- int s;
-
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = INADDR_ANY;
- s = socket(AF_INET, SOCK_STREAM, 0);
- if (s < 0)
- return (-1);
- for (;;) {
- sin.sin_port = htons((u_short)*alport);
- if (bind(s, (struct sockaddr *)&sin, sizeof (sin)) >= 0)
- return (s);
- if (errno != EADDRINUSE) {
- (void) close(s);
- return (-1);
- }
- (*alport)--;
- if (*alport == IPPORT_RESERVED/2) {
- (void) close(s);
- errno = EAGAIN; /* close */
- return (-1);
- }
- }
- }
-
- int
- ruserok(const char *rhost, int superuser, const char *ruser,
- const char *luser)
- {
- FILE *hostf;
- char fhost[MAXHOSTNAMELEN];
- int first = 1;
- register const char *sp;
- register char *p;
- int baselen = -1;
- uid_t saveuid;
-
- saveuid = geteuid();
- sp = rhost;
- p = fhost;
- while (*sp) {
- if (*sp == '.') {
- if (baselen == -1)
- baselen = sp - rhost;
- *p++ = *sp++;
- } else {
- *p++ = isupper(*sp) ? tolower(*sp++) : *sp++;
- }
- }
- *p = '\0';
- hostf = superuser ? (FILE *)0 : fopen(_PATH_HEQUIV, "r");
- again:
- if (hostf) {
- if (!_validuser(hostf, fhost, luser, ruser, baselen)) {
- (void) fclose(hostf);
- seteuid(saveuid);
- return(0);
- }
- (void) fclose(hostf);
- }
- if (first == 1) {
- struct stat sbuf;
- struct passwd *pwd;
- char pbuf[MAXPATHLEN];
-
- first = 0;
- if ((pwd = getpwnam(luser)) == NULL)
- return(-1);
- (void)strcpy(pbuf, pwd->pw_dir);
- (void)strcat(pbuf, "/.rhosts");
- (void)seteuid(pwd->pw_uid);
- if ((hostf = fopen(pbuf, "r")) == NULL) {
- seteuid(saveuid);
- return(-1);
- }
- (void)fstat(fileno(hostf), &sbuf);
- if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid) {
- fclose(hostf);
- seteuid(saveuid);
- return(-1);
- }
- goto again;
- }
- seteuid(saveuid);
- return (-1);
- }
-
- int
- _validuser(FILE *hostf, const char *rhost, const char *luser,
- const char *ruser, int baselen)
- {
- char *user;
- char ahost[MAXHOSTNAMELEN];
- register char *p;
- #ifdef YP
- int hostvalid = 0;
- int uservalid = 0;
- #endif
-
- while (fgets(ahost, sizeof (ahost), hostf)) {
- p = ahost;
- while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') {
- *p = isupper(*p) ? tolower(*p) : *p;
- p++;
- }
- if (*p == ' ' || *p == '\t') {
- *p++ = '\0';
- while (*p == ' ' || *p == '\t')
- p++;
- user = p;
- while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0')
- p++;
- } else
- user = p;
- *p = '\0';
- #ifdef YP
- /* disable host from -hostname entry */
- if ('-' == ahost[0] && '@' != ahost[1]
- && _checkhost(rhost, &ahost[1], baselen))
- return -1;
- /* disable host from -@netgroup entry for host */
- if ('-' == ahost[0] && '@' == ahost[1] && '\0' != ahost[2]
- && _checknetgrouphost(rhost, &ahost[2], baselen))
- return -1;
- /* disable user from -user entry */
- if ('\0' != *user && user[0] == '-' && user[1] != '@'
- && !strcmp(&user[1], ruser))
- return -1;
- /* disable user from -@netgroup entry for user */
- if ('\0' != *user && user[0] == '-' && user[1] == '@'
- && user[2] != '\0' && _checknetgroupuser(ruser, &user[2]))
- return -1;
- /* enable host from +@netgroup entry for host */
- if ('+' == ahost[0] && '@' == ahost[1] && '\0' != ahost[2])
- hostvalid = _checknetgrouphost(rhost, &ahost[2], baselen);
- else
- hostvalid = _checkhost(rhost, ahost, baselen);
- /* enable user from +@netgroup entry for user */
- if ('\0' != *user && user[0] == '+'
- && user[1] == '@' && user[2] != '\0')
- uservalid = _checknetgroupuser(ruser, &user[2]);
- else
- uservalid = !strcmp(ruser, *user ? user : luser);
-
- if (hostvalid && uservalid)
- return 0;
- #else
- if (_checkhost(rhost, ahost, baselen) &&
- !strcmp(ruser, *user ? user : luser)) {
- return (0);
- }
- #endif /* YP */
- }
- return (-1);
- }
-
- int
- _checkhost(const char *rhost, const char *lhost, int len)
- {
- static char ldomain[MAXHOSTNAMELEN + 1];
- static char *domainp = NULL;
- static int nodomain = 0;
- register char *cp;
-
- if (len == -1)
- return(!strcmp(rhost, lhost));
- if (strncmp(rhost, lhost, len))
- return(0);
- if (!strcmp(rhost, lhost))
- return(1);
- if (*(lhost + len) != '\0')
- return(0);
- if (nodomain)
- return(0);
- if (!domainp) {
- if (gethostname(ldomain, sizeof(ldomain)) == -1) {
- nodomain = 1;
- return(0);
- }
- ldomain[MAXHOSTNAMELEN] = (char) 0;
- if ((domainp = index(ldomain, '.')) == (char *)NULL) {
- nodomain = 1;
- return(0);
- }
- for (cp = ++domainp; *cp; ++cp)
- if (isupper(*cp))
- *cp = tolower(*cp);
- }
- return(!strcmp(domainp, rhost + len +1));
- }
-
- #ifdef YP
- static int
- _checknetgrouphost(const char *rhost, const char *netgr, int baselen)
- {
- char *host, *user, *domain;
- int status;
-
- if (NULL == nisdomain)
- yp_get_default_domain(&nisdomain);
-
- setnetgrent(netgr);
- while (1)
- {
- while (1 == (status = getnetgrent(&host, &user, &domain))
- && NULL == host
- && NULL != domain
- && 0 != strcmp(domain, nisdomain))
- ; /* find valid host entry */
-
- if (0 == status || NULL == host)
- {
- endnetgrent();
- return 0;
- }
-
- if(1 == _checkhost(rhost, host, baselen))
- {
- endnetgrent();
- return 1;
- }
- }
- }
-
- static int
- _checknetgroupuser(const char *ruser, const char *netgr)
- {
- char *host, *user, *domain;
- int status;
-
- if (NULL == nisdomain)
- yp_get_default_domain(&nisdomain);
-
- setnetgrent(netgr);
- while (1)
- {
- while (1 == (status = getnetgrent(&host, &user, &domain))
- && NULL == user
- && NULL != domain
- && 0 != strcmp(domain, nisdomain))
- ; /* find valid user entry */
-
- if (0 == status || NULL == user)
- {
- endnetgrent();
- return 0;
- }
-
- if(0 == strcmp(ruser, user))
- {
- endnetgrent();
- return 1;
- }
- }
- }
- #endif /* YP */
-