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.10 (Berkeley) 03/30/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 int 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 char ahost[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 while (fgets(ahost, sizeof (ahost), hostf)) { 208 char *user; 209 210 p = ahost; 211 while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') 212 *p++ = isupper(*p) ? tolower(*p) : *p; 213 if (*p == ' ' || *p == '\t') { 214 *p++ = '\0'; 215 while (*p == ' ' || *p == '\t') 216 p++; 217 user = p; 218 while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') 219 p++; 220 } else 221 user = p; 222 *p = '\0'; 223 if (_checkhost(fhost, ahost, baselen) && 224 !strcmp(ruser, *user ? user : luser)) { 225 (void) fclose(hostf); 226 return (0); 227 } 228 } 229 (void) fclose(hostf); 230 } 231 if (first == 1) { 232 struct stat sbuf; 233 struct passwd *pwd; 234 char pbuf[MAXPATHLEN]; 235 236 first = 0; 237 if ((pwd = getpwnam(luser)) == NULL) 238 return(-1); 239 (void)strcpy(pbuf, pwd->pw_dir); 240 (void)strcat(pbuf, "/.rhosts"); 241 if ((hostf = fopen(pbuf, "r")) == NULL) 242 return(-1); 243 (void)fstat(fileno(hostf), &sbuf); 244 if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid) { 245 fclose(hostf); 246 return(-1); 247 } 248 goto again; 249 } 250 return (-1); 251 } 252 253 _checkhost(rhost, lhost, len) 254 char *rhost, *lhost; 255 int len; 256 { 257 static char ldomain[MAXHOSTNAMELEN + 1]; 258 static char *domainp = NULL; 259 register char *cp; 260 261 if (len == -1) 262 return(!strcmp(rhost, lhost)); 263 if (strncmp(rhost, lhost, len)) 264 return(0); 265 if (!strcmp(rhost, lhost)) 266 return(1); 267 if (*(lhost + len) != '\0') 268 return(0); 269 if (!domainp) { 270 if (gethostname(ldomain, sizeof(ldomain)) == -1) { 271 domainp = (char *)1; 272 return(0); 273 } 274 ldomain[MAXHOSTNAMELEN] = NULL; 275 if ((domainp = index(ldomain, '.') + 1) == (char *)1) 276 return(0); 277 cp = domainp; 278 while (*cp) 279 *cp++ = isupper(*cp) ? tolower(*cp) : *cp; 280 } 281 if (domainp == (char *)1) 282 return(0); 283 return(!strcmp(domainp, rhost + len +1)); 284 } 285