8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / libbc / libc / net / rcmd.c
blob89e8f79f44c60dd7779fb0a6e0ad248a528ecf66
1 /*
2 * Copyright 1995 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
6 /*
7 * Copyright (c) 1983 Regents of the University of California.
8 * All rights reserved. The Berkeley software License Agreement
9 * specifies the terms and conditions for redistribution.
12 #pragma ident "%Z%%M% %I% %E% SMI"
14 #include <stdio.h>
15 #include <ctype.h>
16 #include <pwd.h>
17 #include <sys/param.h>
18 #include <sys/file.h>
19 #include <sys/signal.h>
20 #include <sys/socket.h>
21 #include <sys/stat.h>
23 #include <netinet/in.h>
25 #include <netdb.h>
26 #include <errno.h>
28 #include <strings.h>
30 static char *domain;
32 int
33 rcmd(
34 char **ahost,
35 unsigned short rport,
36 const char *locuser,
37 const char *remuser,
38 const char *cmd,
39 int *fd2p)
41 int s, timo = 1, pid, oldmask, retval;
42 struct sockaddr_in sin, from;
43 char c;
44 int lport = IPPORT_RESERVED - 1;
45 struct hostent *hp;
47 pid = getpid();
48 hp = gethostbyname(*ahost);
49 if (hp == 0) {
50 fprintf(stderr, "%s: unknown host\n", *ahost);
51 return (-1);
53 *ahost = hp->h_name;
54 oldmask = sigblock(sigmask(SIGURG));
55 for (;;) {
56 s = rresvport(&lport);
57 if (s < 0) {
58 if (errno == EAGAIN)
59 fprintf(stderr, "socket: All ports in use\n");
60 else
61 perror("rcmd: socket");
62 sigsetmask(oldmask);
63 return (-1);
65 fcntl(s, F_SETOWN, pid);
66 sin.sin_family = hp->h_addrtype;
67 bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr, hp->h_length);
68 sin.sin_port = rport;
69 if (connect(s, &sin, sizeof (sin)) >= 0)
70 break;
71 (void) close(s);
72 if (errno == EADDRINUSE) {
73 lport--;
74 continue;
76 if (errno == ECONNREFUSED && timo <= 16) {
77 sleep(timo);
78 timo *= 2;
79 continue;
81 if (hp->h_addr_list[1] != NULL) {
82 int oerrno = errno;
84 fprintf(stderr,
85 "connect to address %s: ", inet_ntoa(sin.sin_addr));
86 errno = oerrno;
87 perror(0);
88 hp->h_addr_list++;
89 bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr,
90 hp->h_length);
91 fprintf(stderr, "Trying %s...\n",
92 inet_ntoa(sin.sin_addr));
93 continue;
95 perror(hp->h_name);
96 sigsetmask(oldmask);
97 return (-1);
99 lport--;
100 if (fd2p == 0) {
101 write(s, "", 1);
102 lport = 0;
103 } else {
104 char num[8];
105 int s2 = rresvport(&lport), s3;
106 int len = sizeof (from);
108 if (s2 < 0)
109 goto bad;
110 listen(s2, 1);
111 (void) sprintf(num, "%d", lport);
112 if (write(s, num, strlen(num)+1) != strlen(num)+1) {
113 perror("write: setting up stderr");
114 (void) close(s2);
115 goto bad;
117 s3 = accept(s2, &from, &len);
118 (void) close(s2);
119 if (s3 < 0) {
120 perror("accept");
121 lport = 0;
122 goto bad;
124 *fd2p = s3;
125 from.sin_port = ntohs((u_short)from.sin_port);
126 if (from.sin_family != AF_INET ||
127 from.sin_port >= IPPORT_RESERVED) {
128 fprintf(stderr,
129 "socket: protocol failure in circuit setup.\n");
130 goto bad2;
133 (void) write(s, locuser, strlen(locuser)+1);
134 (void) write(s, remuser, strlen(remuser)+1);
135 (void) write(s, cmd, strlen(cmd)+1);
136 retval = read(s, &c, 1);
137 if (retval != 1) {
138 if (retval == 0) {
139 fprintf(stderr,
140 "Protocol error, %s closed connection\n", *ahost);
141 } else if (retval < 0) {
142 perror(*ahost);
143 } else {
144 fprintf(stderr,
145 "Protocol error, %s sent %d bytes\n", *ahost, retval);
147 goto bad2;
149 if (c != 0) {
150 while (read(s, &c, 1) == 1) {
151 (void) write(2, &c, 1);
152 if (c == '\n')
153 break;
155 goto bad2;
157 sigsetmask(oldmask);
158 return (s);
159 bad2:
160 if (lport)
161 (void) close(*fd2p);
162 bad:
163 (void) close(s);
164 sigsetmask(oldmask);
165 return (-1);
169 rresvport(int *alport)
171 struct sockaddr_in sin;
172 int s;
174 sin.sin_family = AF_INET;
175 sin.sin_addr.s_addr = INADDR_ANY;
176 s = socket(AF_INET, SOCK_STREAM, 0);
177 if (s < 0)
178 return (-1);
179 for (;;) {
180 sin.sin_port = htons((u_short)*alport);
181 if (bind(s, (caddr_t)&sin, sizeof (sin)) >= 0)
182 return (s);
183 if (errno != EADDRINUSE) {
184 (void) close(s);
185 return (-1);
187 (*alport)--;
188 if (*alport == IPPORT_RESERVED/2) {
189 (void) close(s);
190 errno = EAGAIN; /* close */
191 return (-1);
197 ruserok(
198 const char *rhost,
199 int superuser,
200 const char *ruser,
201 const char *luser)
203 FILE *hostf;
204 char fhost[MAXHOSTNAMELEN];
205 const char *sp;
206 char *p;
207 int baselen = -1;
209 struct stat sbuf;
210 struct passwd *pwd;
211 char pbuf[MAXPATHLEN];
212 int euid = -1;
214 sp = rhost;
215 p = fhost;
216 while (*sp) {
217 if (*sp == '.') {
218 if (baselen == -1)
219 baselen = sp - rhost;
220 *p++ = *sp++;
221 } else {
222 *p++ = isupper(*sp) ? tolower(*sp++) : *sp++;
225 *p = '\0';
227 /* check /etc/hosts.equiv */
228 if (!superuser) {
229 if ((hostf = fopen("/etc/hosts.equiv", "r")) != NULL) {
230 if (!_validuser(hostf, fhost, luser, ruser, baselen)) {
231 (void) fclose(hostf);
232 return(0);
234 (void) fclose(hostf);
238 /* check ~/.rhosts */
240 if ((pwd = getpwnam(luser)) == NULL)
241 return(-1);
242 (void)strcpy(pbuf, pwd->pw_dir);
243 (void)strcat(pbuf, "/.rhosts");
246 * Read .rhosts as the local user to avoid NFS mapping the root uid
247 * to something that can't read .rhosts.
249 euid = geteuid();
250 (void) seteuid (pwd->pw_uid);
251 if ((hostf = fopen(pbuf, "r")) == NULL) {
252 if (euid != -1)
253 (void) seteuid (euid);
254 return(-1);
256 (void)fstat(fileno(hostf), &sbuf);
257 if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid) {
258 fclose(hostf);
259 if (euid != -1)
260 (void) seteuid (euid);
261 return(-1);
264 if (!_validuser(hostf, fhost, luser, ruser, baselen)) {
265 (void) fclose(hostf);
266 if (euid != -1)
267 (void) seteuid (euid);
268 return(0);
271 (void) fclose(hostf);
272 if (euid != -1)
273 (void) seteuid (euid);
274 return (-1);
278 _validuser(FILE *hostf, char *rhost, char *luser, char *ruser, int baselen)
280 char *user;
281 char ahost[MAXHOSTNAMELEN];
282 int hostmatch, usermatch;
283 char *p;
285 if (domain == NULL) {
286 (void) yp_get_default_domain(&domain);
288 while (fgets(ahost, sizeof (ahost), hostf)) {
289 hostmatch = usermatch = 0; /* bugid fix 1033104 */
290 p = ahost;
291 while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') {
292 *p = isupper(*p) ? tolower(*p) : *p;
293 p++;
295 if (*p == ' ' || *p == '\t') {
296 *p++ = '\0';
297 while (*p == ' ' || *p == '\t')
298 p++;
299 user = p;
300 while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0')
301 p++;
302 } else
303 user = p;
304 *p = '\0';
305 if (ahost[0] == '+' && ahost[1] == 0)
306 hostmatch = 1;
307 else if (ahost[0] == '+' && ahost[1] == '@')
308 hostmatch = innetgr(ahost + 2, rhost,
309 NULL, domain);
310 else if (ahost[0] == '-' && ahost[1] == '@') {
311 if (innetgr(ahost + 2, rhost, NULL, domain))
312 break;
314 else if (ahost[0] == '-') {
315 if (_checkhost(rhost, ahost+1, baselen))
316 break;
318 else
319 hostmatch = _checkhost(rhost, ahost, baselen);
320 if (user[0]) {
321 if (user[0] == '+' && user[1] == 0)
322 usermatch = 1;
323 else if (user[0] == '+' && user[1] == '@')
324 usermatch = innetgr(user+2, NULL,
325 ruser, domain);
326 else if (user[0] == '-' && user[1] == '@') {
327 if (hostmatch && innetgr(user+2, NULL,
328 ruser, domain))
329 break;
331 else if (user[0] == '-') {
332 if (hostmatch && !strcmp(user+1, ruser))
333 break;
335 else
336 usermatch = !strcmp(user, ruser);
338 else
339 usermatch = !strcmp(ruser, luser);
340 if (hostmatch && usermatch)
341 return (0);
343 return (-1);
347 _checkhost(char *rhost, char *lhost, int len)
349 static char *ldomain;
350 static char *domainp;
351 static int nodomain;
352 char *cp;
354 if (ldomain == NULL) {
355 ldomain = (char *)malloc(MAXHOSTNAMELEN+1);
356 if (ldomain == 0)
357 return (0);
360 if (len == -1)
361 return(!strcmp(rhost, lhost));
362 if (strncmp(rhost, lhost, len))
363 return(0);
364 if (!strcmp(rhost, lhost))
365 return(1);
366 if (*(lhost + len) != '\0')
367 return(0);
368 if (nodomain)
369 return(0);
370 if (!domainp) {
372 * "domainp" points after the first dot in the host name
374 if (gethostname(ldomain, MAXHOSTNAMELEN) == -1) {
375 nodomain = 1;
376 return(0);
378 ldomain[MAXHOSTNAMELEN] = NULL;
379 if ((domainp = index(ldomain, '.')) == (char *)NULL) {
380 nodomain = 1;
381 return(0);
383 domainp++;
384 cp = domainp;
385 while (*cp) {
386 *cp = isupper(*cp) ? tolower(*cp) : *cp;
387 cp++;
390 return(!strcmp(domainp, rhost + len +1));