summaryrefslogtreecommitdiff
path: root/usr/src/lib/libbc/libc/net/rcmd.c
diff options
context:
space:
mode:
authorstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
committerstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
commit7c478bd95313f5f23a4c958a745db2134aa03244 (patch)
treec871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/libbc/libc/net/rcmd.c
downloadillumos-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.c398
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));
+}