Commit | Line | Data |
---|---|---|
586c39b1 DF |
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 | ||
2ce81398 | 7 | #if defined(LIBC_SCCS) && !defined(lint) |
66d34eeb | 8 | static char sccsid[] = "@(#)rcmd.c 5.15 (Berkeley) %G%"; |
2ce81398 | 9 | #endif LIBC_SCCS and not lint |
f0bb4ca8 BJ |
10 | |
11 | #include <stdio.h> | |
20ac274b | 12 | #include <ctype.h> |
eb88aeb4 | 13 | #include <pwd.h> |
20ac274b | 14 | #include <sys/param.h> |
92423502 MK |
15 | #include <sys/file.h> |
16 | #include <sys/signal.h> | |
f0bb4ca8 | 17 | #include <sys/socket.h> |
eb88aeb4 | 18 | #include <sys/stat.h> |
40d6b022 SL |
19 | |
20 | #include <netinet/in.h> | |
21 | ||
3f5b52bc | 22 | #include <netdb.h> |
40d6b022 | 23 | #include <errno.h> |
f0bb4ca8 BJ |
24 | |
25 | extern errno; | |
06eef7c4 | 26 | char *index(); |
f0bb4ca8 BJ |
27 | |
28 | rcmd(ahost, rport, locuser, remuser, cmd, fd2p) | |
29 | char **ahost; | |
9e7d84e3 | 30 | u_short rport; |
f0bb4ca8 BJ |
31 | char *locuser, *remuser, *cmd; |
32 | int *fd2p; | |
33 | { | |
1f83dd8c KB |
34 | int s, timo = 1, pid; |
35 | long oldmask; | |
f0bb4ca8 BJ |
36 | struct sockaddr_in sin, sin2, from; |
37 | char c; | |
40d6b022 | 38 | int lport = IPPORT_RESERVED - 1; |
3f5b52bc | 39 | struct hostent *hp; |
f0bb4ca8 | 40 | |
92423502 | 41 | pid = getpid(); |
3f5b52bc SL |
42 | hp = gethostbyname(*ahost); |
43 | if (hp == 0) { | |
f0bb4ca8 BJ |
44 | fprintf(stderr, "%s: unknown host\n", *ahost); |
45 | return (-1); | |
46 | } | |
3f5b52bc | 47 | *ahost = hp->h_name; |
92423502 MK |
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; | |
ea19968f | 65 | (void) close(s); |
40d6b022 | 66 | if (errno == EADDRINUSE) { |
40d6b022 | 67 | lport--; |
92423502 | 68 | continue; |
40d6b022 | 69 | } |
f0bb4ca8 | 70 | if (errno == ECONNREFUSED && timo <= 16) { |
f0bb4ca8 BJ |
71 | sleep(timo); |
72 | timo *= 2; | |
92423502 MK |
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; | |
f0bb4ca8 | 88 | } |
40d6b022 | 89 | perror(hp->h_name); |
92423502 | 90 | sigsetmask(oldmask); |
f0bb4ca8 BJ |
91 | return (-1); |
92 | } | |
40d6b022 | 93 | lport--; |
f0bb4ca8 BJ |
94 | if (fd2p == 0) { |
95 | write(s, "", 1); | |
c1dfbf19 | 96 | lport = 0; |
f0bb4ca8 BJ |
97 | } else { |
98 | char num[8]; | |
c1dfbf19 | 99 | int s2 = rresvport(&lport), s3; |
ea19968f | 100 | int len = sizeof (from); |
f0bb4ca8 | 101 | |
ea19968f RC |
102 | if (s2 < 0) |
103 | goto bad; | |
40d6b022 | 104 | listen(s2, 1); |
c1dfbf19 | 105 | (void) sprintf(num, "%d", lport); |
2c510808 SL |
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 | } | |
ea19968f RC |
111 | s3 = accept(s2, &from, &len, 0); |
112 | (void) close(s2); | |
113 | if (s3 < 0) { | |
f0bb4ca8 | 114 | perror("accept"); |
c1dfbf19 | 115 | lport = 0; |
f0bb4ca8 BJ |
116 | goto bad; |
117 | } | |
40d6b022 SL |
118 | *fd2p = s3; |
119 | from.sin_port = ntohs((u_short)from.sin_port); | |
f0bb4ca8 BJ |
120 | if (from.sin_family != AF_INET || |
121 | from.sin_port >= IPPORT_RESERVED) { | |
122 | fprintf(stderr, | |
123 | "socket: protocol failure in circuit setup.\n"); | |
40d6b022 | 124 | goto bad2; |
f0bb4ca8 | 125 | } |
f0bb4ca8 BJ |
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); | |
40d6b022 | 132 | goto bad2; |
f0bb4ca8 BJ |
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 | } | |
40d6b022 | 140 | goto bad2; |
f0bb4ca8 | 141 | } |
92423502 | 142 | sigsetmask(oldmask); |
f0bb4ca8 | 143 | return (s); |
40d6b022 | 144 | bad2: |
c1dfbf19 | 145 | if (lport) |
f0bb4ca8 | 146 | (void) close(*fd2p); |
40d6b022 | 147 | bad: |
f0bb4ca8 | 148 | (void) close(s); |
92423502 | 149 | sigsetmask(oldmask); |
f0bb4ca8 BJ |
150 | return (-1); |
151 | } | |
152 | ||
c1dfbf19 SL |
153 | rresvport(alport) |
154 | int *alport; | |
f0bb4ca8 BJ |
155 | { |
156 | struct sockaddr_in sin; | |
f0bb4ca8 BJ |
157 | int s; |
158 | ||
40d6b022 | 159 | sin.sin_family = AF_INET; |
9a89481f MK |
160 | sin.sin_addr.s_addr = INADDR_ANY; |
161 | s = socket(AF_INET, SOCK_STREAM, 0); | |
40d6b022 SL |
162 | if (s < 0) |
163 | return (-1); | |
f0bb4ca8 | 164 | for (;;) { |
40d6b022 | 165 | sin.sin_port = htons((u_short)*alport); |
d277808b | 166 | if (bind(s, (caddr_t)&sin, sizeof (sin)) >= 0) |
f0bb4ca8 | 167 | return (s); |
9a89481f | 168 | if (errno != EADDRINUSE) { |
ea19968f | 169 | (void) close(s); |
f0bb4ca8 BJ |
170 | return (-1); |
171 | } | |
40d6b022 SL |
172 | (*alport)--; |
173 | if (*alport == IPPORT_RESERVED/2) { | |
ea19968f | 174 | (void) close(s); |
0575dce2 | 175 | errno = EAGAIN; /* close */ |
f0bb4ca8 BJ |
176 | return (-1); |
177 | } | |
178 | } | |
179 | } | |
180 | ||
ff3164c8 SL |
181 | ruserok(rhost, superuser, ruser, luser) |
182 | char *rhost; | |
183 | int superuser; | |
184 | char *ruser, *luser; | |
f0bb4ca8 BJ |
185 | { |
186 | FILE *hostf; | |
20ac274b | 187 | char fhost[MAXHOSTNAMELEN]; |
f0bb4ca8 | 188 | int first = 1; |
20ac274b JB |
189 | register char *sp, *p; |
190 | int baselen = -1; | |
f0bb4ca8 | 191 | |
20ac274b JB |
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'; | |
ff3164c8 | 204 | hostf = superuser ? (FILE *)0 : fopen("/etc/hosts.equiv", "r"); |
f0bb4ca8 BJ |
205 | again: |
206 | if (hostf) { | |
9e7d84e3 JB |
207 | if (!_validuser(hostf, fhost, luser, ruser, baselen)) { |
208 | (void) fclose(hostf); | |
209 | return(0); | |
f0bb4ca8 BJ |
210 | } |
211 | (void) fclose(hostf); | |
212 | } | |
213 | if (first == 1) { | |
eb88aeb4 JB |
214 | struct stat sbuf; |
215 | struct passwd *pwd; | |
216 | char pbuf[MAXPATHLEN]; | |
217 | ||
f0bb4ca8 | 218 | first = 0; |
eb88aeb4 JB |
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 | } | |
f0bb4ca8 BJ |
230 | goto again; |
231 | } | |
232 | return (-1); | |
f0bb4ca8 | 233 | } |
20ac274b | 234 | |
9e7d84e3 JB |
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 | ||
20ac274b JB |
268 | _checkhost(rhost, lhost, len) |
269 | char *rhost, *lhost; | |
270 | int len; | |
271 | { | |
426aec69 | 272 | static char ldomain[MAXHOSTNAMELEN + 1]; |
20ac274b | 273 | static char *domainp = NULL; |
1359ea69 | 274 | static int nodomain = 0; |
20ac274b JB |
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); | |
1359ea69 KB |
285 | if (nodomain) |
286 | return(0); | |
20ac274b JB |
287 | if (!domainp) { |
288 | if (gethostname(ldomain, sizeof(ldomain)) == -1) { | |
66d34eeb | 289 | nodomain = 1; |
20ac274b JB |
290 | return(0); |
291 | } | |
292 | ldomain[MAXHOSTNAMELEN] = NULL; | |
1359ea69 KB |
293 | if ((domainp = index(ldomain, '.')) == (char *)NULL) { |
294 | nodomain = 1; | |
49528010 | 295 | return(0); |
9e7d84e3 | 296 | } |
1359ea69 KB |
297 | for (cp = ++domainp; *cp; ++cp) |
298 | if (isupper(*cp)) | |
299 | *cp = tolower(*cp); | |
20ac274b | 300 | } |
20ac274b JB |
301 | return(!strcmp(domainp, rhost + len +1)); |
302 | } |