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.18 (Berkeley) 10/11/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_addr.s_addr = INADDR_ANY; 172 s = socket(AF_INET, SOCK_STREAM, 0); 173 if (s < 0) 174 return (-1); 175 for (;;) { 176 sin.sin_port = htons((u_short)*alport); 177 if (bind(s, (caddr_t)&sin, sizeof (sin)) >= 0) 178 return (s); 179 if (errno != EADDRINUSE) { 180 (void) close(s); 181 return (-1); 182 } 183 (*alport)--; 184 if (*alport == IPPORT_RESERVED/2) { 185 (void) close(s); 186 errno = EAGAIN; /* close */ 187 return (-1); 188 } 189 } 190 } 191 192 ruserok(rhost, superuser, ruser, luser) 193 char *rhost; 194 int superuser; 195 char *ruser, *luser; 196 { 197 FILE *hostf; 198 char fhost[MAXHOSTNAMELEN]; 199 int first = 1; 200 register char *sp, *p; 201 int baselen = -1; 202 203 sp = rhost; 204 p = fhost; 205 while (*sp) { 206 if (*sp == '.') { 207 if (baselen == -1) 208 baselen = sp - rhost; 209 *p++ = *sp++; 210 } else { 211 *p++ = isupper(*sp) ? tolower(*sp++) : *sp++; 212 } 213 } 214 *p = '\0'; 215 hostf = superuser ? (FILE *)0 : fopen("/etc/hosts.equiv", "r"); 216 again: 217 if (hostf) { 218 if (!_validuser(hostf, fhost, luser, ruser, baselen)) { 219 (void) fclose(hostf); 220 return(0); 221 } 222 (void) fclose(hostf); 223 } 224 if (first == 1) { 225 struct stat sbuf; 226 struct passwd *pwd; 227 char pbuf[MAXPATHLEN]; 228 229 first = 0; 230 if ((pwd = getpwnam(luser)) == NULL) 231 return(-1); 232 (void)strcpy(pbuf, pwd->pw_dir); 233 (void)strcat(pbuf, "/.rhosts"); 234 if ((hostf = fopen(pbuf, "r")) == NULL) 235 return(-1); 236 (void)fstat(fileno(hostf), &sbuf); 237 if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid) { 238 fclose(hostf); 239 return(-1); 240 } 241 goto again; 242 } 243 return (-1); 244 } 245 246 _validuser(hostf, rhost, luser, ruser, baselen) 247 char *rhost, *luser, *ruser; 248 FILE *hostf; 249 int baselen; 250 { 251 char *user; 252 char ahost[MAXHOSTNAMELEN]; 253 register char *p; 254 255 while (fgets(ahost, sizeof (ahost), hostf)) { 256 p = ahost; 257 while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') { 258 *p = isupper(*p) ? tolower(*p) : *p; 259 p++; 260 } 261 if (*p == ' ' || *p == '\t') { 262 *p++ = '\0'; 263 while (*p == ' ' || *p == '\t') 264 p++; 265 user = p; 266 while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') 267 p++; 268 } else 269 user = p; 270 *p = '\0'; 271 if (_checkhost(rhost, ahost, baselen) && 272 !strcmp(ruser, *user ? user : luser)) { 273 return (0); 274 } 275 } 276 return (-1); 277 } 278 279 _checkhost(rhost, lhost, len) 280 char *rhost, *lhost; 281 int len; 282 { 283 static char ldomain[MAXHOSTNAMELEN + 1]; 284 static char *domainp = NULL; 285 static int nodomain = 0; 286 register char *cp; 287 288 if (len == -1) 289 return(!strcmp(rhost, lhost)); 290 if (strncmp(rhost, lhost, len)) 291 return(0); 292 if (!strcmp(rhost, lhost)) 293 return(1); 294 if (*(lhost + len) != '\0') 295 return(0); 296 if (nodomain) 297 return(0); 298 if (!domainp) { 299 if (gethostname(ldomain, sizeof(ldomain)) == -1) { 300 nodomain = 1; 301 return(0); 302 } 303 ldomain[MAXHOSTNAMELEN] = NULL; 304 if ((domainp = index(ldomain, '.')) == (char *)NULL) { 305 nodomain = 1; 306 return(0); 307 } 308 for (cp = ++domainp; *cp; ++cp) 309 if (isupper(*cp)) 310 *cp = tolower(*cp); 311 } 312 return(!strcmp(domainp, rhost + len +1)); 313 } 314