- __ivaliduser_sa() was introduced for forthcoming IPv6 support to lpd

- iruserok_sa() and __ivaliduser_af() were re-organized to use
  __ivaliduser_sa()
- __icheckhost() was re-written to use getaddrinfo() instead of
  getipnodebyname()
- better handling of multiple destination addresses in rcmd()

These changes were basically taken from KAME and changed to fit our
rcmd.c.

Obtained from:	KAME
This commit is contained in:
Hajimu UMEMOTO 2000-12-04 18:02:12 +00:00
parent b741a1c581
commit eb74b99618

View File

@ -69,11 +69,15 @@ extern int innetgr __P(( const char *, const char *, const char *, const char *
#define max(a, b) ((a > b) ? a : b) #define max(a, b) ((a > b) ? a : b)
static int __iruserok_af __P((void *, int, const char *, const char *, int));
int __ivaliduser __P((FILE *, u_int32_t, const char *, const char *)); int __ivaliduser __P((FILE *, u_int32_t, const char *, const char *));
static int __icheckhost __P((void *, char *, int, int)); int __ivaliduser_af __P((FILE *,const void *, const char *, const char *,
int, int));
int __ivaliduser_sa __P((FILE *, const struct sockaddr *, socklen_t,
const char *,const char *));
static int __icheckhost __P((const struct sockaddr *, socklen_t,
const char *));
char paddr[INET6_ADDRSTRLEN]; char paddr[NI_MAXHOST];
int int
rcmd(ahost, rport, locuser, remuser, cmd, fd2p) rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
@ -100,6 +104,7 @@ rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, af)
pid_t pid; pid_t pid;
int s, aport, lport, timo, error; int s, aport, lport, timo, error;
char c; char c;
int refused, nres;
char num[8]; char num[8];
static char canonnamebuf[MAXDNAME]; /* is it proper here? */ static char canonnamebuf[MAXDNAME]; /* is it proper here? */
@ -126,7 +131,11 @@ rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, af)
strncpy(canonnamebuf, res->ai_canonname, sizeof(canonnamebuf)); strncpy(canonnamebuf, res->ai_canonname, sizeof(canonnamebuf));
*ahost = canonnamebuf; *ahost = canonnamebuf;
} }
nres = 0;
for (ai = res; ai; ai = ai->ai_next)
nres++;
ai = res; ai = res;
refused = 0;
oldmask = sigblock(sigmask(SIGURG)); oldmask = sigblock(sigmask(SIGURG));
for (timo = 1, lport = IPPORT_RESERVED - 1;;) { for (timo = 1, lport = IPPORT_RESERVED - 1;;) {
s = rresvport_af(&lport, ai->ai_family); s = rresvport_af(&lport, ai->ai_family);
@ -153,15 +162,16 @@ rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, af)
lport--; lport--;
continue; continue;
} }
if (errno == ECONNREFUSED && timo <= 16) { if (errno == ECONNREFUSED)
struct timespec time_to_sleep, time_remaining; refused = 1;
if (ai->ai_next == NULL && (!refused || timo > 16)) {
time_to_sleep.tv_sec = timo; (void)fprintf(stderr, "%s: %s\n",
time_to_sleep.tv_nsec = 0; *ahost, strerror(errno));
(void)_nanosleep(&time_to_sleep, &time_remaining); freeaddrinfo(res);
timo *= 2; sigsetmask(oldmask);
return (-1);
} }
if (ai->ai_next != NULL) { if (nres > 1) {
int oerrno = errno; int oerrno = errno;
getnameinfo(ai->ai_addr, ai->ai_addrlen, getnameinfo(ai->ai_addr, ai->ai_addrlen,
@ -172,18 +182,25 @@ rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, af)
paddr); paddr);
errno = oerrno; errno = oerrno;
perror(0); perror(0);
ai = ai->ai_next; }
if ((ai = ai->ai_next) == NULL) {
/* refused && timo <= 16 */
struct timespec time_to_sleep, time_remaining;
time_to_sleep.tv_sec = timo;
time_to_sleep.tv_nsec = 0;
(void)_nanosleep(&time_to_sleep, &time_remaining);
timo *= 2;
ai = res;
refused = 0;
}
if (nres > 1) {
getnameinfo(ai->ai_addr, ai->ai_addrlen, getnameinfo(ai->ai_addr, ai->ai_addrlen,
paddr, sizeof(paddr), paddr, sizeof(paddr),
NULL, 0, NULL, 0,
NI_NUMERICHOST|NI_WITHSCOPEID); NI_NUMERICHOST|NI_WITHSCOPEID);
fprintf(stderr, "Trying %s...\n", paddr); fprintf(stderr, "Trying %s...\n", paddr);
continue;
} }
(void)fprintf(stderr, "%s: %s\n", *ahost, strerror(errno));
freeaddrinfo(res);
sigsetmask(oldmask);
return (-1);
} }
lport--; lport--;
if (fd2p == 0) { if (fd2p == 0) {
@ -393,16 +410,27 @@ iruserok(raddr, superuser, ruser, luser)
int superuser; int superuser;
const char *ruser, *luser; const char *ruser, *luser;
{ {
return __iruserok_af(&raddr, superuser, ruser, luser, AF_INET); struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_len = sizeof(struct sockaddr_in);
memcpy(&sin.sin_addr, &raddr, sizeof(sin.sin_addr));
return iruserok_sa((struct sockaddr *)&sin, sin.sin_len, superuser,
ruser, luser);
} }
/* Other AF support extension of iruserok. */ /*
static int * AF independent extension of iruserok.
__iruserok_af(raddr, superuser, ruser, luser, af) *
void *raddr; * Returns 0 if ok, -1 if not ok.
*/
int
iruserok_sa(ra, rlen, superuser, ruser, luser)
const void *ra;
int rlen;
int superuser; int superuser;
const char *ruser, *luser; const char *ruser, *luser;
int af;
{ {
register char *cp; register char *cp;
struct stat sbuf; struct stat sbuf;
@ -411,25 +439,20 @@ __iruserok_af(raddr, superuser, ruser, luser, af)
uid_t uid; uid_t uid;
int first; int first;
char pbuf[MAXPATHLEN]; char pbuf[MAXPATHLEN];
int len = 0; const struct sockaddr *raddr;
struct sockaddr_storage ss;
switch (af) { /* avoid alignment issue */
case AF_INET: if (rlen > sizeof(ss))
len = sizeof(struct in_addr); return(-1);
break; memcpy(&ss, ra, rlen);
#ifdef INET6 raddr = (struct sockaddr *)&ss;
case AF_INET6:
len = sizeof(struct in6_addr);
break;
#endif
}
first = 1; first = 1;
hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r"); hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r");
again: again:
if (hostf) { if (hostf) {
if (__ivaliduser_af(hostf, raddr, luser, ruser, af, len) if (__ivaliduser_sa(hostf, raddr, rlen, luser, ruser) == 0) {
== 0) {
(void)fclose(hostf); (void)fclose(hostf);
return (0); return (0);
} }
@ -480,37 +503,6 @@ __iruserok_af(raddr, superuser, ruser, luser, af)
return (-1); return (-1);
} }
/*
* AF independent extension of iruserok. We are passed an sockaddr, and
* then call iruserok_af() as the type of sockaddr.
*
* Returns 0 if ok, -1 if not ok.
*/
int
iruserok_sa(addr, addrlen, superuser, ruser, luser)
const void *addr;
int addrlen;
int superuser;
const char *ruser, *luser;
{
struct sockaddr *sa;
void *raddr = NULL;
sa = (struct sockaddr *)addr;
switch (sa->sa_family) {
case AF_INET:
raddr = &((struct sockaddr_in *)sa)->sin_addr;
break;
#ifdef INET6
case AF_INET6:
raddr = &((struct sockaddr_in6 *)sa)->sin6_addr;
break;
#endif
}
__iruserok_af(raddr, superuser, ruser, luser, sa->sa_family);
}
/* /*
* XXX * XXX
* Don't make static, used by lpd(8). * Don't make static, used by lpd(8).
@ -523,22 +515,78 @@ __ivaliduser(hostf, raddr, luser, ruser)
u_int32_t raddr; u_int32_t raddr;
const char *luser, *ruser; const char *luser, *ruser;
{ {
return __ivaliduser_af(hostf, &raddr, luser, ruser, AF_INET, struct sockaddr_in sin;
sizeof(raddr));
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_len = sizeof(struct sockaddr_in);
memcpy(&sin.sin_addr, &raddr, sizeof(sin.sin_addr));
return __ivaliduser_sa(hostf, (struct sockaddr *)&sin, sin.sin_len,
luser, ruser);
} }
/*
* Returns 0 if ok, -1 if not ok.
*
* XXX obsolete API.
*/
int int
__ivaliduser_af(hostf, raddr, luser, ruser, af, len) __ivaliduser_af(hostf, raddr, luser, ruser, af, len)
FILE *hostf; FILE *hostf;
void *raddr; const void *raddr;
const char *luser, *ruser; const char *luser, *ruser;
int af, len; int af, len;
{
struct sockaddr *sa = NULL;
struct sockaddr_in *sin = NULL;
#ifdef INET6
struct sockaddr_in6 *sin6 = NULL;
#endif
struct sockaddr_storage ss;
memset(&ss, 0, sizeof(ss));
switch (af) {
case AF_INET:
if (len != sizeof(sin->sin_addr))
return -1;
sin = (struct sockaddr_in *)&ss;
sin->sin_family = AF_INET;
sin->sin_len = sizeof(struct sockaddr_in);
memcpy(&sin->sin_addr, raddr, sizeof(sin->sin_addr));
break;
#ifdef INET6
case AF_INET6:
if (len != sizeof(sin6->sin6_addr))
return -1;
/* you will lose scope info */
sin6 = (struct sockaddr_in6 *)&ss;
sin6->sin6_family = AF_INET6;
sin6->sin6_len = sizeof(struct sockaddr_in6);
memcpy(&sin6->sin6_addr, raddr, sizeof(sin6->sin6_addr));
break;
#endif
default:
return -1;
}
sa = (struct sockaddr *)&ss;
return __ivaliduser_sa(hostf, sa, sa->sa_len, luser, ruser);
}
/*
* Returns 0 if ok, -1 if not ok.
*/
int
__ivaliduser_sa(hostf, raddr, salen, luser, ruser)
FILE *hostf;
const struct sockaddr *raddr;
socklen_t salen;
const char *luser, *ruser;
{ {
register char *user, *p; register char *user, *p;
int ch; int ch;
char buf[MAXHOSTNAMELEN + 128]; /* host + login */ char buf[MAXHOSTNAMELEN + 128]; /* host + login */
char hname[MAXHOSTNAMELEN]; char hname[MAXHOSTNAMELEN];
struct hostent *hp;
/* Presumed guilty until proven innocent. */ /* Presumed guilty until proven innocent. */
int userok = 0, hostok = 0; int userok = 0, hostok = 0;
int h_error; int h_error;
@ -551,11 +599,9 @@ __ivaliduser_af(hostf, raddr, luser, ruser, af, len)
#define ypdomain NULL #define ypdomain NULL
#endif #endif
/* We need to get the damn hostname back for netgroup matching. */ /* We need to get the damn hostname back for netgroup matching. */
if ((hp = getipnodebyaddr((char *)raddr, len, af, &h_error)) == NULL) if (getnameinfo(raddr, salen, hname, sizeof(hname), NULL, 0,
NI_NAMEREQD) != 0)
return (-1); return (-1);
strncpy(hname, hp->h_name, sizeof(hname));
hname[sizeof(hname) - 1] = '\0';
freehostent(hp);
while (fgets(buf, sizeof(buf), hostf)) { while (fgets(buf, sizeof(buf), hostf)) {
p = buf; p = buf;
@ -597,8 +643,8 @@ __ivaliduser_af(hostf, raddr, luser, ruser, af, len)
hostok = innetgr((char *)&buf[2], hostok = innetgr((char *)&buf[2],
(char *)&hname, NULL, ypdomain); (char *)&hname, NULL, ypdomain);
else /* match a host by addr */ else /* match a host by addr */
hostok = __icheckhost(raddr,(char *)&buf[1], hostok = __icheckhost(raddr, salen,
af, len); (char *)&buf[1]);
break; break;
case '-': /* reject '-' hosts and all their users */ case '-': /* reject '-' hosts and all their users */
if (buf[1] == '@') { if (buf[1] == '@') {
@ -606,12 +652,13 @@ __ivaliduser_af(hostf, raddr, luser, ruser, af, len)
(char *)&hname, NULL, ypdomain)) (char *)&hname, NULL, ypdomain))
return(-1); return(-1);
} else { } else {
if (__icheckhost(raddr,(char *)&buf[1],af,len)) if (__icheckhost(raddr, salen,
(char *)&buf[1]))
return(-1); return(-1);
} }
break; break;
default: /* if no '+' or '-', do a simple match */ default: /* if no '+' or '-', do a simple match */
hostok = __icheckhost(raddr, buf, af, len); hostok = __icheckhost(raddr, salen, buf);
break; break;
} }
switch(*user) { switch(*user) {
@ -652,40 +699,61 @@ __ivaliduser_af(hostf, raddr, luser, ruser, af, len)
/* /*
* Returns "true" if match, 0 if no match. * Returns "true" if match, 0 if no match.
*
* NI_WITHSCOPEID is useful for comparing sin6_scope_id portion
* if af == AF_INET6.
*/ */
static int static int
__icheckhost(raddr, lhost, af, len) __icheckhost(raddr, salen, lhost)
void *raddr; const struct sockaddr *raddr;
register char *lhost; socklen_t salen;
int af, len; const char *lhost;
{ {
register struct hostent *hp; struct sockaddr_in sin;
char laddr[BUFSIZ]; /* xxx */ struct sockaddr_in6 *sin6;
register char **pp; struct addrinfo hints, *res, *r;
int h_error; int error;
int match; char h1[NI_MAXHOST], h2[NI_MAXHOST];
/* Try for raw ip address first. */ if (raddr->sa_family == AF_INET6) {
if (inet_pton(af, lhost, laddr) == 1) { sin6 = (struct sockaddr_in6 *)raddr;
if (memcmp(raddr, laddr, len) == 0) if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
return (1); memset(&sin, 0, sizeof(sin));
else sin.sin_family = AF_INET;
return (0); sin.sin_len = sizeof(struct sockaddr_in);
memcpy(&sin.sin_addr, &sin6->sin6_addr.s6_addr[12],
sizeof(sin.sin_addr));
raddr = (struct sockaddr *)&sin;
salen = sin.sin_len;
}
} }
/* Better be a hostname. */ h1[0] = '\0';
if ((hp = getipnodebyname(lhost, af, AI_ALL|AI_DEFAULT, &h_error)) if (getnameinfo(raddr, salen, h1, sizeof(h1), NULL, 0,
== NULL) NI_NUMERICHOST | NI_WITHSCOPEID) != 0)
return (0); return (0);
/* Spin through ip addresses. */ /* Resolve laddr into sockaddr */
match = 0; memset(&hints, 0, sizeof(hints));
for (pp = hp->h_addr_list; *pp; ++pp) hints.ai_family = raddr->sa_family;
if (!bcmp(raddr, *pp, len)) { hints.ai_socktype = SOCK_DGRAM; /*XXX dummy*/
match = 1; res = NULL;
break; error = getaddrinfo(lhost, "0", &hints, &res);
} if (error)
return (0);
freehostent(hp); for (r = res; r ; r = r->ai_next) {
return (match); h2[0] = '\0';
if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2),
NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID) != 0)
continue;
if (strcmp(h1, h2) == 0) {
freeaddrinfo(res);
return (1);
}
}
/* No match. */
freeaddrinfo(res);
return (0);
} }