changeset 10544:b484cf5fe72f

6856084 Sparks DNS backend should return canonical name before aliases
author Stacey Marshall <Stacey.Marshall@Sun.COM>
date Fri, 24 Jul 2009 15:08:40 +0100
parents 3e3d2b81ed8e
children a008c2e346a1
files usr/src/lib/nsswitch/dns/common/dns_common.c
diffstat 1 files changed, 34 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/lib/nsswitch/dns/common/dns_common.c	Tue Sep 15 03:36:15 2009 -0700
+++ b/usr/src/lib/nsswitch/dns/common/dns_common.c	Fri Jul 24 15:08:40 2009 +0100
@@ -19,12 +19,10 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  *	dns_common.c
  */
@@ -299,7 +297,7 @@
  * INPUT:
  *  aliases_ptr: space separated list of alias names.
  *  name_ptr: name to look for in aliases_ptr list.
- * RETURNS: NSS_SUCCESS or NSS_ERROR
+ * RETURNS: NSS_SUCCESS or NSS_NOTFOUND
  *  NSS_SUCCESS indicates that the name is listed in the collected aliases.
  */
 static nss_status_t
@@ -332,7 +330,7 @@
 		/* Step over separator character. */
 		while (*aliases_ptr == ' ') aliases_ptr++;
 	}
-	return (NSS_ERROR);
+	return (NSS_NOTFOUND);
 }
 
 /*
@@ -397,7 +395,7 @@
 	/* misc variables */
 	int		af;
 	char		*ap, *apc;
-	int		hlen = 0, alen, iplen, len;
+	int		hlen = 0, alen, iplen, len, isans;
 
 	statp = &stat;
 	(void) memset(statp, '\0', sizeof (struct __res_state));
@@ -482,8 +480,9 @@
 			 * Check that the expanded name is either the
 			 * name we asked for or a learned alias.
 			 */
-			if (strncasecmp(host, ans, hlen) != 0 && (alen == 0 ||
-			    name_is_alias(aliases, ans) == NSS_ERROR)) {
+			if ((isans = strncasecmp(host, ans, hlen)) != 0 &&
+			    (alen == 0 || name_is_alias(aliases, ans)
+			    == NSS_NOTFOUND)) {
 				__res_ndestroy(statp);
 				return (NSS_ERROR);	/* spoof? */
 			}
@@ -494,7 +493,7 @@
 		cp += INT16SZ;
 		class = ns_get16(cp);			/* class */
 		cp += INT16SZ;
-		nttl = (nssuint_t)ns_get32(cp);	/* ttl in sec */
+		nttl = (nssuint_t)ns_get32(cp);		/* ttl in sec */
 		if (nttl < ttl)
 			ttl = nttl;
 		cp += INT32SZ;
@@ -507,34 +506,42 @@
 		eor = cp + n;
 		if (type == T_CNAME) {
 			/*
-			 * The name we looked up is really an alias
-			 * and the canonical name should be in the
-			 * RDATA.  A canonical name may have several
-			 * aliases but an alias should only have one
-			 * canonical name. However multiple CNAMEs and
-			 * CNAME chains do exist!  So for caching
-			 * purposes maintain the alias as the host
-			 * name, and the CNAME as an alias.
+			 * The name looked up is really an alias and the
+			 * canonical name should be in the RDATA.
+			 * A canonical name may have several aliases but an
+			 * alias should only have one canonical name.
+			 * However multiple CNAMEs and CNAME chains do exist!
+			 *
+			 * Just error out on attempted buffer overflow exploit,
+			 * generic code will syslog.
+			 *
 			 */
 			n = dn_expand(bom, eor, cp, aname, MAXHOSTNAMELEN);
-			if (n > 0) {
-				len = strlen(aname);
-				if (len > 0) {
+			if (n > 0 && (len = strlen(aname)) > 0) {
+				if (isans == 0) { /* host matched ans. */
 					/*
-					 * Just error out if there is an
-					 * attempted buffer overflow exploit
-					 * generic code will do a syslog
+					 * Append host to alias list.
 					 */
-					if (alen + len + 2 > NS_MAXMSG) {
+					if (alen + hlen + 2 > NS_MAXMSG) {
 						__res_ndestroy(statp);
 						return (NSS_ERROR);
 					}
 					*apc++ = ' ';
 					alen++;
-					(void) strlcpy(apc, aname, len + 1);
-					alen += len;
-					apc += len;
+					(void) strlcpy(apc, host,
+					    NS_MAXMSG - alen);
+					alen += hlen;
+					apc += hlen;
 				}
+				/*
+				 * Overwrite host with canonical name.
+				 */
+				if (strlcpy(host, aname, MAXHOSTNAMELEN) >=
+				    MAXHOSTNAMELEN) {
+					__res_ndestroy(statp);
+					return (NSS_ERROR);
+				}
+				hlen = len;
 			}
 			cp += n;
 			continue;