Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 29 May 2011 12:15:49 +0000 (UTC)
From:      Hiroki Sato <hrs@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r222448 - user/hrs/ipv6/usr.sbin/ypserv
Message-ID:  <201105291215.p4TCFnt0029384@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hrs
Date: Sun May 29 12:15:49 2011
New Revision: 222448
URL: http://svn.freebsd.org/changeset/base/222448

Log:
  - Enable transports other than INET including INET6.
  
  - Use svc_getrpccaller() instead of svc_getcaller() to support
    transports other than INET.
  
  - Extend /var/yp/securenets to support CIDR notation and IPv6 address.
    It now supports the following:
  
    127.0.0.1     255.0.0.0
    127.0.0.1/8
    172.16.10.1
    fe80::1%fxp0/10
    2001:db8:1::1 ffff:ffff:ffff:ffff::
    2001:db8:2::1/68
    2001:db8:3::1
  
  - Add -S flag to support Sorlais-compatible securenets format.
  
  - Fix memory leak on removal of socklist and bindaddrlist.
  
  - Remove inconsistent LINEBUFSZ, use BUFSIZ.
  
  - Style(9) fixes.

Added:
  user/hrs/ipv6/usr.sbin/ypserv/yp_access_inet.c
  user/hrs/ipv6/usr.sbin/ypserv/yp_access_inet6.c
Modified:
  user/hrs/ipv6/usr.sbin/ypserv/Makefile
  user/hrs/ipv6/usr.sbin/ypserv/yp_access.c
  user/hrs/ipv6/usr.sbin/ypserv/yp_extern.h
  user/hrs/ipv6/usr.sbin/ypserv/yp_main.c
  user/hrs/ipv6/usr.sbin/ypserv/ypserv.8

Modified: user/hrs/ipv6/usr.sbin/ypserv/Makefile
==============================================================================
--- user/hrs/ipv6/usr.sbin/ypserv/Makefile	Sun May 29 11:10:56 2011	(r222447)
+++ user/hrs/ipv6/usr.sbin/ypserv/Makefile	Sun May 29 12:15:49 2011	(r222448)
@@ -3,10 +3,18 @@
 RPCDIR=	${.CURDIR}/../../include/rpcsvc
 .PATH: ${RPCDIR}
 
+.include <bsd.own.mk>
+
 PROG=	ypserv
 MAN=	ypserv.8 ypinit.8
 SRCS=	yp_svc.c yp_server.c yp_dblookup.c yp_dnslookup.c \
 	ypxfr_clnt.c yp.h yp_main.c yp_error.c yp_access.c yp_svc_udp.c
+.if ${MK_INET_SUPPORT} != "no"
+SRCS+=	yp_access_inet.c
+.endif
+.if ${MK_INET6_SUPPORT} != "no"
+SRCS+=	yp_access_inet6.c
+.endif
 
 CFLAGS+= -DDB_CACHE -DTCP_WRAPPER -I.
 

Modified: user/hrs/ipv6/usr.sbin/ypserv/yp_access.c
==============================================================================
--- user/hrs/ipv6/usr.sbin/ypserv/yp_access.c	Sun May 29 11:10:56 2011	(r222447)
+++ user/hrs/ipv6/usr.sbin/ypserv/yp_access.c	Sun May 29 12:15:49 2011	(r222448)
@@ -34,31 +34,35 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
-#include <stdlib.h>
+#include <sys/fcntl.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 #include <rpc/rpc.h>
 #include <rpcsvc/yp.h>
 #include <rpcsvc/yppasswd.h>
 #include <rpcsvc/ypxfrd.h>
-#include <sys/types.h>
-#include <limits.h>
-#include <db.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
 #include <arpa/inet.h>
-#include <sys/stat.h>
-#include <sys/fcntl.h>
-#include <paths.h>
+#include <netinet/in.h>
+#include <db.h>
 #include <errno.h>
-#include <sys/param.h>
+#include <limits.h>
+#include <netdb.h>
+#include <paths.h>
+#include <stdlib.h>
+
 #include "yp_extern.h"
 #ifdef TCP_WRAPPER
 #include "tcpd.h"
 #endif
 
+extern int hosts_ctl(char *, char *, char *, char *);
 extern int debug;
 
-			/* NIS v1 */
 const char *yp_procs[] = {
+	/* NIS v1 */
 	"ypoldproc_null",
 	"ypoldproc_domain",
 	"ypoldproc_domain_nonack",
@@ -87,89 +91,424 @@ const char *yp_procs[] = {
 	"ypproc_maplist"
 };
 
+static SLIST_HEAD(, securenet) securenets =
+	SLIST_HEAD_INITIALIZER(securenets);
 struct securenet {
-	struct in_addr net;
-	struct in_addr mask;
-	struct securenet *next;
+	struct sockaddr_storage	sn_addr;
+	struct sockaddr_storage	sn_mask;
+	SLIST_ENTRY(securenet)	sn_next;
 };
 
-struct securenet *securenets;
+static int
+mask2prefixlen(const struct sockaddr *sap, int *prefixlen)
+{
+	switch (sap->sa_family) {
+#ifdef AF_INET
+	case AF_INET:
+		return (yp_mask2prefixlen_in(sap, prefixlen));
+		break;
+#endif
+#ifdef AF_INET6
+	case AF_INET6:
+		return (yp_mask2prefixlen_in6(sap, prefixlen));
+		break;
+#endif
+	default:
+		break;
+	}
+	return (-1);
+}
 
-#define LINEBUFSZ 1024
+static int
+prefixlen2mask(struct sockaddr *sap, const int *prefixlen)
+{
+	switch (sap->sa_family) {
+#ifdef AF_INET
+	case AF_INET:
+		return (yp_prefixlen2mask_in(sap, prefixlen));
+		break;
+#endif
+#ifdef AF_INET6
+	case AF_INET6:
+		return (yp_prefixlen2mask_in6(sap, prefixlen));
+		break;
+#endif
+	default:
+		break;
+	}
+	return (-1);
+}
+
+void
+yp_debug_sa(const struct sockaddr *sap)
+{
+	int error;
+	char host[NI_MAXHOST + 1];
+	char serv[NI_MAXSERV + 1];
+
+	error = getnameinfo(sap, sap->sa_len, host, sizeof(host), serv,
+		    sizeof(serv), NI_NUMERICHOST | NI_NUMERICSERV);
+	if (error)
+		yp_error("sockaddr: %s", gai_strerror(error));
+	else
+		yp_error("sockaddr: %d/%s/%s", sap->sa_family, host, serv);
+}
+
+void
+show_securenets(void)
+{
+	struct securenet *snp;
+	struct sockaddr *sap;
+	int i = 0;
+
+	yp_error("--- securenets dump start ---");
+	SLIST_FOREACH(snp, &securenets, sn_next) {
+		i++;
+		yp_error("entry %d:", i);
+		sap = (struct sockaddr *)&(snp->sn_addr);
+		yp_debug_sa(sap);
+		sap = (struct sockaddr *)&(snp->sn_mask);
+		yp_debug_sa(sap);
+	}
+	yp_error("--- securenets dump end ---");
+}
 
 /*
  * Read /var/yp/securenets file and initialize the securenets
  * list. If the file doesn't exist, we set up a dummy entry that
  * allows all hosts to connect.
  */
-void
+#define YP_ACL_HOSTMASK_INET	"255.255.255.255"
+#define YP_ACL_HOSTMASK_INET6	"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"
+int
 load_securenets(void)
 {
 	FILE *fp;
-	char path[MAXPATHLEN + 2];
-	char linebuf[1024 + 2];
-	struct securenet *tmp;
-
-	/*
-	 * If securenets is not NULL, we are being called to reload
-	 * the list; free the existing list before re-reading the
-	 * securenets file.
-	 */
-	while (securenets) {
-		tmp = securenets->next;
-		free(securenets);
-		securenets = tmp;
+	char linebuf[BUFSIZ + 2];
+	struct securenet *snp;
+	struct sockaddr *sap;
+	int error = 0;
+	int line;
+	struct addrinfo hints, *res, *res0;
+
+	if (SLIST_EMPTY(&securenets))
+		SLIST_INIT(&securenets);
+	else {
+		/*
+		 * If securenets is not NULL, we are being called to reload
+		 * the list; free the existing list before re-reading the
+		 * securenets file.
+		 */
+		while (!SLIST_EMPTY(&securenets)) {
+			snp = SLIST_FIRST(&securenets);
+			SLIST_REMOVE_HEAD(&securenets, sn_next);
+			free(snp);
+		}
 	}
-
-	snprintf(path, MAXPATHLEN, "%s/securenets", yp_dir);
-
-	if ((fp = fopen(path, "r")) == NULL) {
+	if (debug)
+		yp_error("load_securenets(): loading %s", securenets_path);
+	if ((fp = fopen(securenets_path, "r")) == NULL) {
 		if (errno == ENOENT) {
-			securenets = (struct securenet *)malloc(sizeof(struct securenet));
-			securenets->net.s_addr = INADDR_ANY;
-			securenets->mask.s_addr = INADDR_ANY;
-			securenets->next = NULL;
-			return;
+			/* Create empty access list. */
+			if (debug)
+				yp_error("load_securenets(): ENOENT");
+			memset(&hints, 0, sizeof(hints));
+			hints.ai_family = PF_UNSPEC;
+			hints.ai_flags = AI_PASSIVE;
+			hints.ai_socktype = SOCK_STREAM;
+			error = getaddrinfo(NULL, "0", &hints, &res0);
+			if (error) {
+				yp_error("getaddrinfo() failed: %s",
+				    gai_strerror(error));
+				freeaddrinfo(res0);
+				return (1);
+			}
+			for (res = res0; res; res = res->ai_next) {
+				struct sockaddr *sap;
+				snp = malloc(sizeof(*snp));
+				memset(snp, 0, sizeof(*snp));
+				memcpy(&snp->sn_addr, res->ai_addr,
+				   sizeof(res->ai_addrlen));
+				memcpy(&snp->sn_mask, res->ai_addr,
+				   sizeof(res->ai_addrlen));
+				sap = (struct sockaddr *)&(snp->sn_mask);
+				prefixlen2mask(sap, 0);
+				SLIST_INSERT_HEAD(&securenets, snp, sn_next);
+			}
+			freeaddrinfo(res0);
+			return (0);
 		} else {
-			yp_error("fopen(%s) failed: %s", path, strerror(errno));
-			exit(1);
+			yp_error("fopen(%s) failed: %s", securenets_path,
+			    strerror(errno));
+			return (1);
 		}
 	}
 
-	securenets = NULL;
-
-	while (fgets(linebuf, LINEBUFSZ, fp)) {
-		char addr1[20], addr2[20];
-
+	line = 0;
+	while (fgets(linebuf, sizeof(linebuf), fp)) {
+		int nitems;
+		char *col_host;
+		char *col_mask;
+		char addr1[NI_MAXHOST + 1];
+		char addr2[NI_MAXHOST + 1];
+		int plen;
+		sa_family_t family;
+		char *p;
+
+		line++;
+		if (debug)
+			yp_error("load_securenets(): read line %d", line);
 		if ((linebuf[0] == '#')
 		    || (strspn(linebuf, " \t\r\n") == strlen(linebuf)))
 			continue;
-		if (sscanf(linebuf, "%s %s", addr1, addr2) < 2) {
-			yp_error("badly formatted securenets entry: %s",
-							linebuf);
-			continue;
-		}
-
-		tmp = (struct securenet *)malloc(sizeof(struct securenet));
+		nitems = sscanf(linebuf, "%s %s", addr1, addr2);
+		snp = malloc(sizeof(*snp));
+		memset(snp, 0, sizeof(*snp));
+
+		if (debug)
+			yp_error("load_securenets(): nitems = %d", nitems);
+		if (nitems == 2) {
+			switch (securenets_format) {
+			case YP_SNF_NATIVE:
+				/* ex. 127.0.0.1 255.0.0.0 */
+				col_host = addr1;
+				col_mask = addr2;
+				break;
+			case YP_SNF_SOLARIS:
+				/* ex. 255.0.0.0 127.0.0.1  */
+				col_host = addr2;
+				col_mask = addr1;
+				break;
+			default:
+				yp_error("line %d: internal error: %s",
+					 line, linebuf);
+				continue;
+
+			}
+			if (debug) {
+				yp_error("load_securenets(): try mask expr");
+				yp_error("load_securenets(): host = [%s]",
+				    col_host);
+				yp_error("load_securenets(): mask = [%s]",
+				    col_mask);
+			}
+			memset(&hints, 0, sizeof(hints));
+			hints.ai_family = PF_UNSPEC;
+			hints.ai_socktype = SOCK_STREAM;
+			hints.ai_flags = AI_NUMERICHOST;
+			error = getaddrinfo(col_host, NULL, &hints, &res0);
+			if (error) {
+				yp_error("line %d: "
+					 "badly formatted securenets entry: "
+					 "%s: %s: %s", line, linebuf,
+					 gai_strerror(error));
+				freeaddrinfo(res0);
+				free(snp);
+				continue;
+			}
+			memcpy(&snp->sn_addr, res0->ai_addr, res0->ai_addrlen);
+			family = res0->ai_addr->sa_family;
+			freeaddrinfo(res0);
+
+			if ((securenets_format == YP_SNF_SOLARIS) &&
+			    (strcmp(col_host, "host") == 0)) {
+				switch (family) {
+#ifdef AF_INET
+				case AF_INET:
+					col_host = YP_ACL_HOSTMASK_INET;
+					break;
+#endif
+#ifdef AF_INET6
+				case AF_INET6:
+					col_host = YP_ACL_HOSTMASK_INET6;
+					break;
+#endif
+				default:
+					yp_error("line %d: host keyword for "
+						 "unsupported address family: "
+						 "%s: %s", line, linebuf,
+						 gai_strerror(error));
+					continue;
+				}
+			}
+			memset(&hints, 0, sizeof(hints));
+			hints.ai_family = PF_UNSPEC;
+			hints.ai_socktype = SOCK_STREAM;
+			hints.ai_flags = AI_NUMERICHOST;
+			error = getaddrinfo(col_mask, NULL, &hints, &res0);
+			if (error) {
+				yp_error("line %d: "
+				    "badly formatted securenets entry: "
+				    "%s: %s: %s", line, linebuf,
+				    gai_strerror(error));
+				freeaddrinfo(res0);
+				free(snp);
+				continue;
+			}
+			memcpy(&snp->sn_mask, res0->ai_addr, res0->ai_addrlen);
+			freeaddrinfo(res0);
+		} else if (nitems == 1) {
+			/* ex. 127.0.0.1/8 */
+			/* ex. fe80::/10 */
+			if (debug)
+				yp_error("load_securenets(): try CIDR expr");
+			p = strrchr(addr1, '/');
+			if (p != NULL) {
+				*p = ' ';
+				nitems = sscanf(addr1, "%s %d", addr2, &plen);
+				if (nitems < 2) {
+					yp_error("line %d: "
+						 "badly formatted securenets entry:"
+						 " %s", line, linebuf);
+					free(snp);
+					continue;
+				}
+			} else
+				memcpy(addr2, addr1, sizeof(addr2));
+
+			memset(&hints, 0, sizeof(hints));
+			hints.ai_family = PF_UNSPEC;
+			hints.ai_socktype = SOCK_STREAM;
+			hints.ai_flags = AI_NUMERICHOST;
+			error = getaddrinfo(addr2, NULL, &hints, &res0);
+			if (error) {
+				yp_error("line %d: "
+				    "badly formatted securenets entry: "
+				    "%s: %s", line, linebuf,
+				    gai_strerror(error));
+				freeaddrinfo(res0);
+				free(snp);
+				continue;
+			}
+			if (p == NULL)
+				switch (res0->ai_addr->sa_family) {
+#ifdef AF_INET
+				case AF_INET:
+					plen = 32;
+					break;
+#endif
+#ifdef AF_INET6
+				case AF_INET6:
+					plen = 128;
+					break;
+#endif
+				default:
+					yp_error("line %d: "
+						 "unsupported address family: "
+						 "%s: %s", line, linebuf,
+						 gai_strerror(error));
+					continue;
+				}
+			if (debug) {
+				yp_error("load_securenets(): addr2 = [%s]",
+				    addr2);
+				yp_error("load_securenets(): plen = [%d]",
+				    plen);
+			}
+			memcpy(&snp->sn_addr, res0->ai_addr, res0->ai_addrlen);
+			memcpy(&snp->sn_mask, res0->ai_addr, res0->ai_addrlen);
+			freeaddrinfo(res0);
 
-		if (!inet_aton((char *)&addr1, (struct in_addr *)&tmp->net)) {
-			yp_error("badly formatted securenets entry: %s", addr1);
-			free(tmp);
+			sap = (struct sockaddr *)&(snp->sn_mask);
+			prefixlen2mask(sap, &plen);
+		} else {
+			yp_error("line %d: "
+			    "badly formatted securenets entry: "
+			    "%s", line, linebuf);
 			continue;
 		}
-
-		if (!inet_aton((char *)&addr2, (struct in_addr *)&tmp->mask)) {
-			yp_error("badly formatted securenets entry: %s", addr2);
-			free(tmp);
-			continue;
+		if (debug) {
+			yp_error("load_securenets(): adding entry");
+			yp_debug_sa((struct sockaddr*)&(snp->sn_addr));
+			yp_debug_sa((struct sockaddr *)&(snp->sn_mask));
 		}
-
-		tmp->next = securenets;
-		securenets = tmp;
+		SLIST_INSERT_HEAD(&securenets, snp, sn_next);
 	}
-
 	fclose(fp);
+	if (debug)
+		show_securenets();
+	return (0);
+}
 
+static int
+compare_subnet(struct sockaddr *addr1,
+	       struct sockaddr *addr2,
+	       struct sockaddr *mask)
+{
+#ifdef AF_INET
+	struct sockaddr_in *in_addr1;
+	struct sockaddr_in *in_addr2;
+	struct sockaddr_in *in_addrm;
+#endif
+#ifdef AF_INET6
+	struct sockaddr_in6 *in6_addr1;
+	struct sockaddr_in6 *in6_addr2;
+	struct sockaddr_in6 *in6_addrm;
+#endif
+	u_char a1[sizeof(struct sockaddr_storage)];
+	u_char a2[sizeof(struct sockaddr_storage)];
+	u_char m[sizeof(struct sockaddr_storage)];
+	size_t len;
+	int i;
+	int samescope;
+
+	if (addr1->sa_family != addr2->sa_family)
+		return (1);
+
+	memset(a1, 0, sizeof(a1));
+	memset(a1, 0, sizeof(a2));
+	memset(m, 0, sizeof(m));
+
+	switch (addr1->sa_family) {
+#ifdef AF_INET
+	case AF_INET:
+		in_addr1 = (struct sockaddr_in *)(addr1);
+		in_addr2 = (struct sockaddr_in *)(addr2);
+		in_addrm = (struct sockaddr_in *)(mask);
+		len = sizeof(in_addr1->sin_addr.s_addr);
+		memcpy(a1, (u_char *)&(in_addr1->sin_addr.s_addr),
+		    sizeof(in_addr1->sin_addr.s_addr));
+		memcpy(a2, (u_char *)&(in_addr2->sin_addr.s_addr),
+		    sizeof(in_addr2->sin_addr.s_addr));
+		memcpy(m, (u_char *)&(in_addrm->sin_addr.s_addr),
+		    sizeof(in_addrm->sin_addr.s_addr));
+		samescope = 1;
+		break;
+#endif
+#ifdef AF_INET6
+	case AF_INET6:
+		in6_addr1 = (struct sockaddr_in6 *)(addr1);
+		in6_addr2 = (struct sockaddr_in6 *)(addr2);
+		in6_addrm = (struct sockaddr_in6 *)(mask);
+		len = sizeof(in6_addr1->sin6_addr.s6_addr);
+		memcpy(a1, (u_char *)in6_addr1->sin6_addr.s6_addr,
+		    sizeof(in6_addr1->sin6_addr.s6_addr));
+		memcpy(a2, (u_char *)in6_addr2->sin6_addr.s6_addr,
+		    sizeof(in6_addr2->sin6_addr.s6_addr));
+		memcpy(m, (u_char *)in6_addrm->sin6_addr.s6_addr,
+		    sizeof(in6_addrm->sin6_addr.s6_addr));
+		samescope = (in6_addr1->sin6_scope_id ==
+		    in6_addr2->sin6_scope_id);
+		break;
+#endif
+	default:
+		return (1);
+	}
+	for (i=0; i < len; i++) {
+		a1[i] &= m[i];
+		a2[i] &= m[i];
+	}
+	if (debug) {
+		yp_error("compare_subnet(): addr1");
+		yp_debug_sa(addr1);
+		yp_error("compare_subnet(): addr2");
+		yp_debug_sa(addr2);
+		yp_error("compare_subnet(): mask");
+		yp_debug_sa(mask);
+	}
+	if (!samescope)
+		return (1);
+	return (memcmp(a1, a2, len));
 }
 
 /*
@@ -211,15 +550,21 @@ int
 yp_access(const char *map, const struct svc_req *rqstp)
 #endif
 {
-	struct sockaddr_in *rqhost;
 	int status_securenets = 0;
+	int error;
 #ifdef TCP_WRAPPER
 	int status_tcpwrap;
 #endif
-	static unsigned long oldaddr = 0;
-	struct securenet *tmp;
+	static struct sockaddr oldaddr;
+	struct securenet *snp;
+	struct sockaddr *sap;
+	struct netbuf *rqhost;
 	const char *yp_procedure = NULL;
 	char procbuf[50];
+	char host[NI_MAXHOST];
+	char serv[NI_MAXSERV];
+
+	memset(&oldaddr, 0, sizeof(oldaddr));
 
 	if (rqstp->rq_prog != YPPASSWDPROG && rqstp->rq_prog != YPPROG) {
 		snprintf(procbuf, sizeof(procbuf), "#%lu/#%lu",
@@ -232,12 +577,18 @@ yp_access(const char *map, const struct 
 		yp_procs[rqstp->rq_proc + (12 * (rqstp->rq_vers - 1))];
 	}
 
-	rqhost = svc_getcaller(rqstp->rq_xprt);
-
+	rqhost = svc_getrpccaller(rqstp->rq_xprt);
+	sap = (struct sockaddr *)(rqhost->buf);
+	error = getnameinfo(sap, sap->sa_len,
+		    host, sizeof(host), serv, sizeof(serv),
+		    NI_NUMERICHOST | NI_NUMERICSERV);
+	if (error) {
+		yp_error("yp_access: getnameinfo(): %s", gai_strerror(error));
+		return (1);
+	}
 	if (debug) {
-		yp_error("procedure %s called from %s:%d", yp_procedure,
-			inet_ntoa(rqhost->sin_addr),
-			ntohs(rqhost->sin_port));
+		yp_error("procedure %s called from %s:%s", yp_procedure,
+		    host, serv);
 		if (map != NULL)
 			yp_error("client is referencing map \"%s\".", map);
 	}
@@ -245,11 +596,10 @@ yp_access(const char *map, const struct 
 	/* Check the map name if one was supplied. */
 	if (map != NULL) {
 		if (strchr(map, '/')) {
-			yp_error("embedded slash in map name \"%s\" -- \
-possible spoof attempt from %s:%d",
-				map, inet_ntoa(rqhost->sin_addr),
-				ntohs(rqhost->sin_port));
-			return(1);
+			yp_error("embedded slash in map name \"%s\" "
+			    "-- possible spoof attempt from %s:%s",
+			    map, host, serv);
+			return (1);
 		}
 #ifdef DB_CACHE
 		if ((yp_testflag((char *)map, (char *)domain, YP_SECURE) ||
@@ -260,27 +610,30 @@ possible spoof attempt from %s:%d",
 		     rqstp->rq_proc == YPPROC_XFR) ||
 		    (rqstp->rq_prog == YPXFRD_FREEBSD_PROG &&
 		     rqstp->rq_proc == YPXFRD_GETMAP)) &&
-		     ntohs(rqhost->sin_port) >= IPPORT_RESERVED) {
-			yp_error("access to %s denied -- client %s:%d \
-not privileged", map, inet_ntoa(rqhost->sin_addr), ntohs(rqhost->sin_port));
-			return(1);
+		     atoi(serv) >= IPPORT_RESERVED) {
+			yp_error("access to %s denied -- client %s:%s"
+			    " not privileged", map, host, serv);
+			return (1);
 		}
 	}
 
 #ifdef TCP_WRAPPER
-	status_tcpwrap = hosts_ctl("ypserv", STRING_UNKNOWN,
-			   inet_ntoa(rqhost->sin_addr), "");
+	status_tcpwrap = hosts_ctl("ypserv", STRING_UNKNOWN, host, "");
 #endif
-	tmp = securenets;
-	while (tmp) {
-		if (((rqhost->sin_addr.s_addr & ~tmp->mask.s_addr)
-		    | tmp->net.s_addr) == rqhost->sin_addr.s_addr) {
+	if (debug)
+		yp_error("yp_access(): compare start");
+	SLIST_FOREACH (snp, &securenets, sn_next) {
+		if (compare_subnet(sap,
+		    (struct sockaddr *)&(snp->sn_addr),
+		    (struct sockaddr *)&(snp->sn_mask)) == 0) {
 			status_securenets = 1;
+			if (debug)
+				yp_error("yp_access(): compare success!");
 			break;
 		}
-		tmp = tmp->next;
 	}
-
+	if (debug)
+		yp_error("yp_access(): compare end");
 #ifdef TCP_WRAPPER
 	if (status_securenets == 0 || status_tcpwrap == 0) {
 #else
@@ -296,16 +649,14 @@ not privileged", map, inet_ntoa(rqhost->
 	 *
 	 * In either case deny access.
 	 */
-		if (rqhost->sin_addr.s_addr != oldaddr) {
-			yp_error("connect from %s:%d to procedure %s refused",
-					inet_ntoa(rqhost->sin_addr),
-					ntohs(rqhost->sin_port),
-					yp_procedure);
-			oldaddr = rqhost->sin_addr.s_addr;
+		if (memcmp(sap, &oldaddr, sizeof(oldaddr))) {
+			yp_error("connect from %s:%s to procedure %s refused",
+			     host, serv, yp_procedure);
+			memcpy(&oldaddr, sap, sizeof(oldaddr));
 		}
-		return(1);
+		return (1);
 	}
-	return(0);
+	return (0);
 
 }
 
@@ -318,13 +669,12 @@ yp_validdomain(const char *domain)
 	if (domain == NULL || strstr(domain, "binding") ||
 	    !strcmp(domain, ".") || !strcmp(domain, "..") ||
 	    strchr(domain, '/') || strlen(domain) > YPMAXDOMAIN)
-		return(1);
+		return (1);
 
 	snprintf(dompath, sizeof(dompath), "%s/%s", yp_dir, domain);
 
 	if (stat(dompath, &statbuf) < 0 || !S_ISDIR(statbuf.st_mode))
-		return(1);
-
+		return (1);
 
-	return(0);
+	return (0);
 }

Added: user/hrs/ipv6/usr.sbin/ypserv/yp_access_inet.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ user/hrs/ipv6/usr.sbin/ypserv/yp_access_inet.c	Sun May 29 12:15:49 2011	(r222448)
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2010-2011 Hiroki Sato.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "yp_extern.h"
+
+int
+yp_mask2prefixlen_in(const struct sockaddr *sap, int *prefixlen)
+{
+        int x, y = 0;
+	const u_char *p;
+	const struct in_addr *addr;
+	const struct sockaddr_in *sainp;
+
+	sainp = (const struct sockaddr_in *)sap;
+	addr = &(sainp->sin_addr);
+	p = (const u_char *)&addr->s_addr;
+        for (x = 0; x < (int)sizeof(addr->s_addr); x++)
+                if (p[x] != 0xff)
+                        break;
+        if (x < (int)sizeof(addr->s_addr))
+                for (y = 0; y < 8; y++)
+                        if ((p[x] & (0x80 >> y)) == 0)
+                                break;
+	*prefixlen = x * 8 + y;
+        return (0);
+}
+
+int
+yp_prefixlen2mask_in(struct sockaddr *sap, const int *prefixlen)
+{
+        int i;
+	int len;
+	u_char *p;
+	struct in_addr *addr;
+	struct sockaddr_in *sainp;
+
+	len = *prefixlen;
+	if (0 > len || len > 32)
+		return (-1);
+
+	sainp = (struct sockaddr_in *)sap;
+	memset(&sainp->sin_addr, 0, sizeof(sainp->sin_addr));
+	addr = &(sainp->sin_addr);
+	p = (u_char *)&addr->s_addr;
+        for (i = 0; i < len / 8; i++)
+                p[i] = 0xff;
+        if (len % 8)
+                p[i] = (0xff00 >> (len % 8)) & 0xff;
+	return (0);
+}
+
+struct sockaddr *
+yp_mask_in(const struct sockaddr *addr, const struct sockaddr *mask)
+{
+	int i;
+	const u_char *p, *q;
+	u_char *r;
+	const struct sockaddr_in *in_addr;
+	const struct sockaddr_in *in_mask;
+	struct sockaddr_in *in_res;
+
+	in_addr = (const struct sockaddr_in *)addr;
+	in_mask = (const struct sockaddr_in *)mask;
+
+	if ((in_res = malloc(sizeof(*in_res))) == NULL)
+		return NULL;
+	memcpy(in_res, in_addr, sizeof(*in_res));
+	p = (const u_char *)&(in_addr->sin_addr.s_addr);
+	q = (const u_char *)&(in_mask->sin_addr.s_addr);
+	r = (u_char *)&(in_res->sin_addr.s_addr);
+	for (i = 0; i < (int)sizeof(in_addr->sin_addr.s_addr); i++)
+		r[i] = p[i] & q[i];
+
+	return ((struct sockaddr *)in_res);
+}
+
+int 
+yp_compare_subnet_in(const struct sockaddr *a1, const struct sockaddr *a2)
+{
+        const struct sockaddr_in *in_a1 = (const struct sockaddr_in *)a1;
+        const struct sockaddr_in *in_a2 = (const struct sockaddr_in *)a2;
+
+	if (debug) {
+		yp_error("yp_subnet_cmp_in(): a1");
+		yp_debug_sa(a1);
+		yp_error("yp_subnet_cmp_in(): a2");
+		yp_debug_sa(a2);
+        }
+        return (memcmp((const u_char *)&(in_a1->sin_addr.s_addr),
+                    (const u_char *)&(in_a2->sin_addr.s_addr),
+                    sizeof(in_a1->sin_addr.s_addr)));
+}

Added: user/hrs/ipv6/usr.sbin/ypserv/yp_access_inet6.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ user/hrs/ipv6/usr.sbin/ypserv/yp_access_inet6.c	Sun May 29 12:15:49 2011	(r222448)
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2010-2011 Hiroki Sato.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "yp_extern.h"
+
+int
+yp_mask2prefixlen_in6(const struct sockaddr *sap, int *prefixlen)
+{
+        int x, y = 0;
+        const u_char *p;
+	const struct in6_addr *addr;
+	const struct sockaddr_in6 *sain6p;
+
+	sain6p = (const struct sockaddr_in6 *)sap;
+	addr = &(sain6p->sin6_addr);
+        for (x = 0; x < (int)sizeof(addr->s6_addr); x++)
+		if (addr->s6_addr[x] != 0xff)
+			break;
+        if (x < (int)sizeof(addr->s6_addr))
+                for (y = 0; y < 8; y++)
+                        if ((addr->s6_addr[x] & (0x80 >> y)) == 0)
+                                break;
+        if (x < (int)sizeof(addr->s6_addr)) {
+                if (y != 0 && (addr->s6_addr[x] & (0x00ff >> y)) != 0)
+                        return (-1);
+		p = (const u_char *)&addr->s6_addr[x + 1];
+                for (; p < addr->s6_addr + sizeof(addr->s6_addr); p++)
+                        if (*p != 0)
+                                return (-1);
+        }
+	*prefixlen = x * 8 + y;
+        return (0);
+}
+
+int
+yp_prefixlen2mask_in6(struct sockaddr *sap, const int *prefixlen)
+{
+	int i;
+	int len;
+	int bytelen, bitlen;
+	u_char maskarray[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
+	struct in6_addr *addr;
+	struct sockaddr_in6 *sain6p;
+
+	len = *prefixlen;
+	if (0 > len || len > 128)
+		return (-1);
+
+	sain6p = (struct sockaddr_in6 *)sap;
+	memset(&sain6p->sin6_addr, 0, sizeof(sain6p->sin6_addr));
+	addr = &(sain6p->sin6_addr);
+	bytelen = len / 8;
+	bitlen = len % 8;
+	for (i = 0; i < bytelen; i++)
+		addr->s6_addr[i] = 0xff;
+	if (bitlen)
+		addr->s6_addr[bytelen] = maskarray[bitlen - 1];
+	return (0);
+}
+
+struct sockaddr *
+yp_mask_in6(const struct sockaddr *addr, const struct sockaddr *mask)
+{
+	int i;
+	const u_char *p, *q;
+	u_char *r;
+	const struct sockaddr_in6 *in6_addr;
+	const struct sockaddr_in6 *in6_mask;
+	struct sockaddr_in6 *in6_res;
+
+	in6_addr = (const struct sockaddr_in6 *)addr;
+	in6_mask = (const struct sockaddr_in6 *)mask;
+
+	if ((in6_res = malloc(sizeof(*in6_res))) == NULL)
+		return NULL;
+	memcpy(in6_res, in6_addr, sizeof(*in6_res));
+	p = (const u_char *)&(in6_addr->sin6_addr.s6_addr);
+	q = (const u_char *)&(in6_mask->sin6_addr.s6_addr);
+	r = (u_char *)&(in6_res->sin6_addr.s6_addr);
+	for (i = 0; i < (int)sizeof(in6_addr->sin6_addr.s6_addr); i++)
+		r[i] = p[i] & q[i];
+        
+	return ((struct sockaddr *)in6_res);
+}
+
+int
+yp_compare_subnet_in6(const struct sockaddr *a1, const struct sockaddr *a2)
+{
+	const struct sockaddr_in6 *in6_a1 = (const struct sockaddr_in6 *)a1;
+	const struct sockaddr_in6 *in6_a2 = (const struct sockaddr_in6 *)a2;
+
+	if (debug) {
+		yp_error("yp_subnet_cmp_in6(): a1");
+		yp_debug_sa(a1);
+		yp_error("yp_subnet_cmp_in6(): a2");
+		yp_debug_sa(a2);
+		yp_error("yp_subnet_cmp_in6(): scope: %d - %d",
+		    in6_a1->sin6_scope_id, in6_a2->sin6_scope_id);
+        }
+
+	if (in6_a1->sin6_scope_id != in6_a2->sin6_scope_id)
+		return (-1);
+
+	return (memcmp(in6_a1->sin6_addr.s6_addr,
+		    in6_a2->sin6_addr.s6_addr,
+		    sizeof(in6_a1->sin6_addr.s6_addr)));
+}

Modified: user/hrs/ipv6/usr.sbin/ypserv/yp_extern.h
==============================================================================
--- user/hrs/ipv6/usr.sbin/ypserv/yp_extern.h	Sun May 29 11:10:56 2011	(r222447)
+++ user/hrs/ipv6/usr.sbin/ypserv/yp_extern.h	Sun May 29 12:15:49 2011	(r222448)
@@ -32,15 +32,16 @@
  * $FreeBSD$
  */
 
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <rpc/rpc.h>
+#include <rpcsvc/yp.h>
 #include <db.h>
 #include <limits.h>
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
-#include <sys/cdefs.h>
-#include <sys/types.h>
-#include <rpc/rpc.h>
-#include <rpcsvc/yp.h>
 
 #ifndef _PATH_YP
 #define _PATH_YP "/var/yp/"
@@ -57,6 +58,8 @@
 #define YP_SECURE 0x1
 #define YP_INTERDOMAIN 0x2
 
+#define SECURENETS_FNAME	"securenets"
+
 /*

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201105291215.p4TCFnt0029384>