- __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:
parent
b741a1c581
commit
eb74b99618
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user