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