2 * Copyright (c) 1983 Regents of the University of California.
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18 #if defined(LIBC_SCCS) && !defined(lint)
19 static char sccsid[] = "@(#)rcmd.c 5.20 (Berkeley) 1/24/89";
20 #endif /* LIBC_SCCS and not lint */
22 #include <afs/param.h>
24 #include <sys/types.h>
25 #define MAXHOSTNAMELEN 64 /* use BSD's, not sys/param's */
26 #define MAXPATHLEN 1024 /* from BSD */
27 #include <sys/ioctl.h> /* for SIOCSPGRP */
33 #include <sys/param.h>
39 #include <unistd.h> /* select() prototype */
40 #include <sys/types.h> /* fd_set on older platforms */
41 #include <sys/time.h> /* struct timeval, select() prototype */
43 # include <sys/select.h> /* fd_set on newer platforms */
45 #include <sys/signal.h>
46 #include <sys/socket.h>
49 #include <netinet/in.h>
54 #if defined(AFS_HPUX_ENV)
55 /* HPUX uses a different call to set[res][gu]ids: */
56 #define seteuid(newEuid) setresuid(-1, (newEuid), -1)
57 #define setegid(newEgid) setresgid(-1, (newEgid), -1)
58 #endif /* defined(AFS_HPUX_ENV) */
61 #include <sys/syslog.h>
62 # define DPRINTF(args) dprintf args
69 static char prefix[] = "rcmd: ";
72 vsprintf (buf, argv[0], &argv[1]);
73 syslog (LOG_DEBUG, "%s %s\n", prefix, buf);
76 # define DPRINTF(args)
85 #ifdef AFS_HPUX102_ENV
86 int rmcd(ahost, rport, locuser, remuser, cmd, fd2p)
89 const char *locuser, *remuser, *cmd;
93 rcmd(ahost, rport, locuser, remuser, cmd, fd2p, retry)
96 rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
100 #if defined(AFS_LINUX20_ENV) || defined(AFS_DARWIN_ENV)
101 const char *locuser, *remuser, *cmd;
103 char *locuser, *remuser, *cmd;
108 int s, timo = 1, pid;
111 int someSignals[100];
112 struct servent *sp, *getservbyport();
113 struct sockaddr_in sin, from;
115 int lport = IPPORT_RESERVED - 1;
119 bzero((char *)someSignals, sizeof(someSignals));
120 someSignals[0] = 1<<(SIGURG-1);
121 sigBlock = *((sigset_t *)someSignals);
124 hp = gethostbyname(*ahost); /* CAUTION: this uses global static */
125 /* storage. ANY OTHER CALLS to gethostbyname (including from within
126 syslog, eg) will trash the contents of hp. BE CAREFUL! */
132 /* was: syslog(LOG_ERR, "rcmd: host=%s, rport=%d, luser=%s,ruser=%s,cmd=%s,fd2p=%s\n", *ahost,rport,locuser,remuser,cmd,fd2p)
133 but that trashes hp... */
134 sigprocmask(SIG_BLOCK, &sigBlock, &oldset);
136 s = rresvport(&lport);
139 fprintf(stderr, "socket: All ports in use\n");
141 perror("rcmd: socket");
142 sigprocmask(SIG_SETMASK, &oldset, (sigset_t *)0);
147 fcntl(s, F_SETOWN, pid);
149 /* since AIX has no F_SETOWN, we just do the ioctl */
150 (void)ioctl(s, SIOCSPGRP, &pid );
153 #if !defined(AFS_AIX_ENV) && !defined(AFS_HPUX_ENV)
154 fcntl(s, F_SETOWN, pid);
155 #endif /* !defined(AIX) */
157 sin.sin_family = hp->h_addrtype;
159 bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr, hp->h_length);
161 bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length);
163 sin.sin_port = rport;
164 /* attempt to remote authenticate first... */
165 sp = getservbyport((int)rport, "tcp");
169 switch(ta_rauth(s, sp->s_name, sin.sin_addr)) {
172 fprintf(stderr,"No remote authentication\n");
175 s = rresvport(&lport);
178 fprintf(stderr, "socket: All ports in use\n");
180 perror("rcmd: socket");
181 sigprocmask(SIG_SETMASK, &oldset, (sigset_t *)0);
184 #if !defined(AFS_AIX_ENV) && !defined(AFS_HPUX_ENV)
185 fcntl(s, F_SETOWN, pid);
186 #endif /* !defined(AIX) */
192 fprintf(stderr,"Login incorrect.");
196 fprintf(stderr,"internal failure, ta_rauth\n");
200 fprintf(stderr,"Cannot connect to remote machine\n");
206 break; /* from for loop */
209 if (connect(s, (struct sockaddr *) &sin, sizeof (sin)) >= 0)
212 if (errno == EADDRINUSE) {
216 if (errno == ECONNREFUSED && timo <= 16) {
226 if (hp->h_addr_list[1] != NULL) {
230 "connect to address %s: ", inet_ntoa(sin.sin_addr));
234 bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr,
236 fprintf(stderr, "Trying %s...\n",
237 inet_ntoa(sin.sin_addr));
241 sigprocmask(SIG_SETMASK, &oldset, (sigset_t *)0);
250 int s2 = rresvport(&lport), s3;
251 int len = sizeof (from);
257 (void) sprintf(num, "%d", lport);
258 if (write(s, num, strlen(num)+1) != strlen(num)+1) {
259 perror("write: setting up stderr");
264 FD_SET(s, &reads); if (maxfd < s) maxfd = s;
265 FD_SET(s2, &reads); if (maxfd < s2) maxfd = s2;
267 if (select(maxfd+1, &reads, 0, 0, 0) < 1 ||
268 !FD_ISSET(s2, &reads)) {
270 perror("select: setting up stderr");
272 "select: protocol failure in circuit setup.\n");
276 s3 = accept(s2, (struct sockaddr *) &from, &len);
284 from.sin_port = ntohs((u_short)from.sin_port);
285 if (from.sin_family != AF_INET ||
286 from.sin_port >= IPPORT_RESERVED ||
287 from.sin_port < IPPORT_RESERVED / 2) {
289 "socket: protocol failure in circuit setup.\n");
293 (void) write(s, locuser, strlen(locuser)+1);
294 (void) write(s, remuser, strlen(remuser)+1);
295 (void) write(s, cmd, strlen(cmd)+1);
297 if (read(s, &c, 1) < 0) {
304 * Two different protocols seem to be used;
305 * one prepends a "message" byte with a "small"
306 * number; the other one just sends the message
309 (void) write(2, &c, 1);
312 while (read(s, &c, 1) == 1) {
313 (void) write(2, &c, 1);
319 sigprocmask(SIG_SETMASK, &oldset, (sigset_t *)0);
326 sigprocmask(SIG_SETMASK, &oldset, (sigset_t *)0);
330 #ifndef AFS_AIX32_ENV
334 struct sockaddr_in sin;
337 sin.sin_family = AF_INET;
338 sin.sin_addr.s_addr = INADDR_ANY;
339 s = socket(AF_INET, SOCK_STREAM, 0);
343 sin.sin_port = htons((u_short)*alport);
344 if (bind(s, (struct sockaddr *) &sin, sizeof (sin)) >= 0)
346 if (errno != EADDRINUSE) {
351 if (*alport == IPPORT_RESERVED/2) {
353 errno = EAGAIN; /* close */
360 int _check_rhosts_file = 1;
362 #if defined(AFS_HPUX102_ENV) || defined(AFS_LINUX20_ENV) || defined(AFS_DARWIN_ENV)
363 ruserok(rhost, superuser, ruser, luser)
366 const char *ruser, *luser;
368 ruserok(rhost, superuser, ruser, luser)
375 char fhost[MAXHOSTNAMELEN];
377 register char *sp, *p;
380 int group_list_size= -1;
381 gid_t groups[NGROUPS_MAX];
387 baselen = sp - rhost;
390 *p++ = isupper(*sp) ? tolower(*sp++) : *sp++;
394 hostf = superuser ? (FILE *)0 : fopen("/etc/hosts.equiv", "r");
397 if (!_validuser(hostf, fhost, luser, ruser, baselen)) {
398 (void) fclose(hostf);
401 (void) seteuid(suid);
402 (void) setegid(sgid);
403 if(group_list_size >= 0)
404 (void) setgroups(group_list_size, groups);
409 (void) fclose(hostf);
411 if (first == 1 && (_check_rhosts_file || superuser)) {
413 struct passwd *pwd, *getpwnam();
414 char pbuf[MAXPATHLEN];
419 group_list_size = getgroups(NGROUPS_MAX, groups);
420 if ((pwd = getpwnam(luser)) == NULL)
422 if(setegid(pwd->pw_gid) >= 0)
423 (void) initgroups(luser, pwd->pw_gid);
424 (void) seteuid(pwd->pw_uid);
425 (void)strcpy(pbuf, pwd->pw_dir);
426 (void)strcat(pbuf, "/.rhosts");
427 if ((hostf = fopen(pbuf, "r")) == NULL)
430 * if owned by someone other than user or root or if
431 * writeable by anyone but the owner, quit
433 if (fstat(fileno(hostf), &sbuf) ||
434 sbuf.st_uid && sbuf.st_uid != pwd->pw_uid ||
443 (void) seteuid(suid);
444 (void) setegid(sgid);
445 if(group_list_size >= 0)
446 (void) setgroups(group_list_size, groups);
451 /* don't make static, used by lpd(8) */
452 _validuser(hostf, rhost, luser, ruser, baselen)
453 char *rhost, *luser, *ruser;
458 char ahost[MAXHOSTNAMELEN * 4];
461 #include <arpa/nameser.h>
462 int hostmatch, usermatch;
463 char domain[MAXDNAME], *dp;
466 if (getdomainname(domain, sizeof(domain)) == 0)
469 while (fgets(ahost, sizeof (ahost), hostf)) {
471 hostmatch = usermatch = 0;
473 if (*p == '#' || *p == '\n') /* ignore comments and blanks */
475 while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0')
477 if (*p == ' ' || *p == '\t') {
479 while (*p == ' ' || *p == '\t')
482 while (*p != '\n' && *p != ' ' && *p != '\t' &&
490 * +@<name> - group <name> allowed
491 * -@<name> - group <name> disallowed
492 * -<name> - host <name> disallowed
494 if (ahost[0] == '+' && ahost[1] == 0)
496 else if (ahost[0] == '+' && ahost[1] == '@')
497 hostmatch = innetgr(ahost + 2, rhost, NULL, dp);
498 else if (ahost[0] == '-' && ahost[1] == '@') {
499 if (innetgr(ahost + 2, rhost, NULL, dp))
501 } else if (ahost[0] == '-') {
502 if (_checkhost(rhost, ahost+1, baselen))
505 hostmatch = _checkhost(rhost, ahost, baselen);
507 if (user[0] == '+' && user[1] == 0)
509 else if (user[0] == '+' && user[1] == '@')
510 usermatch = innetgr(user+2, NULL, ruser, dp);
511 else if (user[0] == '-' && user[1] == '@') {
512 if (hostmatch && innetgr(user+2, NULL, ruser, dp))
514 } else if (user[0] == '-') {
515 if (hostmatch && !strcmp(user+1, ruser))
518 usermatch = !strcmp(user, ruser);
520 usermatch = !strcmp(ruser, luser);
521 if (hostmatch && usermatch)
525 while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') {
526 *p = isupper(*p) ? tolower(*p) : *p;
529 if (*p == ' ' || *p == '\t') {
531 while (*p == ' ' || *p == '\t')
534 while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0')
539 if (_checkhost(rhost, ahost, baselen) &&
540 !strcmp(ruser, *user ? user : luser)) {
549 _checkhost(rhost, lhost, len)
553 static char ldomain[MAXHOSTNAMELEN + 1];
554 static char *domainp = NULL;
555 static int nodomain = 0;
563 * check for ip address and do a lookup to convert to hostname
565 if (isinet_addr(lhost) && (addr = inet_addr(lhost)) != -1 &&
566 (hp = gethostbyaddr(&addr, sizeof(addr), AF_INET)))
572 /* see if hostname from file has a domain name */
573 for (cp = lhost; *cp; ++cp) {
580 return(!strcmp(rhost, lhost));
582 if (strncmp(rhost, lhost, len))
584 if (!strcmp(rhost, lhost))
587 if (*(lhost + len) != '\0' && *(rhost + len) != '\0')
589 if (*(lhost + len) != '\0')
595 if (gethostname(ldomain, sizeof(ldomain)) == -1) {
599 ldomain[MAXHOSTNAMELEN] = '\0';
600 if ((domainp = index(ldomain, '.')) == (char *)NULL) {
604 for (cp = ++domainp; *cp; ++cp)
608 return(!strcmp(domainp, rhost + len +1));