diff options
| author | svn2git <svn2git@FreeBSD.org> | 1993-11-01 08:00:00 +0000 |
|---|---|---|
| committer | svn2git <svn2git@FreeBSD.org> | 1993-11-01 08:00:00 +0000 |
| commit | 8503f4f13f77abf7adc8f7e329c6f9c1d52b6a20 (patch) | |
| tree | c5b2ce776438e0a52b492a2ab6ab41360b8ba1f6 /lib/libc/net/rcmd.c | |
Diffstat (limited to 'lib/libc/net/rcmd.c')
| -rw-r--r-- | lib/libc/net/rcmd.c | 351 |
1 files changed, 351 insertions, 0 deletions
diff --git a/lib/libc/net/rcmd.c b/lib/libc/net/rcmd.c new file mode 100644 index 000000000000..d0cd18000ba9 --- /dev/null +++ b/lib/libc/net/rcmd.c @@ -0,0 +1,351 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)rcmd.c 5.24 (Berkeley) 2/24/91"; +#endif /* LIBC_SCCS and not lint */ + +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <signal.h> +#include <fcntl.h> +#include <netdb.h> +#include <pwd.h> +#include <errno.h> +#include <stdio.h> +#include <ctype.h> +#include <unistd.h> +#include <string.h> + +rcmd(ahost, rport, locuser, remuser, cmd, fd2p) + char **ahost; + u_short rport; + const char *locuser, *remuser, *cmd; + int *fd2p; +{ + int s, timo = 1, pid; + long oldmask; + struct sockaddr_in sin, sin2, from; + char c; + int lport = IPPORT_RESERVED - 1; + struct hostent *hp; + fd_set reads; + + pid = getpid(); + hp = gethostbyname(*ahost); + if (hp == 0) { + herror(*ahost); + return (-1); + } + *ahost = hp->h_name; + 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, (struct sockaddr *)&sin, sizeof(sin)) >= 0) + break; + (void) close(s); + if (errno == EADDRINUSE) { + lport--; + continue; + } + if (errno == ECONNREFUSED && timo <= 16) { + sleep(timo); + timo *= 2; + 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--; + if (fd2p == 0) { + write(s, "", 1); + lport = 0; + } else { + char num[8]; + int s2 = rresvport(&lport), s3; + int len = sizeof (from); + + if (s2 < 0) + goto bad; + listen(s2, 1); + (void) sprintf(num, "%d", lport); + if (write(s, num, strlen(num)+1) != strlen(num)+1) { + perror("write: setting up stderr"); + (void) close(s2); + goto bad; + } + FD_ZERO(&reads); + FD_SET(s, &reads); + FD_SET(s2, &reads); + errno = 0; + if (select(32, &reads, 0, 0, 0) < 1 || + !FD_ISSET(s2, &reads)) { + if (errno != 0) + perror("select: setting up stderr"); + else + fprintf(stderr, + "select: protocol failure in circuit setup.\n"); + (void) close(s2); + goto bad; + } + s3 = accept(s2, (struct sockaddr *)&from, &len); + (void) close(s2); + if (s3 < 0) { + perror("accept"); + lport = 0; + goto bad; + } + *fd2p = s3; + from.sin_port = ntohs((u_short)from.sin_port); + if (from.sin_family != AF_INET || + from.sin_port >= IPPORT_RESERVED || + from.sin_port < IPPORT_RESERVED / 2) { + fprintf(stderr, + "socket: protocol failure in circuit setup.\n"); + goto bad2; + } + } + (void) write(s, locuser, strlen(locuser)+1); + (void) write(s, remuser, strlen(remuser)+1); + (void) write(s, cmd, strlen(cmd)+1); + if (read(s, &c, 1) != 1) { + perror(*ahost); + goto bad2; + } + if (c != 0) { + while (read(s, &c, 1) == 1) { + (void) write(2, &c, 1); + if (c == '\n') + break; + } + goto bad2; + } + sigsetmask(oldmask); + return (s); +bad2: + if (lport) + (void) close(*fd2p); +bad: + (void) close(s); + sigsetmask(oldmask); + return (-1); +} + +rresvport(alport) + int *alport; +{ + struct sockaddr_in sin; + int s; + + sin.sin_family = AF_INET; + 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, (struct sockaddr *)&sin, sizeof (sin)) >= 0) + return (s); + if (errno != EADDRINUSE) { + (void) close(s); + return (-1); + } + (*alport)--; + if (*alport == IPPORT_RESERVED/2) { + (void) close(s); + errno = EAGAIN; /* close */ + return (-1); + } + } +} + +int _check_rhosts_file = 1; + +ruserok(rhost, superuser, ruser, luser) + const char *rhost, *ruser, *luser; + int superuser; +{ + FILE *hostf; + char fhost[MAXHOSTNAMELEN]; + int first = 1; + register char *sp, *p; + int baselen = -1; + + sp = (char *)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(_PATH_HEQUIV, "r"); +again: + if (hostf) { + if (!_validuser(hostf, fhost, luser, ruser, baselen)) { + (void) fclose(hostf); + return(0); + } + (void) fclose(hostf); + } + if (first == 1 && (_check_rhosts_file || superuser)) { + struct stat sbuf; + struct passwd *pwd; + char pbuf[MAXPATHLEN]; + + first = 0; + 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); +} + +/* don't make static, used by lpd(8) */ +_validuser(hostf, rhost, luser, ruser, baselen) + char *rhost, *luser, *ruser; + FILE *hostf; + int baselen; +{ + register char *p; + char *user, ahost[MAXHOSTNAMELEN]; + static int _checkhost(); + + 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)); +} |
