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>
23 #include <sys/types.h>
24 #define MAXHOSTNAMELEN 64 /* use BSD's, not sys/param's */
25 #define MAXPATHLEN 1024 /* from BSD */
26 #include <sys/ioctl.h> /* for SIOCSPGRP */
31 #include <sys/param.h>
37 #include <unistd.h> /* select() prototype */
38 #include <sys/types.h> /* fd_set on older platforms */
39 #include <sys/time.h> /* struct timeval, select() prototype */
41 # include <sys/select.h> /* fd_set on newer platforms */
43 #include <sys/signal.h>
44 #include <sys/socket.h>
46 #include <netinet/in.h>
49 #if defined(AFS_HPUX_ENV)
50 /* HPUX uses a different call to set[res][gu]ids: */
51 #define seteuid(newEuid) setresuid(-1, (newEuid), -1)
52 #define setegid(newEgid) setresgid(-1, (newEgid), -1)
53 #endif /* defined(AFS_HPUX_ENV) */
55 #include <sys/syslog.h>
56 # define DPRINTF(args) afs_dprintf args
62 static char prefix
[] = "rcmd: ";
65 vsprintf(buf
, argv
[0], &argv
[1]);
66 syslog(LOG_DEBUG
, "%s %s\n", prefix
, buf
);
69 # define DPRINTF(args)
74 #ifdef AFS_HPUX102_ENV
76 rmcd(ahost
, rport
, locuser
, remuser
, cmd
, fd2p
)
79 const char *locuser
, *remuser
, *cmd
;
83 rcmd(ahost
, rport
, locuser
, remuser
, cmd
, fd2p
, retry
)
86 rcmd(ahost
, rport
, locuser
, remuser
, cmd
, fd2p
)
90 #if defined(AFS_LINUX20_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
91 const char *locuser
, *remuser
, *cmd
;
93 char *locuser
, *remuser
, *cmd
;
101 int someSignals
[100];
102 struct servent
*sp
, *getservbyport();
103 struct sockaddr_in sin
, from
;
105 int lport
= IPPORT_RESERVED
- 1;
109 memset(someSignals
, 0, sizeof(someSignals
));
110 someSignals
[0] = 1 << (SIGURG
- 1);
111 sigBlock
= *((sigset_t
*) someSignals
);
114 hp
= gethostbyname(*ahost
); /* CAUTION: this uses global static */
115 /* storage. ANY OTHER CALLS to gethostbyname (including from within
116 * syslog, eg) will trash the contents of hp. BE CAREFUL! */
122 /* was: syslog(LOG_ERR, "rcmd: host=%s, rport=%d, luser=%s,ruser=%s,cmd=%s,fd2p=%s\n", *ahost,rport,locuser,remuser,cmd,fd2p)
123 * but that trashes hp... */
124 sigprocmask(SIG_BLOCK
, &sigBlock
, &oldset
);
126 s
= rresvport(&lport
);
129 fprintf(stderr
, "socket: All ports in use\n");
131 perror("rcmd: socket");
132 sigprocmask(SIG_SETMASK
, &oldset
, (sigset_t
*) 0);
137 fcntl(s
, F_SETOWN
, pid
);
139 /* since AIX has no F_SETOWN, we just do the ioctl */
140 (void)ioctl(s
, SIOCSPGRP
, &pid
);
143 #if !defined(AFS_AIX_ENV) && !defined(AFS_HPUX_ENV)
144 fcntl(s
, F_SETOWN
, pid
);
145 #endif /* !defined(AIX) */
147 sin
.sin_family
= hp
->h_addrtype
;
149 memcpy((caddr_t
) & sin
.sin_addr
, hp
->h_addr_list
[0], hp
->h_length
);
151 memcpy((caddr_t
) & sin
.sin_addr
, hp
->h_addr
, hp
->h_length
);
153 sin
.sin_port
= rport
;
154 /* attempt to remote authenticate first... */
155 sp
= getservbyport((int)rport
, "tcp");
159 switch (ta_rauth(s
, sp
->s_name
, sin
.sin_addr
)) {
162 fprintf(stderr
, "No remote authentication\n");
165 s
= rresvport(&lport
);
168 fprintf(stderr
, "socket: All ports in use\n");
170 perror("rcmd: socket");
171 sigprocmask(SIG_SETMASK
, &oldset
, (sigset_t
*) 0);
174 #if !defined(AFS_AIX_ENV) && !defined(AFS_HPUX_ENV)
175 fcntl(s
, F_SETOWN
, pid
);
176 #endif /* !defined(AIX) */
182 fprintf(stderr
, "Login incorrect.");
186 fprintf(stderr
, "internal failure, ta_rauth\n");
190 fprintf(stderr
, "Cannot connect to remote machine\n");
196 break; /* from for loop */
199 if (connect(s
, (struct sockaddr
*)&sin
, sizeof(sin
)) >= 0)
202 if (errno
== EADDRINUSE
) {
206 if (errno
== ECONNREFUSED
&& timo
<= 16) {
216 if (hp
->h_addr_list
[1] != NULL
) {
219 fprintf(stderr
, "connect to address %s: ",
220 inet_ntoa(sin
.sin_addr
));
224 memcpy((caddr_t
) & sin
.sin_addr
, hp
->h_addr_list
[0],
226 fprintf(stderr
, "Trying %s...\n", inet_ntoa(sin
.sin_addr
));
230 sigprocmask(SIG_SETMASK
, &oldset
, (sigset_t
*) 0);
239 int s2
= rresvport(&lport
), s3
;
240 int len
= sizeof(from
);
246 (void)sprintf(num
, "%d", lport
);
247 if (write(s
, num
, strlen(num
) + 1) != strlen(num
) + 1) {
248 perror("write: setting up stderr");
260 if (select(maxfd
+ 1, &reads
, 0, 0, 0) < 1 || !FD_ISSET(s2
, &reads
)) {
262 perror("select: setting up stderr");
265 "select: protocol failure in circuit setup.\n");
269 s3
= accept(s2
, (struct sockaddr
*)&from
, &len
);
277 from
.sin_port
= ntohs((u_short
) from
.sin_port
);
278 if (from
.sin_family
!= AF_INET
|| from
.sin_port
>= IPPORT_RESERVED
279 || from
.sin_port
< IPPORT_RESERVED
/ 2) {
280 fprintf(stderr
, "socket: protocol failure in circuit setup.\n");
284 (void)write(s
, locuser
, strlen(locuser
) + 1);
285 (void)write(s
, remuser
, strlen(remuser
) + 1);
286 (void)write(s
, cmd
, strlen(cmd
) + 1);
288 if (read(s
, &c
, 1) < 0) {
295 * Two different protocols seem to be used;
296 * one prepends a "message" byte with a "small"
297 * number; the other one just sends the message
300 (void)write(2, &c
, 1);
303 while (read(s
, &c
, 1) == 1) {
304 (void)write(2, &c
, 1);
310 sigprocmask(SIG_SETMASK
, &oldset
, (sigset_t
*) 0);
317 sigprocmask(SIG_SETMASK
, &oldset
, (sigset_t
*) 0);
321 #ifndef AFS_AIX32_ENV
325 struct sockaddr_in sin
;
328 sin
.sin_family
= AF_INET
;
329 sin
.sin_addr
.s_addr
= INADDR_ANY
;
330 s
= socket(AF_INET
, SOCK_STREAM
, 0);
334 sin
.sin_port
= htons((u_short
) * alport
);
335 if (bind(s
, (struct sockaddr
*)&sin
, sizeof(sin
)) >= 0)
337 if (errno
!= EADDRINUSE
) {
342 if (*alport
== IPPORT_RESERVED
/ 2) {
344 errno
= EAGAIN
; /* close */
351 int _check_rhosts_file
= 1;
353 #if defined(AFS_HPUX102_ENV) || defined(AFS_LINUX20_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
354 ruserok(rhost
, superuser
, ruser
, luser
)
357 const char *ruser
, *luser
;
359 ruserok(rhost
, superuser
, ruser
, luser
)
366 char fhost
[MAXHOSTNAMELEN
];
371 int group_list_size
= -1;
372 gid_t groups
[NGROUPS_MAX
];
378 baselen
= sp
- rhost
;
381 *p
++ = isupper(*sp
) ? tolower(*sp
++) : *sp
++;
385 hostf
= superuser
? (FILE *) 0 : fopen("/etc/hosts.equiv", "r");
388 if (!_validuser(hostf
, fhost
, luser
, ruser
, baselen
)) {
394 if (group_list_size
>= 0)
395 (void)setgroups(group_list_size
, groups
);
402 if (first
== 1 && (_check_rhosts_file
|| superuser
)) {
404 struct passwd
*pwd
, *getpwnam();
405 char pbuf
[MAXPATHLEN
];
410 group_list_size
= getgroups(NGROUPS_MAX
, groups
);
411 if ((pwd
= getpwnam(luser
)) == NULL
)
413 if (setegid(pwd
->pw_gid
) >= 0)
414 (void)initgroups(luser
, pwd
->pw_gid
);
415 (void)seteuid(pwd
->pw_uid
);
416 (void)strcpy(pbuf
, pwd
->pw_dir
);
417 (void)strcat(pbuf
, "/.rhosts");
418 if ((hostf
= fopen(pbuf
, "r")) == NULL
)
421 * if owned by someone other than user or root or if
422 * writable by anyone but the owner, quit
424 if (fstat(fileno(hostf
), &sbuf
) || sbuf
.st_uid
425 && sbuf
.st_uid
!= pwd
->pw_uid
|| sbuf
.st_mode
& 022) {
435 if (group_list_size
>= 0)
436 (void)setgroups(group_list_size
, groups
);
441 /* don't make static, used by lpd(8) */
442 _validuser(hostf
, rhost
, luser
, ruser
, baselen
)
443 char *rhost
, *luser
, *ruser
;
448 char ahost
[MAXHOSTNAMELEN
* 4];
451 #include <arpa/nameser.h>
452 int hostmatch
, usermatch
;
453 char domain
[MAXDNAME
], *dp
;
456 if (getdomainname(domain
, sizeof(domain
)) == 0)
459 while (fgets(ahost
, sizeof(ahost
), hostf
)) {
461 hostmatch
= usermatch
= 0;
463 if (*p
== '#' || *p
== '\n') /* ignore comments and blanks */
465 while (*p
!= '\n' && *p
!= ' ' && *p
!= '\t' && *p
!= '\0')
467 if (*p
== ' ' || *p
== '\t') {
469 while (*p
== ' ' || *p
== '\t')
472 while (*p
!= '\n' && *p
!= ' ' && *p
!= '\t' && *p
!= '\0')
479 * +@<name> - group <name> allowed
480 * -@<name> - group <name> disallowed
481 * -<name> - host <name> disallowed
483 if (ahost
[0] == '+' && ahost
[1] == 0)
485 else if (ahost
[0] == '+' && ahost
[1] == '@')
486 hostmatch
= innetgr(ahost
+ 2, rhost
, NULL
, dp
);
487 else if (ahost
[0] == '-' && ahost
[1] == '@') {
488 if (innetgr(ahost
+ 2, rhost
, NULL
, dp
))
490 } else if (ahost
[0] == '-') {
491 if (_checkhost(rhost
, ahost
+ 1, baselen
))
494 hostmatch
= _checkhost(rhost
, ahost
, baselen
);
496 if (user
[0] == '+' && user
[1] == 0)
498 else if (user
[0] == '+' && user
[1] == '@')
499 usermatch
= innetgr(user
+ 2, NULL
, ruser
, dp
);
500 else if (user
[0] == '-' && user
[1] == '@') {
501 if (hostmatch
&& innetgr(user
+ 2, NULL
, ruser
, dp
))
503 } else if (user
[0] == '-') {
504 if (hostmatch
&& !strcmp(user
+ 1, ruser
))
507 usermatch
= !strcmp(user
, ruser
);
509 usermatch
= !strcmp(ruser
, luser
);
510 if (hostmatch
&& usermatch
)
514 while (*p
!= '\n' && *p
!= ' ' && *p
!= '\t' && *p
!= '\0') {
515 *p
= isupper(*p
) ? tolower(*p
) : *p
;
518 if (*p
== ' ' || *p
== '\t') {
520 while (*p
== ' ' || *p
== '\t')
523 while (*p
!= '\n' && *p
!= ' ' && *p
!= '\t' && *p
!= '\0')
528 if (_checkhost(rhost
, ahost
, baselen
)
529 && !strcmp(ruser
, *user
? user
: luser
)) {
538 _checkhost(rhost
, lhost
, len
)
542 static char ldomain
[MAXHOSTNAMELEN
+ 1];
543 static char *domainp
= NULL
;
544 static int nodomain
= 0;
552 * check for ip address and do a lookup to convert to hostname
554 if (isinet_addr(lhost
) && (addr
= inet_addr(lhost
)) != -1
555 && (hp
= gethostbyaddr(&addr
, sizeof(addr
), AF_INET
)))
561 /* see if hostname from file has a domain name */
562 for (cp
= lhost
; *cp
; ++cp
) {
569 return (!strcmp(rhost
, lhost
));
571 if (strncmp(rhost
, lhost
, len
))
573 if (!strcmp(rhost
, lhost
))
576 if (*(lhost
+ len
) != '\0' && *(rhost
+ len
) != '\0')
578 if (*(lhost
+ len
) != '\0')
584 if (gethostname(ldomain
, sizeof(ldomain
)) == -1) {
588 ldomain
[MAXHOSTNAMELEN
] = '\0';
589 if ((domainp
= strchr(ldomain
, '.')) == NULL
) {
593 for (cp
= ++domainp
; *cp
; ++cp
)
597 return (!strcmp(domainp
, rhost
+ len
+ 1));