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