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 are permitted 6: * provided that the above copyright notice and this paragraph are 7: * duplicated in all such forms and that any documentation, 8: * advertising materials, and other materials related to such 9: * distribution and use acknowledge that the software was developed 10: * by the University of California, Berkeley. The name of the 11: * University may not be used to endorse or promote products derived 12: * from this software without specific prior written permission. 13: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16: */ 17: 18: #if defined(LIBC_SCCS) && !defined(lint) 19: static char sccsid[] = "@(#)rcmd.c 5.20.1 (2.11BSD) 1999/10/24"; 20: #endif /* LIBC_SCCS and not lint */ 21: 22: #include <stdio.h> 23: #include <ctype.h> 24: #include <pwd.h> 25: #include <string.h> 26: #include <sys/param.h> 27: #include <sys/file.h> 28: #include <sys/signal.h> 29: #include <sys/socket.h> 30: #include <sys/stat.h> 31: 32: #include <netinet/in.h> 33: 34: #include <netdb.h> 35: #include <errno.h> 36: 37: rcmd(ahost, rport, locuser, remuser, cmd, fd2p) 38: char **ahost; 39: u_short rport; 40: char *locuser, *remuser, *cmd; 41: int *fd2p; 42: { 43: int s, timo = 1, pid; 44: sigset_t oldmask, nmask; 45: struct sockaddr_in sin, sin2, from; 46: char c; 47: int lport = IPPORT_RESERVED - 1; 48: struct hostent *hp; 49: fd_set reads; 50: 51: pid = getpid(); 52: hp = gethostbyname(*ahost); 53: if (hp == 0) { 54: herror(*ahost); 55: return (-1); 56: } 57: *ahost = hp->h_name; 58: sigemptyset(&nmask); 59: sigaddset(&nmask, SIGURG); 60: (void)sigprocmask(SIG_BLOCK, &nmask, &oldmask); 61: 62: for (;;) { 63: s = rresvport(&lport); 64: if (s < 0) { 65: if (errno == EAGAIN) 66: fprintf(stderr, "socket: All ports in use\n"); 67: else 68: perror("rcmd: socket"); 69: sigprocmask(SIG_SETMASK, &oldmask, NULL); 70: return (-1); 71: } 72: fcntl(s, F_SETOWN, pid); 73: sin.sin_family = hp->h_addrtype; 74: bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr, hp->h_length); 75: sin.sin_port = rport; 76: if (connect(s, (caddr_t)&sin, sizeof (sin), 0) >= 0) 77: break; 78: (void) close(s); 79: if (errno == EADDRINUSE) { 80: lport--; 81: continue; 82: } 83: if (errno == ECONNREFUSED && timo <= 16) { 84: sleep(timo); 85: timo *= 2; 86: continue; 87: } 88: if (hp->h_addr_list[1] != NULL) { 89: int oerrno = errno; 90: 91: fprintf(stderr, 92: "connect to address %s: ", inet_ntoa(sin.sin_addr)); 93: errno = oerrno; 94: perror(0); 95: hp->h_addr_list++; 96: bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr, 97: hp->h_length); 98: fprintf(stderr, "Trying %s...\n", 99: inet_ntoa(sin.sin_addr)); 100: continue; 101: } 102: perror(hp->h_name); 103: sigprocmask(SIG_SETMASK, &oldmask, NULL); 104: return (-1); 105: } 106: lport--; 107: if (fd2p == 0) { 108: write(s, "", 1); 109: lport = 0; 110: } else { 111: char num[8]; 112: int s2 = rresvport(&lport), s3; 113: int len = sizeof (from); 114: 115: if (s2 < 0) 116: goto bad; 117: listen(s2, 1); 118: (void) sprintf(num, "%d", lport); 119: if (write(s, num, strlen(num)+1) != strlen(num)+1) { 120: perror("write: setting up stderr"); 121: (void) close(s2); 122: goto bad; 123: } 124: FD_ZERO(&reads); 125: FD_SET(s, &reads); 126: FD_SET(s2, &reads); 127: errno = 0; 128: if (select(32, &reads, 0, 0, 0) < 1 || 129: !FD_ISSET(s2, &reads)) { 130: if (errno != 0) 131: perror("select: setting up stderr"); 132: else 133: fprintf(stderr, 134: "select: protocol failure in circuit setup.\n"); 135: (void) close(s2); 136: goto bad; 137: } 138: s3 = accept(s2, &from, &len, 0); 139: (void) close(s2); 140: if (s3 < 0) { 141: perror("accept"); 142: lport = 0; 143: goto bad; 144: } 145: *fd2p = s3; 146: from.sin_port = ntohs((u_short)from.sin_port); 147: if (from.sin_family != AF_INET || 148: from.sin_port >= IPPORT_RESERVED || 149: from.sin_port < IPPORT_RESERVED / 2) { 150: fprintf(stderr, 151: "socket: protocol failure in circuit setup.\n"); 152: goto bad2; 153: } 154: } 155: (void) write(s, locuser, strlen(locuser)+1); 156: (void) write(s, remuser, strlen(remuser)+1); 157: (void) write(s, cmd, strlen(cmd)+1); 158: if (read(s, &c, 1) != 1) { 159: perror(*ahost); 160: goto bad2; 161: } 162: if (c != 0) { 163: while (read(s, &c, 1) == 1) { 164: (void) write(2, &c, 1); 165: if (c == '\n') 166: break; 167: } 168: goto bad2; 169: } 170: sigprocmask(SIG_SETMASK, &oldmask, NULL); 171: return (s); 172: bad2: 173: if (lport) 174: (void) close(*fd2p); 175: bad: 176: (void) close(s); 177: sigprocmask(SIG_SETMASK, &oldmask, NULL); 178: return (-1); 179: } 180: 181: rresvport(alport) 182: int *alport; 183: { 184: struct sockaddr_in sin; 185: int s; 186: 187: sin.sin_family = AF_INET; 188: sin.sin_addr.s_addr = INADDR_ANY; 189: s = socket(AF_INET, SOCK_STREAM, 0); 190: if (s < 0) 191: return (-1); 192: for (;;) { 193: sin.sin_port = htons((u_short)*alport); 194: if (bind(s, (caddr_t)&sin, sizeof (sin)) >= 0) 195: return (s); 196: if (errno != EADDRINUSE) { 197: (void) close(s); 198: return (-1); 199: } 200: (*alport)--; 201: if (*alport == IPPORT_RESERVED/2) { 202: (void) close(s); 203: errno = EAGAIN; /* close */ 204: return (-1); 205: } 206: } 207: } 208: 209: int _check_rhosts_file = 1; 210: 211: ruserok(rhost, superuser, ruser, luser) 212: char *rhost; 213: int superuser; 214: char *ruser, *luser; 215: { 216: FILE *hostf; 217: char fhost[MAXHOSTNAMELEN]; 218: int first = 1; 219: register char *sp, *p; 220: int baselen = -1; 221: 222: sp = rhost; 223: p = fhost; 224: while (*sp) { 225: if (*sp == '.') { 226: if (baselen == -1) 227: baselen = sp - rhost; 228: *p++ = *sp++; 229: } else { 230: *p++ = isupper(*sp) ? tolower(*sp++) : *sp++; 231: } 232: } 233: *p = '\0'; 234: hostf = superuser ? (FILE *)0 : fopen("/etc/hosts.equiv", "r"); 235: again: 236: if (hostf) { 237: if (!_validuser(hostf, fhost, luser, ruser, baselen)) { 238: (void) fclose(hostf); 239: return(0); 240: } 241: (void) fclose(hostf); 242: } 243: if (first == 1 && (_check_rhosts_file || superuser)) { 244: struct stat sbuf; 245: struct passwd *pwd; 246: char pbuf[MAXPATHLEN]; 247: 248: first = 0; 249: if ((pwd = getpwnam(luser)) == NULL) 250: return(-1); 251: (void)strcpy(pbuf, pwd->pw_dir); 252: (void)strcat(pbuf, "/.rhosts"); 253: if ((hostf = fopen(pbuf, "r")) == NULL) 254: return(-1); 255: /* 256: * if owned by someone other than user or root or if 257: * writeable by anyone but the owner, quit 258: */ 259: if (fstat(fileno(hostf), &sbuf) || 260: sbuf.st_uid && sbuf.st_uid != pwd->pw_uid || 261: sbuf.st_mode&022) { 262: fclose(hostf); 263: return(-1); 264: } 265: goto again; 266: } 267: return (-1); 268: } 269: 270: /* don't make static, used by lpd(8) */ 271: _validuser(hostf, rhost, luser, ruser, baselen) 272: char *rhost, *luser, *ruser; 273: FILE *hostf; 274: int baselen; 275: { 276: char *user; 277: char ahost[MAXHOSTNAMELEN]; 278: register char *p; 279: 280: while (fgets(ahost, sizeof (ahost), hostf)) { 281: p = ahost; 282: while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') { 283: *p = isupper(*p) ? tolower(*p) : *p; 284: p++; 285: } 286: if (*p == ' ' || *p == '\t') { 287: *p++ = '\0'; 288: while (*p == ' ' || *p == '\t') 289: p++; 290: user = p; 291: while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') 292: p++; 293: } else 294: user = p; 295: *p = '\0'; 296: if (_checkhost(rhost, ahost, baselen) && 297: !strcmp(ruser, *user ? user : luser)) { 298: return (0); 299: } 300: } 301: return (-1); 302: } 303: 304: static 305: _checkhost(rhost, lhost, len) 306: char *rhost, *lhost; 307: int len; 308: { 309: static char ldomain[MAXHOSTNAMELEN + 1]; 310: static char *domainp = NULL; 311: static int nodomain = 0; 312: register char *cp; 313: 314: if (len == -1) 315: return(!strcmp(rhost, lhost)); 316: if (strncmp(rhost, lhost, len)) 317: return(0); 318: if (!strcmp(rhost, lhost)) 319: return(1); 320: if (*(lhost + len) != '\0') 321: return(0); 322: if (nodomain) 323: return(0); 324: if (!domainp) { 325: if (gethostname(ldomain, sizeof(ldomain)) == -1) { 326: nodomain = 1; 327: return(0); 328: } 329: ldomain[MAXHOSTNAMELEN] = NULL; 330: if ((domainp = index(ldomain, '.')) == (char *)NULL) { 331: nodomain = 1; 332: return(0); 333: } 334: for (cp = ++domainp; *cp; ++cp) 335: if (isupper(*cp)) 336: *cp = tolower(*cp); 337: } 338: return(!strcmp(domainp, rhost + len +1)); 339: }