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