1 /* 2 * Copyright (c) 1983 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 #if defined(LIBC_SCCS) && !defined(lint) 8 static char sccsid[] = "@(#)rcmd.c 5.14 (Berkeley) 10/22/87"; 9 #endif LIBC_SCCS and not lint 10 11 #include <stdio.h> 12 #include <ctype.h> 13 #include <pwd.h> 14 #include <sys/param.h> 15 #include <sys/file.h> 16 #include <sys/signal.h> 17 #include <sys/socket.h> 18 #include <sys/stat.h> 19 20 #include <netinet/in.h> 21 22 #include <netdb.h> 23 #include <errno.h> 24 25 extern errno; 26 char *index(); 27 28 rcmd(ahost, rport, locuser, remuser, cmd, fd2p) 29 char **ahost; 30 u_short rport; 31 char *locuser, *remuser, *cmd; 32 int *fd2p; 33 { 34 int s, timo = 1, pid; 35 long oldmask; 36 struct sockaddr_in sin, sin2, from; 37 char c; 38 int lport = IPPORT_RESERVED - 1; 39 struct hostent *hp; 40 41 pid = getpid(); 42 hp = gethostbyname(*ahost); 43 if (hp == 0) { 44 fprintf(stderr, "%s: unknown host\n", *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, (caddr_t)&sin, sizeof (sin), 0) >= 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 s3 = accept(s2, &from, &len, 0); 112 (void) close(s2); 113 if (s3 < 0) { 114 perror("accept"); 115 lport = 0; 116 goto bad; 117 } 118 *fd2p = s3; 119 from.sin_port = ntohs((u_short)from.sin_port); 120 if (from.sin_family != AF_INET || 121 from.sin_port >= IPPORT_RESERVED) { 122 fprintf(stderr, 123 "socket: protocol failure in circuit setup.\n"); 124 goto bad2; 125 } 126 } 127 (void) write(s, locuser, strlen(locuser)+1); 128 (void) write(s, remuser, strlen(remuser)+1); 129 (void) write(s, cmd, strlen(cmd)+1); 130 if (read(s, &c, 1) != 1) { 131 perror(*ahost); 132 goto bad2; 133 } 134 if (c != 0) { 135 while (read(s, &c, 1) == 1) { 136 (void) write(2, &c, 1); 137 if (c == '\n') 138 break; 139 } 140 goto bad2; 141 } 142 sigsetmask(oldmask); 143 return (s); 144 bad2: 145 if (lport) 146 (void) close(*fd2p); 147 bad: 148 (void) close(s); 149 sigsetmask(oldmask); 150 return (-1); 151 } 152 153 rresvport(alport) 154 int *alport; 155 { 156 struct sockaddr_in sin; 157 int s; 158 159 sin.sin_family = AF_INET; 160 sin.sin_addr.s_addr = INADDR_ANY; 161 s = socket(AF_INET, SOCK_STREAM, 0); 162 if (s < 0) 163 return (-1); 164 for (;;) { 165 sin.sin_port = htons((u_short)*alport); 166 if (bind(s, (caddr_t)&sin, sizeof (sin)) >= 0) 167 return (s); 168 if (errno != EADDRINUSE) { 169 (void) close(s); 170 return (-1); 171 } 172 (*alport)--; 173 if (*alport == IPPORT_RESERVED/2) { 174 (void) close(s); 175 errno = EAGAIN; /* close */ 176 return (-1); 177 } 178 } 179 } 180 181 ruserok(rhost, superuser, ruser, luser) 182 char *rhost; 183 int superuser; 184 char *ruser, *luser; 185 { 186 FILE *hostf; 187 char fhost[MAXHOSTNAMELEN]; 188 int first = 1; 189 register char *sp, *p; 190 int baselen = -1; 191 192 sp = rhost; 193 p = fhost; 194 while (*sp) { 195 if (*sp == '.') { 196 if (baselen == -1) 197 baselen = sp - rhost; 198 *p++ = *sp++; 199 } else { 200 *p++ = isupper(*sp) ? tolower(*sp++) : *sp++; 201 } 202 } 203 *p = '\0'; 204 hostf = superuser ? (FILE *)0 : fopen("/etc/hosts.equiv", "r"); 205 again: 206 if (hostf) { 207 if (!_validuser(hostf, fhost, luser, ruser, baselen)) { 208 (void) fclose(hostf); 209 return(0); 210 } 211 (void) fclose(hostf); 212 } 213 if (first == 1) { 214 struct stat sbuf; 215 struct passwd *pwd; 216 char pbuf[MAXPATHLEN]; 217 218 first = 0; 219 if ((pwd = getpwnam(luser)) == NULL) 220 return(-1); 221 (void)strcpy(pbuf, pwd->pw_dir); 222 (void)strcat(pbuf, "/.rhosts"); 223 if ((hostf = fopen(pbuf, "r")) == NULL) 224 return(-1); 225 (void)fstat(fileno(hostf), &sbuf); 226 if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid) { 227 fclose(hostf); 228 return(-1); 229 } 230 goto again; 231 } 232 return (-1); 233 } 234 235 _validuser(hostf, rhost, luser, ruser, baselen) 236 char *rhost, *luser, *ruser; 237 FILE *hostf; 238 int baselen; 239 { 240 char *user; 241 char ahost[MAXHOSTNAMELEN]; 242 register char *p; 243 244 while (fgets(ahost, sizeof (ahost), hostf)) { 245 p = ahost; 246 while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') { 247 *p = isupper(*p) ? tolower(*p) : *p; 248 p++; 249 } 250 if (*p == ' ' || *p == '\t') { 251 *p++ = '\0'; 252 while (*p == ' ' || *p == '\t') 253 p++; 254 user = p; 255 while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') 256 p++; 257 } else 258 user = p; 259 *p = '\0'; 260 if (_checkhost(rhost, ahost, baselen) && 261 !strcmp(ruser, *user ? user : luser)) { 262 return (0); 263 } 264 } 265 return (-1); 266 } 267 268 _checkhost(rhost, lhost, len) 269 char *rhost, *lhost; 270 int len; 271 { 272 static char ldomain[MAXHOSTNAMELEN + 1]; 273 static char *domainp = NULL; 274 static int nodomain = 0; 275 register char *cp; 276 277 if (len == -1) 278 return(!strcmp(rhost, lhost)); 279 if (strncmp(rhost, lhost, len)) 280 return(0); 281 if (!strcmp(rhost, lhost)) 282 return(1); 283 if (*(lhost + len) != '\0') 284 return(0); 285 if (nodomain) 286 return(0); 287 if (!domainp) { 288 if (gethostname(ldomain, sizeof(ldomain)) == -1) { 289 domainp = (char *)1; 290 return(0); 291 } 292 ldomain[MAXHOSTNAMELEN] = NULL; 293 if ((domainp = index(ldomain, '.')) == (char *)NULL) { 294 nodomain = 1; 295 return(0); 296 } 297 for (cp = ++domainp; *cp; ++cp) 298 if (isupper(*cp)) 299 *cp = tolower(*cp); 300 } 301 return(!strcmp(domainp, rhost + len +1)); 302 } 303