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 | ||
f0bb4ca8 | 7 | #ifndef lint |
d277808b | 8 | static char sccsid[] = "@(#)rcmd.c 5.8 (Berkeley) %G%"; |
586c39b1 | 9 | #endif 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> |
f0bb4ca8 | 15 | #include <sys/socket.h> |
eb88aeb4 | 16 | #include <sys/stat.h> |
40d6b022 SL |
17 | |
18 | #include <netinet/in.h> | |
19 | ||
3f5b52bc | 20 | #include <netdb.h> |
40d6b022 | 21 | #include <errno.h> |
f0bb4ca8 BJ |
22 | |
23 | extern errno; | |
24 | char *index(), *sprintf(); | |
f0bb4ca8 BJ |
25 | |
26 | rcmd(ahost, rport, locuser, remuser, cmd, fd2p) | |
27 | char **ahost; | |
28 | int rport; | |
29 | char *locuser, *remuser, *cmd; | |
30 | int *fd2p; | |
31 | { | |
40d6b022 | 32 | int s, timo = 1; |
f0bb4ca8 BJ |
33 | struct sockaddr_in sin, sin2, from; |
34 | char c; | |
40d6b022 | 35 | int lport = IPPORT_RESERVED - 1; |
3f5b52bc | 36 | struct hostent *hp; |
f0bb4ca8 | 37 | |
3f5b52bc SL |
38 | hp = gethostbyname(*ahost); |
39 | if (hp == 0) { | |
f0bb4ca8 BJ |
40 | fprintf(stderr, "%s: unknown host\n", *ahost); |
41 | return (-1); | |
42 | } | |
3f5b52bc | 43 | *ahost = hp->h_name; |
f0bb4ca8 | 44 | retry: |
c1dfbf19 | 45 | s = rresvport(&lport); |
0575dce2 MK |
46 | if (s < 0) { |
47 | if (errno == EAGAIN) | |
48 | fprintf(stderr, "socket: All ports in use\n"); | |
49 | else | |
50 | perror("rcmd: socket"); | |
f0bb4ca8 | 51 | return (-1); |
0575dce2 | 52 | } |
3f5b52bc | 53 | sin.sin_family = hp->h_addrtype; |
40d6b022 | 54 | bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length); |
b567f18d | 55 | sin.sin_port = rport; |
40d6b022 | 56 | if (connect(s, (caddr_t)&sin, sizeof (sin), 0) < 0) { |
ea19968f | 57 | (void) close(s); |
40d6b022 | 58 | if (errno == EADDRINUSE) { |
40d6b022 SL |
59 | lport--; |
60 | goto retry; | |
61 | } | |
f0bb4ca8 | 62 | if (errno == ECONNREFUSED && timo <= 16) { |
f0bb4ca8 BJ |
63 | sleep(timo); |
64 | timo *= 2; | |
65 | goto retry; | |
66 | } | |
40d6b022 | 67 | perror(hp->h_name); |
f0bb4ca8 BJ |
68 | return (-1); |
69 | } | |
40d6b022 | 70 | lport--; |
f0bb4ca8 BJ |
71 | if (fd2p == 0) { |
72 | write(s, "", 1); | |
c1dfbf19 | 73 | lport = 0; |
f0bb4ca8 BJ |
74 | } else { |
75 | char num[8]; | |
c1dfbf19 | 76 | int s2 = rresvport(&lport), s3; |
ea19968f | 77 | int len = sizeof (from); |
f0bb4ca8 | 78 | |
ea19968f RC |
79 | if (s2 < 0) |
80 | goto bad; | |
40d6b022 | 81 | listen(s2, 1); |
c1dfbf19 | 82 | (void) sprintf(num, "%d", lport); |
2c510808 SL |
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 | } | |
ea19968f RC |
88 | s3 = accept(s2, &from, &len, 0); |
89 | (void) close(s2); | |
90 | if (s3 < 0) { | |
f0bb4ca8 | 91 | perror("accept"); |
c1dfbf19 | 92 | lport = 0; |
f0bb4ca8 BJ |
93 | goto bad; |
94 | } | |
40d6b022 SL |
95 | *fd2p = s3; |
96 | from.sin_port = ntohs((u_short)from.sin_port); | |
f0bb4ca8 BJ |
97 | if (from.sin_family != AF_INET || |
98 | from.sin_port >= IPPORT_RESERVED) { | |
99 | fprintf(stderr, | |
100 | "socket: protocol failure in circuit setup.\n"); | |
40d6b022 | 101 | goto bad2; |
f0bb4ca8 | 102 | } |
f0bb4ca8 BJ |
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); | |
40d6b022 | 109 | goto bad2; |
f0bb4ca8 BJ |
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 | } | |
40d6b022 | 117 | goto bad2; |
f0bb4ca8 BJ |
118 | } |
119 | return (s); | |
40d6b022 | 120 | bad2: |
c1dfbf19 | 121 | if (lport) |
f0bb4ca8 | 122 | (void) close(*fd2p); |
40d6b022 | 123 | bad: |
f0bb4ca8 BJ |
124 | (void) close(s); |
125 | return (-1); | |
126 | } | |
127 | ||
c1dfbf19 SL |
128 | rresvport(alport) |
129 | int *alport; | |
f0bb4ca8 BJ |
130 | { |
131 | struct sockaddr_in sin; | |
f0bb4ca8 BJ |
132 | int s; |
133 | ||
40d6b022 | 134 | sin.sin_family = AF_INET; |
9a89481f MK |
135 | sin.sin_addr.s_addr = INADDR_ANY; |
136 | s = socket(AF_INET, SOCK_STREAM, 0); | |
40d6b022 SL |
137 | if (s < 0) |
138 | return (-1); | |
f0bb4ca8 | 139 | for (;;) { |
40d6b022 | 140 | sin.sin_port = htons((u_short)*alport); |
d277808b | 141 | if (bind(s, (caddr_t)&sin, sizeof (sin)) >= 0) |
f0bb4ca8 | 142 | return (s); |
9a89481f | 143 | if (errno != EADDRINUSE) { |
ea19968f | 144 | (void) close(s); |
f0bb4ca8 BJ |
145 | return (-1); |
146 | } | |
40d6b022 SL |
147 | (*alport)--; |
148 | if (*alport == IPPORT_RESERVED/2) { | |
ea19968f | 149 | (void) close(s); |
0575dce2 | 150 | errno = EAGAIN; /* close */ |
f0bb4ca8 BJ |
151 | return (-1); |
152 | } | |
153 | } | |
154 | } | |
155 | ||
ff3164c8 SL |
156 | ruserok(rhost, superuser, ruser, luser) |
157 | char *rhost; | |
158 | int superuser; | |
159 | char *ruser, *luser; | |
f0bb4ca8 BJ |
160 | { |
161 | FILE *hostf; | |
20ac274b JB |
162 | char fhost[MAXHOSTNAMELEN]; |
163 | char ahost[MAXHOSTNAMELEN]; | |
f0bb4ca8 | 164 | int first = 1; |
20ac274b JB |
165 | register char *sp, *p; |
166 | int baselen = -1; | |
f0bb4ca8 | 167 | |
20ac274b JB |
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'; | |
ff3164c8 | 180 | hostf = superuser ? (FILE *)0 : fopen("/etc/hosts.equiv", "r"); |
f0bb4ca8 BJ |
181 | again: |
182 | if (hostf) { | |
183 | while (fgets(ahost, sizeof (ahost), hostf)) { | |
184 | char *user; | |
7620d83a JB |
185 | |
186 | p = ahost; | |
187 | while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') | |
20ac274b | 188 | *p++ = isupper(*p) ? tolower(*p) : *p; |
7620d83a JB |
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'; | |
20ac274b | 199 | if (_checkhost(fhost, ahost, baselen) && |
7620d83a | 200 | !strcmp(ruser, *user ? user : luser)) { |
ff3164c8 SL |
201 | (void) fclose(hostf); |
202 | return (0); | |
203 | } | |
f0bb4ca8 BJ |
204 | } |
205 | (void) fclose(hostf); | |
206 | } | |
207 | if (first == 1) { | |
eb88aeb4 JB |
208 | struct stat sbuf; |
209 | struct passwd *pwd; | |
210 | char pbuf[MAXPATHLEN]; | |
211 | ||
f0bb4ca8 | 212 | first = 0; |
eb88aeb4 JB |
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 | } | |
f0bb4ca8 BJ |
224 | goto again; |
225 | } | |
226 | return (-1); | |
f0bb4ca8 | 227 | } |
20ac274b JB |
228 | |
229 | _checkhost(rhost, lhost, len) | |
230 | char *rhost, *lhost; | |
231 | int len; | |
232 | { | |
426aec69 | 233 | static char ldomain[MAXHOSTNAMELEN + 1]; |
20ac274b JB |
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; | |
49528010 JB |
251 | if ((domainp = index(ldomain, '.') + 1) == (char *)1) |
252 | return(0); | |
20ac274b JB |
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 | } |