commit 913c1d3396ba57052054d6da0745b29f82ece4eb Author: Steve Dickson Date: Mon Dec 17 14:28:03 2007 -0500 Changed is_loopback() and check_access() see if the calling address is an address on a local interface, just not a loopback address. Signed-off-by: Steve Dickson diff --git a/src/security.c b/src/security.c index 7e6f3a9..b1a2b76 100644 --- a/src/security.c +++ b/src/security.c @@ -31,6 +31,7 @@ #ifdef LIBWRAP # include +# include #ifndef LIBWRAP_ALLOW_FACILITY # define LIBWRAP_ALLOW_FACILITY LOG_AUTH #endif @@ -61,6 +62,49 @@ int log_severity = PORTMAP_LOG_FACILITY|PORTMAP_LOG_SEVERITY; extern int verboselog; +#ifdef LIBWRAP +static int localaddr(struct sockaddr *addr) +{ + static struct ifaddrs *ifp = NULL; + struct ifaddrs *ifa = NULL; + void *caller, *localip; + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; + + if (ifp == NULL && getifaddrs (&ifp) < 0) { + perror ("getifaddrs"); + return 0; + } + + if (addr->sa_family == AF_INET) + caller = (void *)&((struct sockaddr_in *)addr)->sin_addr; + else + caller = (void *)&((struct sockaddr_in6 *)addr)->sin6_addr; + + for (ifa = ifp; ifa; ifa = ifa->ifa_next) { + socklen_t salen; + + if (ifa->ifa_addr == NULL) + continue; + + if (ifa->ifa_addr->sa_family == AF_INET) { + salen = sizeof (struct sockaddr_in); + sin = (struct sockaddr_in *)ifa->ifa_addr; + localip = (void *)&sin->sin_addr; + } else if (ifa->ifa_addr->sa_family == AF_INET6) { + sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; + localip = (void *)&sin6->sin6_addr; + } else + continue; + + if (memcmp(localip, caller, salen) == 0) + return 1; + } + + return 0; +} +#endif + int check_access(SVCXPRT *xprt, rpcproc_t proc, void *args, unsigned int rpcbvers) { @@ -115,7 +159,7 @@ check_access(SVCXPRT *xprt, rpcproc_t proc, void *args, unsigned int rpcbvers) } #ifdef LIBWRAP - if (addr->sa_family == AF_LOCAL) + if (addr->sa_family == AF_LOCAL || localaddr(addr)) return 1; request_init(&req, RQ_DAEMON, "rpcbind", RQ_CLIENT_SIN, addr, 0); sock_methods(&req); @@ -147,13 +191,17 @@ is_loopback(struct netbuf *nbuf) case AF_INET: if (!oldstyle_local) return 0; + if (localaddr(addr)) + return 1; sin = (struct sockaddr_in *)addr; - return ((sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) && + return ((sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) && (ntohs(sin->sin_port) < IPPORT_RESERVED)); #ifdef INET6 case AF_INET6: if (!oldstyle_local) return 0; + if (localaddr(addr)) + return 1; sin6 = (struct sockaddr_in6 *)addr; return ((IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr) || (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) &&