Blob Blame History Raw
commit 913c1d3396ba57052054d6da0745b29f82ece4eb
Author: Steve Dickson <steved@redhat.com>
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 <steved@redhat.com>

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 <tcpd.h>
+# include <ifaddrs.h>
 #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) &&