bring up to rev 6
[unix-history] / usr / src / lib / libc / net / rcmd.c
CommitLineData
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 8static 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
25extern errno;
06eef7c4 26char *index();
f0bb4ca8
BJ
27
28rcmd(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 144bad2:
c1dfbf19 145 if (lport)
f0bb4ca8 146 (void) close(*fd2p);
40d6b022 147bad:
f0bb4ca8 148 (void) close(s);
92423502 149 sigsetmask(oldmask);
f0bb4ca8
BJ
150 return (-1);
151}
152
c1dfbf19
SL
153rresvport(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
181ruserok(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
205again:
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)
236char *rhost, *luser, *ruser;
237FILE *hostf;
238int 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)
269char *rhost, *lhost;
270int 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}