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.23 (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 <unistd.h> 24 #include <string.h> 25 26 rcmd(ahost, rport, locuser, remuser, cmd, fd2p) 27 char **ahost; 28 u_short rport; 29 const char *locuser, *remuser, *cmd; 30 int *fd2p; 31 { 32 int s, timo = 1, pid; 33 long oldmask; 34 struct sockaddr_in sin, sin2, from; 35 char c; 36 int lport = IPPORT_RESERVED - 1; 37 struct hostent *hp; 38 fd_set reads; 39 40 pid = getpid(); 41 hp = gethostbyname(*ahost); 42 if (hp == 0) { 43 herror(*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, (struct sockaddr *)&sin, sizeof(sin)) >= 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 FD_ZERO(&reads); 111 FD_SET(s, &reads); 112 FD_SET(s2, &reads); 113 errno = 0; 114 if (select(32, &reads, 0, 0, 0) < 1 || 115 !FD_ISSET(s2, &reads)) { 116 if (errno != 0) 117 perror("select: setting up stderr"); 118 else 119 fprintf(stderr, 120 "select: protocol failure in circuit setup.\n"); 121 (void) close(s2); 122 goto bad; 123 } 124 s3 = accept(s2, (struct sockaddr *)&from, &len); 125 (void) close(s2); 126 if (s3 < 0) { 127 perror("accept"); 128 lport = 0; 129 goto bad; 130 } 131 *fd2p = s3; 132 from.sin_port = ntohs((u_short)from.sin_port); 133 if (from.sin_family != AF_INET || 134 from.sin_port >= IPPORT_RESERVED || 135 from.sin_port < IPPORT_RESERVED / 2) { 136 fprintf(stderr, 137 "socket: protocol failure in circuit setup.\n"); 138 goto bad2; 139 } 140 } 141 (void) write(s, locuser, strlen(locuser)+1); 142 (void) write(s, remuser, strlen(remuser)+1); 143 (void) write(s, cmd, strlen(cmd)+1); 144 if (read(s, &c, 1) != 1) { 145 perror(*ahost); 146 goto bad2; 147 } 148 if (c != 0) { 149 while (read(s, &c, 1) == 1) { 150 (void) write(2, &c, 1); 151 if (c == '\n') 152 break; 153 } 154 goto bad2; 155 } 156 sigsetmask(oldmask); 157 return (s); 158 bad2: 159 if (lport) 160 (void) close(*fd2p); 161 bad: 162 (void) close(s); 163 sigsetmask(oldmask); 164 return (-1); 165 } 166 167 rresvport(alport) 168 int *alport; 169 { 170 struct sockaddr_in sin; 171 int s; 172 173 sin.sin_family = AF_INET; 174 sin.sin_addr.s_addr = INADDR_ANY; 175 s = socket(AF_INET, SOCK_STREAM, 0); 176 if (s < 0) 177 return (-1); 178 for (;;) { 179 sin.sin_port = htons((u_short)*alport); 180 if (bind(s, (struct sockaddr *)&sin, sizeof (sin)) >= 0) 181 return (s); 182 if (errno != EADDRINUSE) { 183 (void) close(s); 184 return (-1); 185 } 186 (*alport)--; 187 if (*alport == IPPORT_RESERVED/2) { 188 (void) close(s); 189 errno = EAGAIN; /* close */ 190 return (-1); 191 } 192 } 193 } 194 195 int _check_rhosts_file = 1; 196 197 ruserok(rhost, superuser, ruser, luser) 198 const char *rhost, *ruser, *luser; 199 int superuser; 200 { 201 FILE *hostf; 202 char fhost[MAXHOSTNAMELEN]; 203 int first = 1; 204 register char *sp, *p; 205 int baselen = -1; 206 207 sp = (char *)rhost; 208 p = fhost; 209 while (*sp) { 210 if (*sp == '.') { 211 if (baselen == -1) 212 baselen = sp - rhost; 213 *p++ = *sp++; 214 } else { 215 *p++ = isupper(*sp) ? tolower(*sp++) : *sp++; 216 } 217 } 218 *p = '\0'; 219 hostf = superuser ? (FILE *)0 : fopen(_PATH_HEQUIV, "r"); 220 again: 221 if (hostf) { 222 if (!_validuser(hostf, fhost, luser, ruser, baselen)) { 223 (void) fclose(hostf); 224 return(0); 225 } 226 (void) fclose(hostf); 227 } 228 if (first == 1 && (_check_rhosts_file || superuser)) { 229 struct stat sbuf; 230 struct passwd *pwd; 231 char pbuf[MAXPATHLEN]; 232 233 first = 0; 234 if ((pwd = getpwnam(luser)) == NULL) 235 return(-1); 236 (void)strcpy(pbuf, pwd->pw_dir); 237 (void)strcat(pbuf, "/.rhosts"); 238 if ((hostf = fopen(pbuf, "r")) == NULL) 239 return(-1); 240 /* 241 * if owned by someone other than user or root or if 242 * writeable by anyone but the owner, quit 243 */ 244 if (fstat(fileno(hostf), &sbuf) || 245 sbuf.st_uid && sbuf.st_uid != pwd->pw_uid || 246 sbuf.st_mode&022) { 247 fclose(hostf); 248 return(-1); 249 } 250 goto again; 251 } 252 return (-1); 253 } 254 255 /* don't make static, used by lpd(8) */ 256 _validuser(hostf, rhost, luser, ruser, baselen) 257 char *rhost, *luser, *ruser; 258 FILE *hostf; 259 int baselen; 260 { 261 register char *p; 262 char *user, ahost[MAXHOSTNAMELEN]; 263 static int _checkhost(); 264 265 while (fgets(ahost, sizeof (ahost), hostf)) { 266 p = ahost; 267 while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') { 268 *p = isupper(*p) ? tolower(*p) : *p; 269 p++; 270 } 271 if (*p == ' ' || *p == '\t') { 272 *p++ = '\0'; 273 while (*p == ' ' || *p == '\t') 274 p++; 275 user = p; 276 while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') 277 p++; 278 } else 279 user = p; 280 *p = '\0'; 281 if (_checkhost(rhost, ahost, baselen) && 282 !strcmp(ruser, *user ? user : luser)) { 283 return (0); 284 } 285 } 286 return (-1); 287 } 288 289 static 290 _checkhost(rhost, lhost, len) 291 char *rhost, *lhost; 292 int len; 293 { 294 static char ldomain[MAXHOSTNAMELEN + 1]; 295 static char *domainp = NULL; 296 static int nodomain = 0; 297 register char *cp; 298 299 if (len == -1) 300 return(!strcmp(rhost, lhost)); 301 if (strncmp(rhost, lhost, len)) 302 return(0); 303 if (!strcmp(rhost, lhost)) 304 return(1); 305 if (*(lhost + len) != '\0') 306 return(0); 307 if (nodomain) 308 return(0); 309 if (!domainp) { 310 if (gethostname(ldomain, sizeof(ldomain)) == -1) { 311 nodomain = 1; 312 return(0); 313 } 314 ldomain[MAXHOSTNAMELEN] = NULL; 315 if ((domainp = index(ldomain, '.')) == (char *)NULL) { 316 nodomain = 1; 317 return(0); 318 } 319 for (cp = ++domainp; *cp; ++cp) 320 if (isupper(*cp)) 321 *cp = tolower(*cp); 322 } 323 return(!strcmp(domainp, rhost + len +1)); 324 } 325