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 #ifndef lint 8 static char sccsid[] = "@(#)rcmd.c 5.8 (Berkeley) 10/25/85"; 9 #endif not lint 10 11 #include <stdio.h> 12 #include <ctype.h> 13 #include <pwd.h> 14 #include <sys/param.h> 15 #include <sys/socket.h> 16 #include <sys/stat.h> 17 18 #include <netinet/in.h> 19 20 #include <netdb.h> 21 #include <errno.h> 22 23 extern errno; 24 char *index(), *sprintf(); 25 26 rcmd(ahost, rport, locuser, remuser, cmd, fd2p) 27 char **ahost; 28 int rport; 29 char *locuser, *remuser, *cmd; 30 int *fd2p; 31 { 32 int s, timo = 1; 33 struct sockaddr_in sin, sin2, from; 34 char c; 35 int lport = IPPORT_RESERVED - 1; 36 struct hostent *hp; 37 38 hp = gethostbyname(*ahost); 39 if (hp == 0) { 40 fprintf(stderr, "%s: unknown host\n", *ahost); 41 return (-1); 42 } 43 *ahost = hp->h_name; 44 retry: 45 s = rresvport(&lport); 46 if (s < 0) { 47 if (errno == EAGAIN) 48 fprintf(stderr, "socket: All ports in use\n"); 49 else 50 perror("rcmd: socket"); 51 return (-1); 52 } 53 sin.sin_family = hp->h_addrtype; 54 bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length); 55 sin.sin_port = rport; 56 if (connect(s, (caddr_t)&sin, sizeof (sin), 0) < 0) { 57 (void) close(s); 58 if (errno == EADDRINUSE) { 59 lport--; 60 goto retry; 61 } 62 if (errno == ECONNREFUSED && timo <= 16) { 63 sleep(timo); 64 timo *= 2; 65 goto retry; 66 } 67 perror(hp->h_name); 68 return (-1); 69 } 70 lport--; 71 if (fd2p == 0) { 72 write(s, "", 1); 73 lport = 0; 74 } else { 75 char num[8]; 76 int s2 = rresvport(&lport), s3; 77 int len = sizeof (from); 78 79 if (s2 < 0) 80 goto bad; 81 listen(s2, 1); 82 (void) sprintf(num, "%d", lport); 83 if (write(s, num, strlen(num)+1) != strlen(num)+1) { 84 perror("write: setting up stderr"); 85 (void) close(s2); 86 goto bad; 87 } 88 s3 = accept(s2, &from, &len, 0); 89 (void) close(s2); 90 if (s3 < 0) { 91 perror("accept"); 92 lport = 0; 93 goto bad; 94 } 95 *fd2p = s3; 96 from.sin_port = ntohs((u_short)from.sin_port); 97 if (from.sin_family != AF_INET || 98 from.sin_port >= IPPORT_RESERVED) { 99 fprintf(stderr, 100 "socket: protocol failure in circuit setup.\n"); 101 goto bad2; 102 } 103 } 104 (void) write(s, locuser, strlen(locuser)+1); 105 (void) write(s, remuser, strlen(remuser)+1); 106 (void) write(s, cmd, strlen(cmd)+1); 107 if (read(s, &c, 1) != 1) { 108 perror(*ahost); 109 goto bad2; 110 } 111 if (c != 0) { 112 while (read(s, &c, 1) == 1) { 113 (void) write(2, &c, 1); 114 if (c == '\n') 115 break; 116 } 117 goto bad2; 118 } 119 return (s); 120 bad2: 121 if (lport) 122 (void) close(*fd2p); 123 bad: 124 (void) close(s); 125 return (-1); 126 } 127 128 rresvport(alport) 129 int *alport; 130 { 131 struct sockaddr_in sin; 132 int s; 133 134 sin.sin_family = AF_INET; 135 sin.sin_addr.s_addr = INADDR_ANY; 136 s = socket(AF_INET, SOCK_STREAM, 0); 137 if (s < 0) 138 return (-1); 139 for (;;) { 140 sin.sin_port = htons((u_short)*alport); 141 if (bind(s, (caddr_t)&sin, sizeof (sin)) >= 0) 142 return (s); 143 if (errno != EADDRINUSE) { 144 (void) close(s); 145 return (-1); 146 } 147 (*alport)--; 148 if (*alport == IPPORT_RESERVED/2) { 149 (void) close(s); 150 errno = EAGAIN; /* close */ 151 return (-1); 152 } 153 } 154 } 155 156 ruserok(rhost, superuser, ruser, luser) 157 char *rhost; 158 int superuser; 159 char *ruser, *luser; 160 { 161 FILE *hostf; 162 char fhost[MAXHOSTNAMELEN]; 163 char ahost[MAXHOSTNAMELEN]; 164 int first = 1; 165 register char *sp, *p; 166 int baselen = -1; 167 168 sp = rhost; 169 p = fhost; 170 while (*sp) { 171 if (*sp == '.') { 172 if (baselen == -1) 173 baselen = sp - rhost; 174 *p++ = *sp++; 175 } else { 176 *p++ = isupper(*sp) ? tolower(*sp++) : *sp++; 177 } 178 } 179 *p = '\0'; 180 hostf = superuser ? (FILE *)0 : fopen("/etc/hosts.equiv", "r"); 181 again: 182 if (hostf) { 183 while (fgets(ahost, sizeof (ahost), hostf)) { 184 char *user; 185 186 p = ahost; 187 while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') 188 *p++ = isupper(*p) ? tolower(*p) : *p; 189 if (*p == ' ' || *p == '\t') { 190 *p++ = '\0'; 191 while (*p == ' ' || *p == '\t') 192 p++; 193 user = p; 194 while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') 195 p++; 196 } else 197 user = p; 198 *p = '\0'; 199 if (_checkhost(fhost, ahost, baselen) && 200 !strcmp(ruser, *user ? user : luser)) { 201 (void) fclose(hostf); 202 return (0); 203 } 204 } 205 (void) fclose(hostf); 206 } 207 if (first == 1) { 208 struct stat sbuf; 209 struct passwd *pwd; 210 char pbuf[MAXPATHLEN]; 211 212 first = 0; 213 if ((pwd = getpwnam(luser)) == NULL) 214 return(-1); 215 (void)strcpy(pbuf, pwd->pw_dir); 216 (void)strcat(pbuf, "/.rhosts"); 217 if ((hostf = fopen(pbuf, "r")) == NULL) 218 return(-1); 219 (void)fstat(fileno(hostf), &sbuf); 220 if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid) { 221 fclose(hostf); 222 return(-1); 223 } 224 goto again; 225 } 226 return (-1); 227 } 228 229 _checkhost(rhost, lhost, len) 230 char *rhost, *lhost; 231 int len; 232 { 233 static char ldomain[MAXHOSTNAMELEN + 1]; 234 static char *domainp = NULL; 235 register char *cp; 236 237 if (len == -1) 238 return(!strcmp(rhost, lhost)); 239 if (strncmp(rhost, lhost, len)) 240 return(0); 241 if (!strcmp(rhost, lhost)) 242 return(1); 243 if (*(lhost + len) != '\0') 244 return(0); 245 if (!domainp) { 246 if (gethostname(ldomain, sizeof(ldomain)) == -1) { 247 domainp = (char *)1; 248 return(0); 249 } 250 ldomain[MAXHOSTNAMELEN] = NULL; 251 if ((domainp = index(ldomain, '.') + 1) == (char *)1) 252 return(0); 253 cp = domainp; 254 while (*cp) 255 *cp++ = isupper(*cp) ? tolower(*cp) : *cp; 256 } 257 if (domainp == (char *)1) 258 return(0); 259 return(!strcmp(domainp, rhost + len +1)); 260 } 261