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