rcmd.c revision 17543
11573Srgrimes/* 21573Srgrimes * Copyright (c) 1983, 1993, 1994 31573Srgrimes * The Regents of the University of California. All rights reserved. 41573Srgrimes * 51573Srgrimes * Redistribution and use in source and binary forms, with or without 61573Srgrimes * modification, are permitted provided that the following conditions 71573Srgrimes * are met: 81573Srgrimes * 1. Redistributions of source code must retain the above copyright 91573Srgrimes * notice, this list of conditions and the following disclaimer. 101573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111573Srgrimes * notice, this list of conditions and the following disclaimer in the 121573Srgrimes * documentation and/or other materials provided with the distribution. 131573Srgrimes * 3. All advertising materials mentioning features or use of this software 141573Srgrimes * must display the following acknowledgement: 151573Srgrimes * This product includes software developed by the University of 161573Srgrimes * California, Berkeley and its contributors. 171573Srgrimes * 4. Neither the name of the University nor the names of its contributors 181573Srgrimes * may be used to endorse or promote products derived from this software 191573Srgrimes * without specific prior written permission. 201573Srgrimes * 211573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241573Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311573Srgrimes * SUCH DAMAGE. 321573Srgrimes */ 331573Srgrimes 341573Srgrimes#if defined(LIBC_SCCS) && !defined(lint) 351573Srgrimesstatic char sccsid[] = "@(#)rcmd.c 8.3 (Berkeley) 3/26/94"; 361573Srgrimes#endif /* LIBC_SCCS and not lint */ 371573Srgrimes 381573Srgrimes#include <sys/param.h> 391573Srgrimes#include <sys/socket.h> 401573Srgrimes#include <sys/stat.h> 411573Srgrimes 421573Srgrimes#include <netinet/in.h> 431573Srgrimes#include <arpa/inet.h> 441573Srgrimes 451573Srgrimes#include <signal.h> 461573Srgrimes#include <fcntl.h> 471573Srgrimes#include <netdb.h> 481573Srgrimes#include <unistd.h> 491573Srgrimes#include <pwd.h> 501573Srgrimes#include <errno.h> 511573Srgrimes#include <stdio.h> 521573Srgrimes#include <ctype.h> 531573Srgrimes#include <string.h> 549978Swpaul#ifdef YP 559978Swpaul#include <rpc/rpc.h> 569978Swpaul#include <rpcsvc/yp_prot.h> 579978Swpaul#include <rpcsvc/ypclnt.h> 589978Swpaul#endif 591573Srgrimes 6017141Sjkhextern int innetgr __P(( const char *, const char *, const char *, const char * )); 6117141Sjkh 622592Scsgr#define max(a, b) ((a > b) ? a : b) 632592Scsgr 641573Srgrimesint __ivaliduser __P((FILE *, u_long, const char *, const char *)); 651573Srgrimesstatic int __icheckhost __P((u_long, char *)); 661573Srgrimes 671573Srgrimesint 681573Srgrimesrcmd(ahost, rport, locuser, remuser, cmd, fd2p) 691573Srgrimes char **ahost; 701573Srgrimes u_short rport; 711573Srgrimes const char *locuser, *remuser, *cmd; 721573Srgrimes int *fd2p; 731573Srgrimes{ 741573Srgrimes struct hostent *hp; 751573Srgrimes struct sockaddr_in sin, from; 761573Srgrimes fd_set reads; 771573Srgrimes long oldmask; 781573Srgrimes pid_t pid; 791573Srgrimes int s, lport, timo; 801573Srgrimes char c; 811573Srgrimes 821573Srgrimes pid = getpid(); 831573Srgrimes hp = gethostbyname(*ahost); 841573Srgrimes if (hp == NULL) { 851573Srgrimes herror(*ahost); 861573Srgrimes return (-1); 871573Srgrimes } 881573Srgrimes *ahost = hp->h_name; 891573Srgrimes oldmask = sigblock(sigmask(SIGURG)); 901573Srgrimes for (timo = 1, lport = IPPORT_RESERVED - 1;;) { 911573Srgrimes s = rresvport(&lport); 921573Srgrimes if (s < 0) { 931573Srgrimes if (errno == EAGAIN) 941573Srgrimes (void)fprintf(stderr, 951573Srgrimes "rcmd: socket: All ports in use\n"); 961573Srgrimes else 971573Srgrimes (void)fprintf(stderr, "rcmd: socket: %s\n", 981573Srgrimes strerror(errno)); 991573Srgrimes sigsetmask(oldmask); 1001573Srgrimes return (-1); 1011573Srgrimes } 1021573Srgrimes fcntl(s, F_SETOWN, pid); 10317543Speter bzero(&sin, sizeof sin); 10417543Speter sin.sin_len = sizeof(struct sockaddr_in); 1051573Srgrimes sin.sin_family = hp->h_addrtype; 10617543Speter sin.sin_port = rport; 1071573Srgrimes bcopy(hp->h_addr_list[0], &sin.sin_addr, hp->h_length); 1081573Srgrimes if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0) 1091573Srgrimes break; 1101573Srgrimes (void)close(s); 1111573Srgrimes if (errno == EADDRINUSE) { 1121573Srgrimes lport--; 1131573Srgrimes continue; 1141573Srgrimes } 1151573Srgrimes if (errno == ECONNREFUSED && timo <= 16) { 1161573Srgrimes (void)sleep(timo); 1171573Srgrimes timo *= 2; 1181573Srgrimes continue; 1191573Srgrimes } 1201573Srgrimes if (hp->h_addr_list[1] != NULL) { 1211573Srgrimes int oerrno = errno; 1221573Srgrimes 1231573Srgrimes (void)fprintf(stderr, "connect to address %s: ", 1241573Srgrimes inet_ntoa(sin.sin_addr)); 1251573Srgrimes errno = oerrno; 1261573Srgrimes perror(0); 1271573Srgrimes hp->h_addr_list++; 1281573Srgrimes bcopy(hp->h_addr_list[0], &sin.sin_addr, hp->h_length); 1291573Srgrimes (void)fprintf(stderr, "Trying %s...\n", 1301573Srgrimes inet_ntoa(sin.sin_addr)); 1311573Srgrimes continue; 1321573Srgrimes } 1331573Srgrimes (void)fprintf(stderr, "%s: %s\n", hp->h_name, strerror(errno)); 1341573Srgrimes sigsetmask(oldmask); 1351573Srgrimes return (-1); 1361573Srgrimes } 1371573Srgrimes lport--; 1381573Srgrimes if (fd2p == 0) { 1391573Srgrimes write(s, "", 1); 1401573Srgrimes lport = 0; 1411573Srgrimes } else { 1421573Srgrimes char num[8]; 1431573Srgrimes int s2 = rresvport(&lport), s3; 1441573Srgrimes int len = sizeof(from); 1452592Scsgr int nfds; 1461573Srgrimes 1471573Srgrimes if (s2 < 0) 1481573Srgrimes goto bad; 1491573Srgrimes listen(s2, 1); 1501573Srgrimes (void)snprintf(num, sizeof(num), "%d", lport); 1511573Srgrimes if (write(s, num, strlen(num)+1) != strlen(num)+1) { 1521573Srgrimes (void)fprintf(stderr, 1531573Srgrimes "rcmd: write (setting up stderr): %s\n", 1541573Srgrimes strerror(errno)); 1551573Srgrimes (void)close(s2); 1561573Srgrimes goto bad; 1571573Srgrimes } 1582592Scsgr nfds = max(s, s2)+1; 1592592Scsgr if(nfds > FD_SETSIZE) { 1602592Scsgr fprintf(stderr, "rcmd: too many files\n"); 1612592Scsgr (void)close(s2); 1622592Scsgr goto bad; 1632592Scsgr } 16417543Speteragain: 1651573Srgrimes FD_ZERO(&reads); 1661573Srgrimes FD_SET(s, &reads); 1671573Srgrimes FD_SET(s2, &reads); 1681573Srgrimes errno = 0; 1692592Scsgr if (select(nfds, &reads, 0, 0, 0) < 1 || !FD_ISSET(s2, &reads)){ 1701573Srgrimes if (errno != 0) 1711573Srgrimes (void)fprintf(stderr, 1721573Srgrimes "rcmd: select (setting up stderr): %s\n", 1731573Srgrimes strerror(errno)); 1741573Srgrimes else 1751573Srgrimes (void)fprintf(stderr, 1761573Srgrimes "select: protocol failure in circuit setup\n"); 1771573Srgrimes (void)close(s2); 1781573Srgrimes goto bad; 1791573Srgrimes } 1801573Srgrimes s3 = accept(s2, (struct sockaddr *)&from, &len); 18117543Speter /* 18217543Speter * XXX careful for ftp bounce attacks. If discovered, shut them 18317543Speter * down and check for the real auxiliary channel to connect. 18417543Speter */ 18517543Speter if (from.sin_family == AF_INET && from.sin_port == htons(20)) { 18617543Speter close(s3); 18717543Speter goto again; 18817543Speter } 1891573Srgrimes (void)close(s2); 1901573Srgrimes if (s3 < 0) { 1911573Srgrimes (void)fprintf(stderr, 1921573Srgrimes "rcmd: accept: %s\n", strerror(errno)); 1931573Srgrimes lport = 0; 1941573Srgrimes goto bad; 1951573Srgrimes } 1961573Srgrimes *fd2p = s3; 1971573Srgrimes from.sin_port = ntohs((u_short)from.sin_port); 1981573Srgrimes if (from.sin_family != AF_INET || 1991573Srgrimes from.sin_port >= IPPORT_RESERVED || 2001573Srgrimes from.sin_port < IPPORT_RESERVED / 2) { 2011573Srgrimes (void)fprintf(stderr, 2021573Srgrimes "socket: protocol failure in circuit setup.\n"); 2031573Srgrimes goto bad2; 2041573Srgrimes } 2051573Srgrimes } 2061573Srgrimes (void)write(s, locuser, strlen(locuser)+1); 2071573Srgrimes (void)write(s, remuser, strlen(remuser)+1); 2081573Srgrimes (void)write(s, cmd, strlen(cmd)+1); 2091573Srgrimes if (read(s, &c, 1) != 1) { 2101573Srgrimes (void)fprintf(stderr, 2111573Srgrimes "rcmd: %s: %s\n", *ahost, strerror(errno)); 2121573Srgrimes goto bad2; 2131573Srgrimes } 2141573Srgrimes if (c != 0) { 2151573Srgrimes while (read(s, &c, 1) == 1) { 2161573Srgrimes (void)write(STDERR_FILENO, &c, 1); 2171573Srgrimes if (c == '\n') 2181573Srgrimes break; 2191573Srgrimes } 2201573Srgrimes goto bad2; 2211573Srgrimes } 2221573Srgrimes sigsetmask(oldmask); 2231573Srgrimes return (s); 2241573Srgrimesbad2: 2251573Srgrimes if (lport) 2261573Srgrimes (void)close(*fd2p); 2271573Srgrimesbad: 2281573Srgrimes (void)close(s); 2291573Srgrimes sigsetmask(oldmask); 2301573Srgrimes return (-1); 2311573Srgrimes} 2321573Srgrimes 2331573Srgrimesint 2341573Srgrimesrresvport(alport) 2351573Srgrimes int *alport; 2361573Srgrimes{ 2371573Srgrimes struct sockaddr_in sin; 23817543Speter int s; 2391573Srgrimes 24017543Speter bzero(&sin, sizeof sin); 24117543Speter sin.sin_len = sizeof(struct sockaddr_in); 2421573Srgrimes sin.sin_family = AF_INET; 2431573Srgrimes sin.sin_addr.s_addr = INADDR_ANY; 2441573Srgrimes s = socket(AF_INET, SOCK_STREAM, 0); 2451573Srgrimes if (s < 0) 2461573Srgrimes return (-1); 24717543Speter#if 0 /* compat_exact_traditional_rresvport_semantics */ 24817543Speter sin.sin_port = htons((u_short)*alport); 24917543Speter if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0) 25017543Speter return (s); 25117543Speter if (errno != EADDRINUSE) { 25216034Speter (void)close(s); 25317543Speter return (-1); 25416034Speter } 25517543Speter#endif 25617543Speter sin.sin_port = 0; 25717543Speter if (bindresvport(s, &sin) == -1) { 25817543Speter (void)close(s); 25917543Speter return (-1); 2601573Srgrimes } 26117543Speter *alport = (int)ntohs(sin.sin_port); 26217543Speter return (s); 2631573Srgrimes} 2641573Srgrimes 2651573Srgrimesint __check_rhosts_file = 1; 2661573Srgrimeschar *__rcmd_errstr; 2671573Srgrimes 2681573Srgrimesint 2691573Srgrimesruserok(rhost, superuser, ruser, luser) 2701573Srgrimes const char *rhost, *ruser, *luser; 2711573Srgrimes int superuser; 2721573Srgrimes{ 2731573Srgrimes struct hostent *hp; 2741573Srgrimes u_long addr; 2751573Srgrimes char **ap; 2761573Srgrimes 2771573Srgrimes if ((hp = gethostbyname(rhost)) == NULL) 2781573Srgrimes return (-1); 2791573Srgrimes for (ap = hp->h_addr_list; *ap; ++ap) { 2801573Srgrimes bcopy(*ap, &addr, sizeof(addr)); 2811573Srgrimes if (iruserok(addr, superuser, ruser, luser) == 0) 2821573Srgrimes return (0); 2831573Srgrimes } 2841573Srgrimes return (-1); 2851573Srgrimes} 2861573Srgrimes 2871573Srgrimes/* 2881573Srgrimes * New .rhosts strategy: We are passed an ip address. We spin through 2891573Srgrimes * hosts.equiv and .rhosts looking for a match. When the .rhosts only 2901573Srgrimes * has ip addresses, we don't have to trust a nameserver. When it 2911573Srgrimes * contains hostnames, we spin through the list of addresses the nameserver 2921573Srgrimes * gives us and look for a match. 2931573Srgrimes * 2941573Srgrimes * Returns 0 if ok, -1 if not ok. 2951573Srgrimes */ 2961573Srgrimesint 2971573Srgrimesiruserok(raddr, superuser, ruser, luser) 2981573Srgrimes u_long raddr; 2991573Srgrimes int superuser; 3001573Srgrimes const char *ruser, *luser; 3011573Srgrimes{ 3021573Srgrimes register char *cp; 3031573Srgrimes struct stat sbuf; 3041573Srgrimes struct passwd *pwd; 3051573Srgrimes FILE *hostf; 3061573Srgrimes uid_t uid; 3071573Srgrimes int first; 3081573Srgrimes char pbuf[MAXPATHLEN]; 3091573Srgrimes 3101573Srgrimes first = 1; 3111573Srgrimes hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r"); 3121573Srgrimesagain: 3131573Srgrimes if (hostf) { 3141573Srgrimes if (__ivaliduser(hostf, raddr, luser, ruser) == 0) { 3151573Srgrimes (void)fclose(hostf); 3161573Srgrimes return (0); 3171573Srgrimes } 3181573Srgrimes (void)fclose(hostf); 3191573Srgrimes } 3201573Srgrimes if (first == 1 && (__check_rhosts_file || superuser)) { 3211573Srgrimes first = 0; 3221573Srgrimes if ((pwd = getpwnam(luser)) == NULL) 3231573Srgrimes return (-1); 3241573Srgrimes (void)strcpy(pbuf, pwd->pw_dir); 3251573Srgrimes (void)strcat(pbuf, "/.rhosts"); 3261573Srgrimes 3271573Srgrimes /* 3281573Srgrimes * Change effective uid while opening .rhosts. If root and 3291573Srgrimes * reading an NFS mounted file system, can't read files that 3301573Srgrimes * are protected read/write owner only. 3311573Srgrimes */ 3321573Srgrimes uid = geteuid(); 3331573Srgrimes (void)seteuid(pwd->pw_uid); 3341573Srgrimes hostf = fopen(pbuf, "r"); 3351573Srgrimes (void)seteuid(uid); 3361573Srgrimes 3371573Srgrimes if (hostf == NULL) 3381573Srgrimes return (-1); 3391573Srgrimes /* 3401573Srgrimes * If not a regular file, or is owned by someone other than 3411573Srgrimes * user or root or if writeable by anyone but the owner, quit. 3421573Srgrimes */ 3431573Srgrimes cp = NULL; 3441573Srgrimes if (lstat(pbuf, &sbuf) < 0) 3451573Srgrimes cp = ".rhosts lstat failed"; 3461573Srgrimes else if (!S_ISREG(sbuf.st_mode)) 3471573Srgrimes cp = ".rhosts not regular file"; 3481573Srgrimes else if (fstat(fileno(hostf), &sbuf) < 0) 3491573Srgrimes cp = ".rhosts fstat failed"; 3501573Srgrimes else if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid) 3511573Srgrimes cp = "bad .rhosts owner"; 3521573Srgrimes else if (sbuf.st_mode & (S_IWGRP|S_IWOTH)) 3531573Srgrimes cp = ".rhosts writeable by other than owner"; 3541573Srgrimes /* If there were any problems, quit. */ 3551573Srgrimes if (cp) { 3561573Srgrimes __rcmd_errstr = cp; 3571573Srgrimes (void)fclose(hostf); 3581573Srgrimes return (-1); 3591573Srgrimes } 3601573Srgrimes goto again; 3611573Srgrimes } 3621573Srgrimes return (-1); 3631573Srgrimes} 3641573Srgrimes 3651573Srgrimes/* 3661573Srgrimes * XXX 3671573Srgrimes * Don't make static, used by lpd(8). 3681573Srgrimes * 3691573Srgrimes * Returns 0 if ok, -1 if not ok. 3701573Srgrimes */ 3711573Srgrimesint 3721573Srgrimes__ivaliduser(hostf, raddr, luser, ruser) 3731573Srgrimes FILE *hostf; 3741573Srgrimes u_long raddr; 3751573Srgrimes const char *luser, *ruser; 3761573Srgrimes{ 3771573Srgrimes register char *user, *p; 3781573Srgrimes int ch; 3791573Srgrimes char buf[MAXHOSTNAMELEN + 128]; /* host + login */ 38010059Swpaul char hname[MAXHOSTNAMELEN]; 3817183Swpaul struct hostent *hp; 3827183Swpaul /* Presumed guilty until proven innocent. */ 3837183Swpaul int userok = 0, hostok = 0; 3849978Swpaul#ifdef YP 3859978Swpaul char *ypdomain; 3861573Srgrimes 3879978Swpaul if (yp_get_default_domain(&ypdomain)) 3889978Swpaul ypdomain = NULL; 3899978Swpaul#else 3909978Swpaul#define ypdomain NULL 3919978Swpaul#endif 3927183Swpaul /* We need to get the damn hostname back for netgroup matching. */ 3937183Swpaul if ((hp = gethostbyaddr((char *)&raddr, sizeof(u_long), 3947183Swpaul AF_INET)) == NULL) 3957183Swpaul return (-1); 39610059Swpaul strcpy(hname, hp->h_name); 3977183Swpaul 3981573Srgrimes while (fgets(buf, sizeof(buf), hostf)) { 3991573Srgrimes p = buf; 4001573Srgrimes /* Skip lines that are too long. */ 4011573Srgrimes if (strchr(p, '\n') == NULL) { 4021573Srgrimes while ((ch = getc(hostf)) != '\n' && ch != EOF); 4031573Srgrimes continue; 4041573Srgrimes } 4059552Speter if (*p == '\n' || *p == '#') { 4069552Speter /* comment... */ 4079552Speter continue; 4089552Speter } 4091573Srgrimes while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') { 4101573Srgrimes *p = isupper(*p) ? tolower(*p) : *p; 4111573Srgrimes p++; 4121573Srgrimes } 4131573Srgrimes if (*p == ' ' || *p == '\t') { 4141573Srgrimes *p++ = '\0'; 4151573Srgrimes while (*p == ' ' || *p == '\t') 4161573Srgrimes p++; 4171573Srgrimes user = p; 4181573Srgrimes while (*p != '\n' && *p != ' ' && 4191573Srgrimes *p != '\t' && *p != '\0') 4201573Srgrimes p++; 4211573Srgrimes } else 4221573Srgrimes user = p; 4231573Srgrimes *p = '\0'; 4247183Swpaul /* 4257183Swpaul * Do +/- and +@/-@ checking. This looks really nasty, 4267183Swpaul * but it matches SunOS's behavior so far as I can tell. 4277183Swpaul */ 4287183Swpaul switch(buf[0]) { 4297183Swpaul case '+': 4307183Swpaul if (!buf[1]) { /* '+' matches all hosts */ 4317183Swpaul hostok = 1; 4327183Swpaul break; 4337183Swpaul } 4347183Swpaul if (buf[1] == '@') /* match a host by netgroup */ 43510059Swpaul hostok = innetgr((char *)&buf[2], 43610059Swpaul (char *)&hname, NULL, ypdomain); 4377183Swpaul else /* match a host by addr */ 4387183Swpaul hostok = __icheckhost(raddr,(char *)&buf[1]); 4397183Swpaul break; 4407183Swpaul case '-': /* reject '-' hosts and all their users */ 4417183Swpaul if (buf[1] == '@') { 4427183Swpaul if (innetgr((char *)&buf[2], 44310059Swpaul (char *)&hname, NULL, ypdomain)) 4447183Swpaul return(-1); 4457183Swpaul } else { 4467183Swpaul if (__icheckhost(raddr,(char *)&buf[1])) 4477183Swpaul return(-1); 4487183Swpaul } 4497183Swpaul break; 4507183Swpaul default: /* if no '+' or '-', do a simple match */ 4517183Swpaul hostok = __icheckhost(raddr, buf); 4527183Swpaul break; 4531573Srgrimes } 4547183Swpaul switch(*user) { 4557183Swpaul case '+': 4567183Swpaul if (!*(user+1)) { /* '+' matches all users */ 4577183Swpaul userok = 1; 4587183Swpaul break; 4597183Swpaul } 4607183Swpaul if (*(user+1) == '@') /* match a user by netgroup */ 4619978Swpaul userok = innetgr(user+2, NULL, ruser, ypdomain); 4627183Swpaul else /* match a user by direct specification */ 4637183Swpaul userok = !(strcmp(ruser, user+1)); 4647183Swpaul break; 4657183Swpaul case '-': /* if we matched a hostname, */ 4667183Swpaul if (hostok) { /* check for user field rejections */ 4677183Swpaul if (!*(user+1)) 4687183Swpaul return(-1); 4697183Swpaul if (*(user+1) == '@') { 4707183Swpaul if (innetgr(user+2, NULL, 4719978Swpaul ruser, ypdomain)) 4727183Swpaul return(-1); 4737183Swpaul } else { 4747183Swpaul if (!strcmp(ruser, user+1)) 4757183Swpaul return(-1); 4767183Swpaul } 4777183Swpaul } 4787183Swpaul break; 4797183Swpaul default: /* no rejections: try to match the user */ 4807183Swpaul if (hostok) 4817183Swpaul userok = !(strcmp(ruser,*user ? user : luser)); 4827183Swpaul break; 4837183Swpaul } 4847183Swpaul if (hostok && userok) 4857183Swpaul return(0); 4861573Srgrimes } 4871573Srgrimes return (-1); 4881573Srgrimes} 4891573Srgrimes 4901573Srgrimes/* 4911573Srgrimes * Returns "true" if match, 0 if no match. 4921573Srgrimes */ 4931573Srgrimesstatic int 4941573Srgrimes__icheckhost(raddr, lhost) 4951573Srgrimes u_long raddr; 4961573Srgrimes register char *lhost; 4971573Srgrimes{ 4981573Srgrimes register struct hostent *hp; 4991573Srgrimes register u_long laddr; 5001573Srgrimes register char **pp; 5011573Srgrimes 5021573Srgrimes /* Try for raw ip address first. */ 5031573Srgrimes if (isdigit(*lhost) && (long)(laddr = inet_addr(lhost)) != -1) 5041573Srgrimes return (raddr == laddr); 5051573Srgrimes 5061573Srgrimes /* Better be a hostname. */ 5071573Srgrimes if ((hp = gethostbyname(lhost)) == NULL) 5081573Srgrimes return (0); 5091573Srgrimes 5101573Srgrimes /* Spin through ip addresses. */ 5111573Srgrimes for (pp = hp->h_addr_list; *pp; ++pp) 5121573Srgrimes if (!bcmp(&raddr, *pp, sizeof(u_long))) 5131573Srgrimes return (1); 5141573Srgrimes 5151573Srgrimes /* No match. */ 5161573Srgrimes return (0); 5171573Srgrimes} 518