diff options
author | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
---|---|---|
committer | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
commit | 7c478bd95313f5f23a4c958a745db2134aa03244 (patch) | |
tree | c871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/libbc/libc/net/rcmd.c | |
download | illumos-gate-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz |
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/libbc/libc/net/rcmd.c')
-rw-r--r-- | usr/src/lib/libbc/libc/net/rcmd.c | 398 |
1 files changed, 398 insertions, 0 deletions
diff --git a/usr/src/lib/libbc/libc/net/rcmd.c b/usr/src/lib/libbc/libc/net/rcmd.c new file mode 100644 index 0000000000..9e989ff69e --- /dev/null +++ b/usr/src/lib/libbc/libc/net/rcmd.c @@ -0,0 +1,398 @@ +/* + * Copyright 1995 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <ctype.h> +#include <pwd.h> +#include <sys/param.h> +#include <sys/file.h> +#include <sys/signal.h> +#include <sys/socket.h> +#include <sys/stat.h> + +#include <netinet/in.h> + +#include <netdb.h> +#include <errno.h> + +extern errno; +char *index(), *strcpy(); +#ifndef S5EMUL +char *sprintf(); +#endif +static char *domain; + +int +rcmd( + char **ahost, + unsigned short rport, + const char *locuser, + const char *remuser, + const char *cmd, + int *fd2p) +{ + int s, timo = 1, pid, oldmask, retval; + struct sockaddr_in sin, from; + char c; + int lport = IPPORT_RESERVED - 1; + struct hostent *hp; + + pid = getpid(); + hp = gethostbyname(*ahost); + if (hp == 0) { + fprintf(stderr, "%s: unknown host\n", *ahost); + return (-1); + } + *ahost = hp->h_name; + oldmask = sigblock(sigmask(SIGURG)); + for (;;) { + s = rresvport(&lport); + if (s < 0) { + if (errno == EAGAIN) + fprintf(stderr, "socket: All ports in use\n"); + else + perror("rcmd: socket"); + sigsetmask(oldmask); + return (-1); + } + fcntl(s, F_SETOWN, pid); + 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, &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, + "connect to address %s: ", inet_ntoa(sin.sin_addr)); + errno = oerrno; + perror(0); + hp->h_addr_list++; + bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr, + hp->h_length); + fprintf(stderr, "Trying %s...\n", + inet_ntoa(sin.sin_addr)); + continue; + } + perror(hp->h_name); + sigsetmask(oldmask); + 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) sprintf(num, "%d", lport); + if (write(s, num, strlen(num)+1) != strlen(num)+1) { + perror("write: setting up stderr"); + (void) close(s2); + goto bad; + } + s3 = accept(s2, &from, &len); + (void) close(s2); + if (s3 < 0) { + perror("accept"); + 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, + "socket: protocol failure in circuit setup.\n"); + goto bad2; + } + } + (void) write(s, locuser, strlen(locuser)+1); + (void) write(s, remuser, strlen(remuser)+1); + (void) write(s, cmd, strlen(cmd)+1); + retval = read(s, &c, 1); + if (retval != 1) { + if (retval == 0) { + fprintf(stderr, + "Protocol error, %s closed connection\n", *ahost); + } else if (retval < 0) { + perror(*ahost); + } else { + fprintf(stderr, + "Protocol error, %s sent %d bytes\n", *ahost, retval); + } + goto bad2; + } + if (c != 0) { + while (read(s, &c, 1) == 1) { + (void) write(2, &c, 1); + if (c == '\n') + break; + } + goto bad2; + } + sigsetmask(oldmask); + return (s); +bad2: + if (lport) + (void) close(*fd2p); +bad: + (void) close(s); + sigsetmask(oldmask); + 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, (caddr_t)&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]; + register const char *sp; + register char *p; + int baselen = -1; + + struct stat sbuf; + struct passwd *pwd; + char pbuf[MAXPATHLEN]; + int euid = -1; + + 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'; + + /* check /etc/hosts.equiv */ + if (!superuser) { + if ((hostf = fopen("/etc/hosts.equiv", "r")) != NULL) { + if (!_validuser(hostf, fhost, luser, ruser, baselen)) { + (void) fclose(hostf); + return(0); + } + (void) fclose(hostf); + } + } + + /* check ~/.rhosts */ + + if ((pwd = getpwnam(luser)) == NULL) + return(-1); + (void)strcpy(pbuf, pwd->pw_dir); + (void)strcat(pbuf, "/.rhosts"); + + /* + * Read .rhosts as the local user to avoid NFS mapping the root uid + * to something that can't read .rhosts. + */ + euid = geteuid(); + (void) seteuid (pwd->pw_uid); + if ((hostf = fopen(pbuf, "r")) == NULL) { + if (euid != -1) + (void) seteuid (euid); + return(-1); + } + (void)fstat(fileno(hostf), &sbuf); + if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid) { + fclose(hostf); + if (euid != -1) + (void) seteuid (euid); + return(-1); + } + + if (!_validuser(hostf, fhost, luser, ruser, baselen)) { + (void) fclose(hostf); + if (euid != -1) + (void) seteuid (euid); + return(0); + } + + (void) fclose(hostf); + if (euid != -1) + (void) seteuid (euid); + return (-1); +} + +_validuser(hostf, rhost, luser, ruser, baselen) +char *rhost, *luser, *ruser; +FILE *hostf; +int baselen; +{ + char *user; + char ahost[MAXHOSTNAMELEN]; + int hostmatch, usermatch; + register char *p; + + if (domain == NULL) { + (void) yp_get_default_domain(&domain); + } + while (fgets(ahost, sizeof (ahost), hostf)) { + hostmatch = usermatch = 0; /* bugid fix 1033104 */ + 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'; + if (ahost[0] == '+' && ahost[1] == 0) + hostmatch = 1; + else if (ahost[0] == '+' && ahost[1] == '@') + hostmatch = innetgr(ahost + 2, rhost, + NULL, domain); + else if (ahost[0] == '-' && ahost[1] == '@') { + if (innetgr(ahost + 2, rhost, NULL, domain)) + break; + } + else if (ahost[0] == '-') { + if (_checkhost(rhost, ahost+1, baselen)) + break; + } + else + hostmatch = _checkhost(rhost, ahost, baselen); + if (user[0]) { + if (user[0] == '+' && user[1] == 0) + usermatch = 1; + else if (user[0] == '+' && user[1] == '@') + usermatch = innetgr(user+2, NULL, + ruser, domain); + else if (user[0] == '-' && user[1] == '@') { + if (hostmatch && innetgr(user+2, NULL, + ruser, domain)) + break; + } + else if (user[0] == '-') { + if (hostmatch && !strcmp(user+1, ruser)) + break; + } + else + usermatch = !strcmp(user, ruser); + } + else + usermatch = !strcmp(ruser, luser); + if (hostmatch && usermatch) + return (0); + } + return (-1); +} + +_checkhost(rhost, lhost, len) +char *rhost, *lhost; +int len; +{ + static char *ldomain; + static char *domainp; + static int nodomain; + register char *cp; + + if (ldomain == NULL) { + ldomain = (char *)malloc(MAXHOSTNAMELEN+1); + if (ldomain == 0) + return (0); + } + + 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) { + /* + * "domainp" points after the first dot in the host name + */ + if (gethostname(ldomain, MAXHOSTNAMELEN) == -1) { + nodomain = 1; + return(0); + } + ldomain[MAXHOSTNAMELEN] = NULL; + if ((domainp = index(ldomain, '.')) == (char *)NULL) { + nodomain = 1; + return(0); + } + domainp++; + cp = domainp; + while (*cp) { + *cp = isupper(*cp) ? tolower(*cp) : *cp; + cp++; + } + } + return(!strcmp(domainp, rhost + len +1)); +} |