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