1 #include "FEATURE/uwin"
2
3 #if !_UWIN || _lib_rcmd
4
_STUB_rcmd()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
rresvport(int * alport)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
rcmd(char ** ahost,unsigned short rport,const char * locuser,const char * remuser,const char * cmd,int * fd2p)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
ruserok(const char * rhost,int superuser,const char * ruser,const char * luser)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
_validuser(FILE * hostf,const char * rhost,const char * luser,const char * ruser,int baselen)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
_checkhost(const char * rhost,const char * lhost,int len)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
_checknetgrouphost(const char * rhost,const char * netgr,int baselen)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
_checknetgroupuser(const char * ruser,const char * netgr)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