X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/ea19968fd08ce05ae11d7e277109434127d003fd..bec8d58c692d252d93d5e2c9a3aa35d7ccaa6796:/usr/src/lib/libc/net/rcmd.c diff --git a/usr/src/lib/libc/net/rcmd.c b/usr/src/lib/libc/net/rcmd.c index 8d7620fdfe..16c2cc62d9 100644 --- a/usr/src/lib/libc/net/rcmd.c +++ b/usr/src/lib/libc/net/rcmd.c @@ -1,10 +1,32 @@ -#ifndef lint -static char sccsid[] = "@(#)rcmd.c 4.9 %G%"; -#endif +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)rcmd.c 5.19 (Berkeley) %G%"; +#endif /* LIBC_SCCS and not lint */ #include -#include +#include +#include +#include +#include +#include #include +#include #include @@ -12,45 +34,71 @@ static char sccsid[] = "@(#)rcmd.c 4.9 %G%"; #include extern errno; -char *index(), *sprintf(); +char *index(); rcmd(ahost, rport, locuser, remuser, cmd, fd2p) char **ahost; - int rport; + u_short rport; char *locuser, *remuser, *cmd; int *fd2p; { - int s, timo = 1; + int s, timo = 1, pid; + long oldmask; struct sockaddr_in sin, sin2, from; char c; int lport = IPPORT_RESERVED - 1; struct hostent *hp; + pid = getpid(); hp = gethostbyname(*ahost); if (hp == 0) { - fprintf(stderr, "%s: unknown host\n", *ahost); + herror(*ahost); return (-1); } *ahost = hp->h_name; -retry: - s = rresvport(&lport); - if (s < 0) - return (-1); - sin.sin_family = hp->h_addrtype; - bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length); - sin.sin_port = rport; - if (connect(s, (caddr_t)&sin, sizeof (sin), 0) < 0) { + oldmask = sigblock(sigmask(SIGURG)); + for (;;) { + s = rresvport(&lport); + if (s < 0) { + if (errno == EAGAIN) + fprintf(stderr, "socket: All ports in use\n"); + else + perror("rcmd: socket"); + sigsetmask(oldmask); + return (-1); + } + fcntl(s, F_SETOWN, pid); + sin.sin_family = hp->h_addrtype; + bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr, hp->h_length); + sin.sin_port = rport; + if (connect(s, (caddr_t)&sin, sizeof (sin), 0) >= 0) + break; (void) close(s); if (errno == EADDRINUSE) { lport--; - goto retry; + continue; } if (errno == ECONNREFUSED && timo <= 16) { sleep(timo); timo *= 2; - goto retry; + continue; + } + if (hp->h_addr_list[1] != NULL) { + int oerrno = errno; + + fprintf(stderr, + "connect to address %s: ", inet_ntoa(sin.sin_addr)); + errno = oerrno; + perror(0); + hp->h_addr_list++; + bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr, + hp->h_length); + fprintf(stderr, "Trying %s...\n", + inet_ntoa(sin.sin_addr)); + continue; } perror(hp->h_name); + sigsetmask(oldmask); return (-1); } lport--; @@ -102,12 +150,14 @@ retry: } goto bad2; } + sigsetmask(oldmask); return (s); bad2: if (lport) (void) close(*fd2p); bad: (void) close(s); + sigsetmask(oldmask); return (-1); } @@ -118,59 +168,156 @@ rresvport(alport) int s; sin.sin_family = AF_INET; - sin.sin_addr.s_addr = 0; - s = socket(AF_INET, SOCK_STREAM, 0, 0); + sin.sin_len = sizeof(sin); + sin.sin_addr.s_addr = INADDR_ANY; + s = socket(AF_INET, SOCK_STREAM, 0); if (s < 0) return (-1); for (;;) { sin.sin_port = htons((u_short)*alport); - if (bind(s, (caddr_t)&sin, sizeof (sin), 0) >= 0) + if (bind(s, (caddr_t)&sin, sizeof (sin)) >= 0) return (s); - if (errno != EADDRINUSE && errno != EADDRNOTAVAIL) { - perror("socket"); + if (errno != EADDRINUSE) { (void) close(s); return (-1); } (*alport)--; if (*alport == IPPORT_RESERVED/2) { - fprintf(stderr, "socket: All ports in use\n"); (void) close(s); + errno = EAGAIN; /* close */ return (-1); } } } +int _check_rhosts_file = 1; + ruserok(rhost, superuser, ruser, luser) char *rhost; int superuser; char *ruser, *luser; { FILE *hostf; - char ahost[32]; + char fhost[MAXHOSTNAMELEN]; int first = 1; + register char *sp, *p; + int baselen = -1; + sp = rhost; + p = fhost; + while (*sp) { + if (*sp == '.') { + if (baselen == -1) + baselen = sp - rhost; + *p++ = *sp++; + } else { + *p++ = isupper(*sp) ? tolower(*sp++) : *sp++; + } + } + *p = '\0'; hostf = superuser ? (FILE *)0 : fopen("/etc/hosts.equiv", "r"); again: if (hostf) { - while (fgets(ahost, sizeof (ahost), hostf)) { - char *user; - if (index(ahost, '\n')) - *index(ahost, '\n') = 0; - user = index(ahost, ' '); - if (user) - *user++ = 0; - if (!strcmp(rhost, ahost) && - !strcmp(ruser, user ? user : luser)) { - (void) fclose(hostf); - return (0); - } + if (!_validuser(hostf, fhost, luser, ruser, baselen)) { + (void) fclose(hostf); + return(0); } (void) fclose(hostf); } - if (first == 1) { + if (first == 1 && (_check_rhosts_file || superuser)) { + struct stat sbuf; + struct passwd *pwd; + char pbuf[MAXPATHLEN]; + first = 0; - hostf = fopen(".rhosts", "r"); + if ((pwd = getpwnam(luser)) == NULL) + return(-1); + (void)strcpy(pbuf, pwd->pw_dir); + (void)strcat(pbuf, "/.rhosts"); + if ((hostf = fopen(pbuf, "r")) == NULL) + return(-1); + /* + * if owned by someone other than user or root or if + * writeable by anyone but the owner, quit + */ + if (fstat(fileno(hostf), &sbuf) || + sbuf.st_uid && sbuf.st_uid != pwd->pw_uid || + sbuf.st_mode&022) { + fclose(hostf); + return(-1); + } goto again; } return (-1); } + +static +_validuser(hostf, rhost, luser, ruser, baselen) + char *rhost, *luser, *ruser; + FILE *hostf; + int baselen; +{ + char *user; + char ahost[MAXHOSTNAMELEN]; + register char *p; + + while (fgets(ahost, sizeof (ahost), hostf)) { + p = ahost; + while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') { + *p = isupper(*p) ? tolower(*p) : *p; + p++; + } + if (*p == ' ' || *p == '\t') { + *p++ = '\0'; + while (*p == ' ' || *p == '\t') + p++; + user = p; + while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') + p++; + } else + user = p; + *p = '\0'; + if (_checkhost(rhost, ahost, baselen) && + !strcmp(ruser, *user ? user : luser)) { + return (0); + } + } + return (-1); +} + +static +_checkhost(rhost, lhost, len) + char *rhost, *lhost; + int len; +{ + static char ldomain[MAXHOSTNAMELEN + 1]; + static char *domainp = NULL; + static int nodomain = 0; + register char *cp; + + if (len == -1) + return(!strcmp(rhost, lhost)); + if (strncmp(rhost, lhost, len)) + return(0); + if (!strcmp(rhost, lhost)) + return(1); + if (*(lhost + len) != '\0') + return(0); + if (nodomain) + return(0); + if (!domainp) { + if (gethostname(ldomain, sizeof(ldomain)) == -1) { + nodomain = 1; + return(0); + } + ldomain[MAXHOSTNAMELEN] = NULL; + if ((domainp = index(ldomain, '.')) == (char *)NULL) { + nodomain = 1; + return(0); + } + for (cp = ++domainp; *cp; ++cp) + if (isupper(*cp)) + *cp = tolower(*cp); + } + return(!strcmp(domainp, rhost + len +1)); +}