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