1: /* 2: * Copyright (c) 1983 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: */ 6: 7: #if defined(LIBC_SCCS) && !defined(lint) 8: static char sccsid[] = "@(#)rcmd.c 5.11 (Berkeley) 5/6/86"; 9: #endif LIBC_SCCS and not lint 10: 11: #include <stdio.h> 12: #include <ctype.h> 13: #include <pwd.h> 14: #include <sys/param.h> 15: #include <sys/file.h> 16: #include <sys/signal.h> 17: #include <sys/socket.h> 18: #include <sys/stat.h> 19: 20: #include <netinet/in.h> 21: 22: #include <netdb.h> 23: #include <errno.h> 24: 25: extern errno; 26: char *index(), *sprintf(); 27: 28: rcmd(ahost, rport, locuser, remuser, cmd, fd2p) 29: char **ahost; 30: u_short rport; 31: char *locuser, *remuser, *cmd; 32: int *fd2p; 33: { 34: int s, timo = 1, pid, oldmask; 35: struct sockaddr_in sin, sin2, from; 36: char c; 37: int lport = IPPORT_RESERVED - 1; 38: struct hostent *hp; 39: 40: pid = getpid(); 41: hp = gethostbyname(*ahost); 42: if (hp == 0) { 43: fprintf(stderr, "%s: unknown host\n", *ahost); 44: return (-1); 45: } 46: *ahost = hp->h_name; 47: oldmask = sigblock(sigmask(SIGURG)); 48: for (;;) { 49: s = rresvport(&lport); 50: if (s < 0) { 51: if (errno == EAGAIN) 52: fprintf(stderr, "socket: All ports in use\n"); 53: else 54: perror("rcmd: socket"); 55: sigsetmask(oldmask); 56: return (-1); 57: } 58: fcntl(s, F_SETOWN, pid); 59: sin.sin_family = hp->h_addrtype; 60: bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr, hp->h_length); 61: sin.sin_port = rport; 62: if (connect(s, (caddr_t)&sin, sizeof (sin), 0) >= 0) 63: break; 64: (void) close(s); 65: if (errno == EADDRINUSE) { 66: lport--; 67: continue; 68: } 69: if (errno == ECONNREFUSED && timo <= 16) { 70: sleep(timo); 71: timo *= 2; 72: continue; 73: } 74: if (hp->h_addr_list[1] != NULL) { 75: int oerrno = errno; 76: 77: fprintf(stderr, 78: "connect to address %s: ", inet_ntoa(sin.sin_addr)); 79: errno = oerrno; 80: perror(0); 81: hp->h_addr_list++; 82: bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr, 83: hp->h_length); 84: fprintf(stderr, "Trying %s...\n", 85: inet_ntoa(sin.sin_addr)); 86: continue; 87: } 88: perror(hp->h_name); 89: sigsetmask(oldmask); 90: return (-1); 91: } 92: lport--; 93: if (fd2p == 0) { 94: write(s, "", 1); 95: lport = 0; 96: } else { 97: char num[8]; 98: int s2 = rresvport(&lport), s3; 99: int len = sizeof (from); 100: 101: if (s2 < 0) 102: goto bad; 103: listen(s2, 1); 104: (void) sprintf(num, "%d", lport); 105: if (write(s, num, strlen(num)+1) != strlen(num)+1) { 106: perror("write: setting up stderr"); 107: (void) close(s2); 108: goto bad; 109: } 110: s3 = accept(s2, &from, &len, 0); 111: (void) close(s2); 112: if (s3 < 0) { 113: perror("accept"); 114: lport = 0; 115: goto bad; 116: } 117: *fd2p = s3; 118: from.sin_port = ntohs((u_short)from.sin_port); 119: if (from.sin_family != AF_INET || 120: from.sin_port >= IPPORT_RESERVED) { 121: fprintf(stderr, 122: "socket: protocol failure in circuit setup.\n"); 123: goto bad2; 124: } 125: } 126: (void) write(s, locuser, strlen(locuser)+1); 127: (void) write(s, remuser, strlen(remuser)+1); 128: (void) write(s, cmd, strlen(cmd)+1); 129: if (read(s, &c, 1) != 1) { 130: perror(*ahost); 131: goto bad2; 132: } 133: if (c != 0) { 134: while (read(s, &c, 1) == 1) { 135: (void) write(2, &c, 1); 136: if (c == '\n') 137: break; 138: } 139: goto bad2; 140: } 141: sigsetmask(oldmask); 142: return (s); 143: bad2: 144: if (lport) 145: (void) close(*fd2p); 146: bad: 147: (void) close(s); 148: sigsetmask(oldmask); 149: return (-1); 150: } 151: 152: rresvport(alport) 153: int *alport; 154: { 155: struct sockaddr_in sin; 156: int s; 157: 158: sin.sin_family = AF_INET; 159: sin.sin_addr.s_addr = INADDR_ANY; 160: s = socket(AF_INET, SOCK_STREAM, 0); 161: if (s < 0) 162: return (-1); 163: for (;;) { 164: sin.sin_port = htons((u_short)*alport); 165: if (bind(s, (caddr_t)&sin, sizeof (sin)) >= 0) 166: return (s); 167: if (errno != EADDRINUSE) { 168: (void) close(s); 169: return (-1); 170: } 171: (*alport)--; 172: if (*alport == IPPORT_RESERVED/2) { 173: (void) close(s); 174: errno = EAGAIN; /* close */ 175: return (-1); 176: } 177: } 178: } 179: 180: ruserok(rhost, superuser, ruser, luser) 181: char *rhost; 182: int superuser; 183: char *ruser, *luser; 184: { 185: FILE *hostf; 186: char fhost[MAXHOSTNAMELEN]; 187: int first = 1; 188: register char *sp, *p; 189: int baselen = -1; 190: 191: sp = rhost; 192: p = fhost; 193: while (*sp) { 194: if (*sp == '.') { 195: if (baselen == -1) 196: baselen = sp - rhost; 197: *p++ = *sp++; 198: } else { 199: *p++ = isupper(*sp) ? tolower(*sp++) : *sp++; 200: } 201: } 202: *p = '\0'; 203: hostf = superuser ? (FILE *)0 : fopen("/etc/hosts.equiv", "r"); 204: again: 205: if (hostf) { 206: if (!_validuser(hostf, fhost, luser, ruser, baselen)) { 207: (void) fclose(hostf); 208: return(0); 209: } 210: (void) fclose(hostf); 211: } 212: if (first == 1) { 213: struct stat sbuf; 214: struct passwd *pwd; 215: char pbuf[MAXPATHLEN]; 216: 217: first = 0; 218: if ((pwd = getpwnam(luser)) == NULL) 219: return(-1); 220: (void)strcpy(pbuf, pwd->pw_dir); 221: (void)strcat(pbuf, "/.rhosts"); 222: if ((hostf = fopen(pbuf, "r")) == NULL) 223: return(-1); 224: (void)fstat(fileno(hostf), &sbuf); 225: if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid) { 226: fclose(hostf); 227: return(-1); 228: } 229: goto again; 230: } 231: return (-1); 232: } 233: 234: _validuser(hostf, rhost, luser, ruser, baselen) 235: char *rhost, *luser, *ruser; 236: FILE *hostf; 237: int baselen; 238: { 239: char *user; 240: char ahost[MAXHOSTNAMELEN]; 241: register char *p; 242: 243: while (fgets(ahost, sizeof (ahost), hostf)) { 244: p = ahost; 245: while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') { 246: *p = isupper(*p) ? tolower(*p) : *p; 247: p++; 248: } 249: if (*p == ' ' || *p == '\t') { 250: *p++ = '\0'; 251: while (*p == ' ' || *p == '\t') 252: p++; 253: user = p; 254: while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') 255: p++; 256: } else 257: user = p; 258: *p = '\0'; 259: if (_checkhost(rhost, ahost, baselen) && 260: !strcmp(ruser, *user ? user : luser)) { 261: return (0); 262: } 263: } 264: return (-1); 265: } 266: 267: _checkhost(rhost, lhost, len) 268: char *rhost, *lhost; 269: int len; 270: { 271: static char ldomain[MAXHOSTNAMELEN + 1]; 272: static char *domainp = NULL; 273: register char *cp; 274: 275: if (len == -1) 276: return(!strcmp(rhost, lhost)); 277: if (strncmp(rhost, lhost, len)) 278: return(0); 279: if (!strcmp(rhost, lhost)) 280: return(1); 281: if (*(lhost + len) != '\0') 282: return(0); 283: if (!domainp) { 284: if (gethostname(ldomain, sizeof(ldomain)) == -1) { 285: domainp = (char *)1; 286: return(0); 287: } 288: ldomain[MAXHOSTNAMELEN] = NULL; 289: if ((domainp = index(ldomain, '.') + 1) == (char *)1) 290: return(0); 291: cp = domainp; 292: while (*cp) { 293: *cp = isupper(*cp) ? tolower(*cp) : *cp; 294: cp++; 295: } 296: } 297: if (domainp == (char *)1) 298: return(0); 299: return(!strcmp(domainp, rhost + len +1)); 300: }