xref: /titanic_41/usr/src/lib/libast/common/uwin/rcmd.c (revision 2f172c55ef76964744bc62b4500ece87f3089b4d)
1 #include "FEATURE/uwin"
2 
3 #if !_UWIN || _lib_rcmd
4 
5 void _STUB_rcmd(){}
6 
7 #else
8 
9 /*
10  * Copyright (c) 1983
11  *	The Regents of the University of California.  All rights reserved.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  * 3. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  */
37 
38 #if defined(LIBC_SCCS) && !defined(lint)
39 static char sccsid[] = "@(#)rcmd.c	5.17 (Berkeley) 6/27/88";
40 #endif /* LIBC_SCCS and not lint */
41 
42 #include "rlib.h"
43 #include <pwd.h>
44 #include <sys/file.h>
45 #include <sys/signal.h>
46 #if 1
47 #define _PATH_HEQUIV	"/etc/hosts.equiv"
48 #endif
49 #include <sys/stat.h>
50 
51 #if NLS
52 #include "nl_types.h"
53 #endif
54 
55 #ifdef YP
56 #include <rpcsvc/ypclnt.h>
57 extern void setnetgrent(const char *);
58 extern void endnetgrent(void);
59 extern int getnetgrent(char **, char **, char **);
60 static char *nisdomain = NULL;
61 static int _checknetgrouphost(const char *, const char *, int);
62 static int _checknetgroupuser(const char *, const char *);
63 #endif
64 
65 #if defined(__EXPORT__)
66 #define extern		__EXPORT__
67 #endif
68 
69 extern int rresvport(int *alport)
70 {
71 	struct sockaddr_in sin;
72 	int s;
73 
74 	sin.sin_family = AF_INET;
75 	sin.sin_addr.s_addr = INADDR_ANY;
76 	s = socket(AF_INET, SOCK_STREAM, 0);
77 	if (s < 0)
78 		return (-1);
79 	for (;;) {
80 		sin.sin_port = htons((u_short)*alport);
81 		if (bind(s, (struct sockaddr *)&sin, sizeof (sin)) >= 0)
82 			return (s);
83 		if (errno != EADDRINUSE) {
84 			(void) close(s);
85 			return (-1);
86 		}
87 		(*alport)--;
88 		if (*alport == IPPORT_RESERVED/2) {
89 			(void) close(s);
90 			errno = EAGAIN;		/* close */
91 			return (-1);
92 		}
93 	}
94 }
95 
96 extern int rcmd(char **ahost, unsigned short rport, const char *locuser, const char *remuser, const char *cmd, int *fd2p)
97 {
98 	int s, timo = 1;
99 #ifdef F_SETOWN
100 	pid_t pid;
101 #endif
102 #ifdef _POSIX_SOURCE
103 	sigset_t set, oset;
104 #else
105 	long oldmask;
106 #endif
107 	struct sockaddr_in sin, from;
108 	char c;
109 	int lport = IPPORT_RESERVED - 1;
110 	struct hostent *hp;
111 
112 #if NLS
113 	libc_nls_init();
114 #endif
115 
116 #ifdef F_SETOWN
117 	pid = getpid();
118 #endif
119 	hp = gethostbyname(*ahost);
120 	if (hp == 0) {
121 #if NLS
122 		fprintf(stderr, "%s: %s\n", *ahost,
123 		    catgets(_libc_cat, HerrorListSet,
124 		    2, "unknown host"));
125 #else
126 		fprintf(stderr, "%s: unknown host\n", *ahost);
127 #endif
128 		return (-1);
129 	}
130 	*ahost = hp->h_name;
131 #ifdef SIGURG
132 #ifdef _POSIX_SOURCE
133 	sigemptyset (&set);
134 	sigaddset (&set, SIGURG);
135 	sigprocmask (SIG_BLOCK, &set, &oset);
136 #else
137 	oldmask = sigblock(sigmask(SIGURG));
138 #endif
139 #endif
140 	for (;;) {
141 		s = rresvport(&lport);
142 		if (s < 0) {
143 			if (errno == EAGAIN)
144 #if NLS
145 				fprintf(stderr, "socket: %s\n",
146 				    catgets(_libc_cat, NetMiscSet,
147 				    NetMiscAllPortsInUse,
148 				    "All ports in use"));
149 #else
150 			fprintf(stderr, "socket: All ports in use\n");
151 #endif
152 			else
153 #if NLS
154 	perror(catgets(_libc_cat, NetMiscSet,
155 	    NetMiscRcmdSocket,
156 	    "rcmd: socket"));
157 #else
158 perror("rcmd: socket");
159 #endif
160 #ifdef SIGURG
161 #ifdef _POSIX_SOURCE
162 sigprocmask (SIG_SETMASK, &oset,
163 (sigset_t *)NULL);
164 #else
165 sigsetmask(oldmask);
166 #endif
167 #endif
168 return (-1);
169 		}
170 #ifdef F_SETOWN
171 		fcntl(s, F_SETOWN, pid);
172 #endif
173 		sin.sin_family = hp->h_addrtype;
174 		bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr, hp->h_length);
175 		sin.sin_port = rport;
176 		if (connect(s, (struct sockaddr *)&sin, sizeof (sin)) >= 0)
177 			break;
178 		(void) close(s);
179 		if (errno == EADDRINUSE) {
180 			lport--;
181 			continue;
182 		}
183 		if (errno == ECONNREFUSED && timo <= 16) {
184 			sleep(timo);
185 			timo *= 2;
186 			continue;
187 		}
188 		if (hp->h_addr_list[1] != NULL) {
189 			int oerrno = errno;
190 
191 			fprintf(stderr,
192 #if NLS
193 			    "%s %s: ", catgets(_libc_cat, NetMiscSet,
194 			    NetMiscAllPortsInUse,
195 			    "connect to address"),
196 			    inet_ntoa(sin.sin_addr));
197 
198 #else
199 
200 			"connect to address %s: ", inet_ntoa(sin.sin_addr));
201 #endif
202 			errno = oerrno;
203 			perror(0);
204 			hp->h_addr_list++;
205 			bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr,
206 			    hp->h_length);
207 
208 #if NLS
209 			fprintf(stderr, catgets(_libc_cat, NetMiscSet,
210 			    NetMiscTrying,
211 			    "Trying %s...\n"),
212 #else
213 			    fprintf(stderr,	"Trying %s...\n",
214 #endif
215 			    inet_ntoa(sin.sin_addr));
216 			    continue;
217 		}
218 		perror(hp->h_name);
219 #ifdef SIGURG
220 #ifdef _POSIX_SOURCE
221 		    sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
222 #else
223 		    sigsetmask(oldmask);
224 #endif
225 #endif
226 		    return (-1);
227 	}
228 	lport--;
229 	    if (fd2p == 0) {
230 		write(s, "", 1);
231 		    lport = 0;
232 	} else {
233 		char num[8];
234 		    int s2 = rresvport(&lport), s3;
235 		    int len = sizeof (from);
236 
237 		    if (s2 < 0)
238 		    goto bad;
239 		    listen(s2, 1);
240 		    (void) snprintf(num, sizeof(num), "%d", lport);
241 		    if (write(s, num, strlen(num)+1) != strlen(num)+1) {
242 #if NLS
243 			perror(catgets(_libc_cat, NetMiscSet,
244 			    NetMiscSettingUpStderr,
245 			    "write: setting up stderr"));
246 #else
247 			    perror("write: setting up stderr");
248 #endif
249 			    (void) close(s2);
250 			    goto bad;
251 		}
252 		s3 = accept(s2, (struct sockaddr *)&from, &len);
253 		    (void) close(s2);
254 		    if (s3 < 0) {
255 #if NLS
256 			perror(catgets(_libc_cat, NetMiscSet,
257 			    NetMiscAccept,
258 			    "accept"));
259 #else
260 			    perror("accept");
261 #endif
262 			    lport = 0;
263 			    goto bad;
264 		}
265 		*fd2p = s3;
266 		    from.sin_port = ntohs((u_short)from.sin_port);
267 		    if (from.sin_family != AF_INET ||
268 		    from.sin_port >= IPPORT_RESERVED) {
269 			fprintf(stderr,
270 #if NLS
271 			    "%s\n",
272 			    catgets(_libc_cat, NetMiscSet,
273 			    NetMiscProtocolFailure,
274 			    "socket: protocol failure in circuit setup."));
275 #else
276 			    "socket: protocol failure in circuit setup.\n");
277 #endif
278 			goto bad2;
279 		}
280 	}
281 	(void) write(s, locuser, strlen(locuser)+1);
282 	(void) write(s, remuser, strlen(remuser)+1);
283 	(void) write(s, cmd, strlen(cmd)+1);
284 	if (read(s, &c, 1) != 1) {
285 		perror(*ahost);
286 		goto bad2;
287 	}
288 	if (c != 0) {
289 		while (read(s, &c, 1) == 1) {
290 			(void) write(2, &c, 1);
291 			if (c == '\n')
292 				break;
293 		}
294 		goto bad2;
295 	}
296 #ifdef SIGURG
297 #ifdef _POSIX_SOURCE
298 	sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
299 #else
300 	sigsetmask(oldmask);
301 #endif
302 #endif
303 	return (s);
304 bad2:
305 	if (lport)
306 		(void) close(*fd2p);
307 bad:
308 	(void) close(s);
309 #ifdef SIGURG
310 #ifdef _POSIX_SOURCE
311 	sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
312 #else
313 	sigsetmask(oldmask);
314 #endif
315 #endif
316 	return (-1);
317 }
318 
319 extern int ruserok(const char *rhost, int superuser, const char *ruser, const char *luser)
320 {
321 	FILE *hostf;
322 	char fhost[MAXHOSTNAMELEN];
323 	int first = 1;
324 	register const char *sp;
325 	register char *p;
326 	int baselen = -1;
327 	uid_t saveuid;
328 
329 	saveuid = geteuid();
330 	sp = rhost;
331 	p = fhost;
332 	while (*sp) {
333 		if (*sp == '.') {
334 			if (baselen == -1)
335 				baselen = sp - rhost;
336 			*p++ = *sp++;
337 		} else {
338 			*p++ = isupper(*sp) ? tolower(*sp++) : *sp++;
339 		}
340 	}
341 	*p = '\0';
342 	hostf = superuser ? (FILE *)0 : fopen(_PATH_HEQUIV, "r");
343 again:
344 	if (hostf) {
345 		if (!_validuser(hostf, fhost, luser, ruser, baselen)) {
346 			(void) fclose(hostf);
347 			seteuid(saveuid);
348 			return(0);
349 		}
350 		(void) fclose(hostf);
351 	}
352 	if (first == 1) {
353 		struct stat sbuf;
354 		struct passwd *pwd;
355 		char pbuf[MAXPATHLEN];
356 
357 		first = 0;
358 		if ((pwd = getpwnam(luser)) == NULL)
359 			return(-1);
360 		(void)strcpy(pbuf, pwd->pw_dir);
361 		(void)strcat(pbuf, "/.rhosts");
362 		(void)seteuid(pwd->pw_uid);
363 		if ((hostf = fopen(pbuf, "r")) == NULL) {
364 			seteuid(saveuid);
365 			return(-1);
366 		}
367 		(void)fstat(fileno(hostf), &sbuf);
368 		if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid) {
369 			fclose(hostf);
370 			seteuid(saveuid);
371 			return(-1);
372 		}
373 		goto again;
374 	}
375 	seteuid(saveuid);
376 	return (-1);
377 }
378 
379 int
380 _validuser(FILE *hostf, const char *rhost, const char *luser,
381 const char *ruser, int baselen)
382 {
383 	char *user;
384 	char ahost[MAXHOSTNAMELEN];
385 	register char *p;
386 	int hostvalid = 0;
387 	int uservalid = 0;
388 
389 	while (fgets(ahost, sizeof (ahost), hostf)) {
390 		/* We need to get rid of all comments. */
391 		p = strchr (ahost, '#');
392 		if (p) *p = '\0';
393 		p = ahost;
394 		while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') {
395 			*p = isupper(*p) ? tolower(*p) : *p;
396 			p++;
397 		}
398 		if (*p == ' ' || *p == '\t') {
399 			*p++ = '\0';
400 			while (*p == ' ' || *p == '\t')
401 				p++;
402 			user = p;
403 			while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0')
404 				p++;
405 		} else
406 			user = p;
407 		*p = '\0';
408 	/* Adding new authentication -Nilendu */
409 
410 		/* enable all host for + entry */
411 		if ('+' == ahost[0] && '\0' == ahost[1] )
412 			hostvalid = 1;
413 
414 		/* enable all user for + entry */
415 		if ('+' == user[0] && '\0' == user[1] )
416 			uservalid = 1;
417 
418 		/* disable all host for - entry */
419 		if ('-' == ahost[0] && '\0' == ahost[1] )
420 			hostvalid = 0;
421 
422 		/* disable all user for - entry */
423 		if ('-' == user[0] && '\0' == user[1] )
424 			uservalid = 0;
425 
426 
427 #ifdef YP
428 		/* disable host from -hostname entry */
429 		if ('-' == ahost[0] && '@' != ahost[1]
430 		    && _checkhost(rhost, &ahost[1], baselen))
431 			return -1;
432 		/* disable host from -@netgroup entry for host */
433 		if ('-' == ahost[0] && '@' == ahost[1] && '\0' != ahost[2]
434 		    && _checknetgrouphost(rhost, &ahost[2], baselen))
435 			return -1;
436 		/* disable user from -user entry */
437 		if ('\0' != *user && user[0] == '-' && user[1] != '@'
438 		    && !strcmp(&user[1], ruser))
439 			return -1;
440 		/* disable user from -@netgroup entry for user */
441 		if ('\0' != *user && user[0] == '-' && user[1] == '@'
442 		    && user[2] != '\0' && _checknetgroupuser(ruser, &user[2]))
443 			return -1;
444 		/* enable host from +@netgroup entry for host */
445 		if ('+' == ahost[0] && '@' == ahost[1] && '\0' != ahost[2])
446 			hostvalid = _checknetgrouphost(rhost, &ahost[2], baselen);
447 			else
448 			hostvalid = _checkhost(rhost, ahost, baselen);
449 		/* enable user from +@netgroup entry for user */
450 		if ('\0' != *user && user[0] == '+'
451 		    && user[1] == '@' && user[2] != '\0')
452 			uservalid = _checknetgroupuser(ruser, &user[2]);
453 			else
454 			uservalid = !strcmp(ruser, *user ? user : luser);
455 
456 		if (hostvalid && uservalid)
457 			return 0;
458 #else
459 		hostvalid = hostvalid ? 1 : _checkhost(rhost, ahost, baselen);
460 	 	uservalid = uservalid ? 1 :	!stricmp(ruser,*user ? user : luser);
461 		if (hostvalid && uservalid)
462 			return 0;
463 
464 #endif /* YP */
465 		hostvalid = uservalid = 0;
466 	}
467 	return (-1);
468 }
469 
470 int
471 _checkhost(const char *rhost, const char *lhost, int len)
472 {
473 	static char ldomain[MAXHOSTNAMELEN + 1];
474 	static char *domainp = NULL;
475 	static int nodomain = 0;
476 	register char *cp;
477 
478 	if (len == -1)
479 		return(!strcmp(rhost, lhost));
480 	if (strncmp(rhost, lhost, len))
481 		return(0);
482 	if (!strcmp(rhost, lhost))
483 		return(1);
484 	if (*(lhost + len) != '\0')
485 		return(0);
486 	if (nodomain)
487 		return(0);
488 	if (!domainp) {
489 		if (gethostname(ldomain, sizeof(ldomain)) == -1) {
490 			nodomain = 1;
491 			return(0);
492 		}
493 		ldomain[MAXHOSTNAMELEN] = (char) 0;
494 		if ((domainp = index(ldomain, '.')) == (char *)NULL) {
495 			nodomain = 1;
496 			return(0);
497 		}
498 		for (cp = ++domainp; *cp; ++cp)
499 			if (isupper(*cp))
500 				*cp = tolower(*cp);
501 	}
502 	return(!strcmp(domainp, rhost + len +1));
503 }
504 
505 #ifdef YP
506 static int
507 _checknetgrouphost(const char *rhost, const char *netgr, int baselen)
508 {
509 	char *host, *user, *domain;
510 	int status;
511 
512 	if (NULL == nisdomain)
513 		yp_get_default_domain(&nisdomain);
514 
515 	setnetgrent(netgr);
516 	while (1)
517 	{
518 		while (1 == (status = getnetgrent(&host, &user, &domain))
519 		    && NULL == host
520 		    && NULL != domain
521 		    && 0 != strcmp(domain, nisdomain))
522 			;  /* find valid host entry */
523 
524 		if (0 == status || NULL == host)
525 		{
526 			endnetgrent();
527 			return 0;
528 		}
529 
530 		if(1 == _checkhost(rhost, host, baselen))
531 		{
532 			endnetgrent();
533 			return 1;
534 		}
535 	}
536 }
537 
538 static int
539 _checknetgroupuser(const char *ruser, const char *netgr)
540 {
541 	char *host, *user, *domain;
542 	int status;
543 
544 	if (NULL == nisdomain)
545 		yp_get_default_domain(&nisdomain);
546 
547 	setnetgrent(netgr);
548 	while (1)
549 	{
550 		while (1 == (status = getnetgrent(&host, &user, &domain))
551 		    && NULL == user
552 		    && NULL != domain
553 		    && 0 != strcmp(domain, nisdomain))
554 			;  /* find valid user entry */
555 
556 		if (0 == status || NULL == user)
557 		{
558 			endnetgrent();
559 			return 0;
560 		}
561 
562 		if(0 == strcmp(ruser, user))
563 		{
564 			endnetgrent();
565 			return 1;
566 		}
567 	}
568 }
569 #endif /* YP */
570 
571 #endif
572