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 #include <afsconfig.h>
19 #include <afs/param.h>
25 #include <sys/types.h>
26 #define MAXHOSTNAMELEN 64 /* use BSD's, not sys/param's */
27 #define MAXPATHLEN 1024 /* from BSD */
28 #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>
48 #include <netinet/in.h>
51 #if defined(AFS_HPUX_ENV)
52 /* HPUX uses a different call to set[res][gu]ids: */
53 #define seteuid(newEuid) setresuid(-1, (newEuid), -1)
54 #define setegid(newEgid) setresgid(-1, (newEgid), -1)
55 #endif /* defined(AFS_HPUX_ENV) */
57 #include <sys/syslog.h>
58 # define DPRINTF(args) dprintf args
64 static char prefix[] = "rcmd: ";
67 vsprintf(buf, argv[0], &argv[1]);
68 syslog(LOG_DEBUG, "%s %s\n", prefix, buf);
71 # define DPRINTF(args)
76 #ifdef AFS_HPUX102_ENV
78 rmcd(ahost, rport, locuser, remuser, cmd, fd2p)
81 const char *locuser, *remuser, *cmd;
85 rcmd(ahost, rport, locuser, remuser, cmd, fd2p, retry)
88 rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
92 #if defined(AFS_LINUX20_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
93 const char *locuser, *remuser, *cmd;
95 char *locuser, *remuser, *cmd;
100 int s, timo = 1, pid;
103 int someSignals[100];
104 struct servent *sp, *getservbyport();
105 struct sockaddr_in sin, from;
107 int lport = IPPORT_RESERVED - 1;
111 memset((char *)someSignals, 0, sizeof(someSignals));
112 someSignals[0] = 1 << (SIGURG - 1);
113 sigBlock = *((sigset_t *) someSignals);
116 hp = gethostbyname(*ahost); /* CAUTION: this uses global static */
117 /* storage. ANY OTHER CALLS to gethostbyname (including from within
118 * syslog, eg) will trash the contents of hp. BE CAREFUL! */
124 /* was: syslog(LOG_ERR, "rcmd: host=%s, rport=%d, luser=%s,ruser=%s,cmd=%s,fd2p=%s\n", *ahost,rport,locuser,remuser,cmd,fd2p)
125 * but that trashes hp... */
126 sigprocmask(SIG_BLOCK, &sigBlock, &oldset);
128 s = rresvport(&lport);
131 fprintf(stderr, "socket: All ports in use\n");
133 perror("rcmd: socket");
134 sigprocmask(SIG_SETMASK, &oldset, (sigset_t *) 0);
139 fcntl(s, F_SETOWN, pid);
141 /* since AIX has no F_SETOWN, we just do the ioctl */
142 (void)ioctl(s, SIOCSPGRP, &pid);
145 #if !defined(AFS_AIX_ENV) && !defined(AFS_HPUX_ENV)
146 fcntl(s, F_SETOWN, pid);
147 #endif /* !defined(AIX) */
149 sin.sin_family = hp->h_addrtype;
151 memcpy((caddr_t) & sin.sin_addr, hp->h_addr_list[0], hp->h_length);
153 memcpy((caddr_t) & sin.sin_addr, hp->h_addr, hp->h_length);
155 sin.sin_port = rport;
156 /* attempt to remote authenticate first... */
157 sp = getservbyport((int)rport, "tcp");
161 switch (ta_rauth(s, sp->s_name, sin.sin_addr)) {
164 fprintf(stderr, "No remote authentication\n");
167 s = rresvport(&lport);
170 fprintf(stderr, "socket: All ports in use\n");
172 perror("rcmd: socket");
173 sigprocmask(SIG_SETMASK, &oldset, (sigset_t *) 0);
176 #if !defined(AFS_AIX_ENV) && !defined(AFS_HPUX_ENV)
177 fcntl(s, F_SETOWN, pid);
178 #endif /* !defined(AIX) */
184 fprintf(stderr, "Login incorrect.");
188 fprintf(stderr, "internal failure, ta_rauth\n");
192 fprintf(stderr, "Cannot connect to remote machine\n");
198 break; /* from for loop */
201 if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
204 if (errno == EADDRINUSE) {
208 if (errno == ECONNREFUSED && timo <= 16) {
218 if (hp->h_addr_list[1] != NULL) {
221 fprintf(stderr, "connect to address %s: ",
222 inet_ntoa(sin.sin_addr));
226 memcpy((caddr_t) & sin.sin_addr, hp->h_addr_list[0],
228 fprintf(stderr, "Trying %s...\n", inet_ntoa(sin.sin_addr));
232 sigprocmask(SIG_SETMASK, &oldset, (sigset_t *) 0);
241 int s2 = rresvport(&lport), s3;
242 int len = sizeof(from);
248 (void)sprintf(num, "%d", lport);
249 if (write(s, num, strlen(num) + 1) != strlen(num) + 1) {
250 perror("write: setting up stderr");
262 if (select(maxfd + 1, &reads, 0, 0, 0) < 1 || !FD_ISSET(s2, &reads)) {
264 perror("select: setting up stderr");
267 "select: protocol failure in circuit setup.\n");
271 s3 = accept(s2, (struct sockaddr *)&from, &len);
279 from.sin_port = ntohs((u_short) from.sin_port);
280 if (from.sin_family != AF_INET || from.sin_port >= IPPORT_RESERVED
281 || from.sin_port < IPPORT_RESERVED / 2) {
282 fprintf(stderr, "socket: protocol failure in circuit setup.\n");
286 (void)write(s, locuser, strlen(locuser) + 1);
287 (void)write(s, remuser, strlen(remuser) + 1);
288 (void)write(s, cmd, strlen(cmd) + 1);
290 if (read(s, &c, 1) < 0) {
297 * Two different protocols seem to be used;
298 * one prepends a "message" byte with a "small"
299 * number; the other one just sends the message
302 (void)write(2, &c, 1);
305 while (read(s, &c, 1) == 1) {
306 (void)write(2, &c, 1);
312 sigprocmask(SIG_SETMASK, &oldset, (sigset_t *) 0);
319 sigprocmask(SIG_SETMASK, &oldset, (sigset_t *) 0);
323 #ifndef AFS_AIX32_ENV
327 struct sockaddr_in sin;
330 sin.sin_family = AF_INET;
331 sin.sin_addr.s_addr = INADDR_ANY;
332 s = socket(AF_INET, SOCK_STREAM, 0);
336 sin.sin_port = htons((u_short) * alport);
337 if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
339 if (errno != EADDRINUSE) {
344 if (*alport == IPPORT_RESERVED / 2) {
346 errno = EAGAIN; /* close */
353 int _check_rhosts_file = 1;
355 #if defined(AFS_HPUX102_ENV) || defined(AFS_LINUX20_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
356 ruserok(rhost, superuser, ruser, luser)
359 const char *ruser, *luser;
361 ruserok(rhost, superuser, ruser, luser)
368 char fhost[MAXHOSTNAMELEN];
370 register char *sp, *p;
373 int group_list_size = -1;
374 gid_t groups[NGROUPS_MAX];
380 baselen = sp - rhost;
383 *p++ = isupper(*sp) ? tolower(*sp++) : *sp++;
387 hostf = superuser ? (FILE *) 0 : fopen("/etc/hosts.equiv", "r");
390 if (!_validuser(hostf, fhost, luser, ruser, baselen)) {
396 if (group_list_size >= 0)
397 (void)setgroups(group_list_size, groups);
404 if (first == 1 && (_check_rhosts_file || superuser)) {
406 struct passwd *pwd, *getpwnam();
407 char pbuf[MAXPATHLEN];
412 group_list_size = getgroups(NGROUPS_MAX, groups);
413 if ((pwd = getpwnam(luser)) == NULL)
415 if (setegid(pwd->pw_gid) >= 0)
416 (void)initgroups(luser, pwd->pw_gid);
417 (void)seteuid(pwd->pw_uid);
418 (void)strcpy(pbuf, pwd->pw_dir);
419 (void)strcat(pbuf, "/.rhosts");
420 if ((hostf = fopen(pbuf, "r")) == NULL)
423 * if owned by someone other than user or root or if
424 * writeable by anyone but the owner, quit
426 if (fstat(fileno(hostf), &sbuf) || sbuf.st_uid
427 && sbuf.st_uid != pwd->pw_uid || sbuf.st_mode & 022) {
437 if (group_list_size >= 0)
438 (void)setgroups(group_list_size, groups);
443 /* don't make static, used by lpd(8) */
444 _validuser(hostf, rhost, luser, ruser, baselen)
445 char *rhost, *luser, *ruser;
450 char ahost[MAXHOSTNAMELEN * 4];
453 #include <arpa/nameser.h>
454 int hostmatch, usermatch;
455 char domain[MAXDNAME], *dp;
458 if (getdomainname(domain, sizeof(domain)) == 0)
461 while (fgets(ahost, sizeof(ahost), hostf)) {
463 hostmatch = usermatch = 0;
465 if (*p == '#' || *p == '\n') /* ignore comments and blanks */
467 while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0')
469 if (*p == ' ' || *p == '\t') {
471 while (*p == ' ' || *p == '\t')
474 while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0')
481 * +@<name> - group <name> allowed
482 * -@<name> - group <name> disallowed
483 * -<name> - host <name> disallowed
485 if (ahost[0] == '+' && ahost[1] == 0)
487 else if (ahost[0] == '+' && ahost[1] == '@')
488 hostmatch = innetgr(ahost + 2, rhost, NULL, dp);
489 else if (ahost[0] == '-' && ahost[1] == '@') {
490 if (innetgr(ahost + 2, rhost, NULL, dp))
492 } else if (ahost[0] == '-') {
493 if (_checkhost(rhost, ahost + 1, baselen))
496 hostmatch = _checkhost(rhost, ahost, baselen);
498 if (user[0] == '+' && user[1] == 0)
500 else if (user[0] == '+' && user[1] == '@')
501 usermatch = innetgr(user + 2, NULL, ruser, dp);
502 else if (user[0] == '-' && user[1] == '@') {
503 if (hostmatch && innetgr(user + 2, NULL, ruser, dp))
505 } else if (user[0] == '-') {
506 if (hostmatch && !strcmp(user + 1, ruser))
509 usermatch = !strcmp(user, ruser);
511 usermatch = !strcmp(ruser, luser);
512 if (hostmatch && usermatch)
516 while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') {
517 *p = isupper(*p) ? tolower(*p) : *p;
520 if (*p == ' ' || *p == '\t') {
522 while (*p == ' ' || *p == '\t')
525 while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0')
530 if (_checkhost(rhost, ahost, baselen)
531 && !strcmp(ruser, *user ? user : luser)) {
540 _checkhost(rhost, lhost, len)
544 static char ldomain[MAXHOSTNAMELEN + 1];
545 static char *domainp = NULL;
546 static int nodomain = 0;
554 * check for ip address and do a lookup to convert to hostname
556 if (isinet_addr(lhost) && (addr = inet_addr(lhost)) != -1
557 && (hp = gethostbyaddr(&addr, sizeof(addr), AF_INET)))
563 /* see if hostname from file has a domain name */
564 for (cp = lhost; *cp; ++cp) {
571 return (!strcmp(rhost, lhost));
573 if (strncmp(rhost, lhost, len))
575 if (!strcmp(rhost, lhost))
578 if (*(lhost + len) != '\0' && *(rhost + len) != '\0')
580 if (*(lhost + len) != '\0')
586 if (gethostname(ldomain, sizeof(ldomain)) == -1) {
590 ldomain[MAXHOSTNAMELEN] = '\0';
591 if ((domainp = strchr(ldomain, '.')) == (char *)NULL) {
595 for (cp = ++domainp; *cp; ++cp)
599 return (!strcmp(domainp, rhost + len + 1));