Index: bind8/src/CHANGES
diff -c bind8/src/CHANGES:8.798.2.71 bind8/src/CHANGES:8.798.2.71.2.3
*** bind8/src/CHANGES:8.798.2.71	Thu Sep 27 23:41:55 2001
--- bind8/src/CHANGES	Wed Jun 26 21:19:29 2002
***************
*** 1,3 ****
--- 1,10 ----
+ 
+ 	--- 8.2.6-REL released --- (Wed Jun 26 21:15:43 PDT 2002)
+ 
+ 1301.	[func]		log attempts to exploit #1300.
+ 
+ 1300.   [bug]           Remote buffer overrun.
+ 
  	--- 8.2.5-REL released --- (Thu Sep 27 23:41:08 PDT 2001)
  
  1272.	[bug]		"rndc trace 0" should behave like "rndc notrace".
Index: bind8/src/README
diff -c bind8/src/README:8.44.2.2 bind8/src/README:8.44.2.2.2.1
*** bind8/src/README:8.44.2.2	Sun Jun 17 23:22:03 2001
--- bind8/src/README	Wed Jun 26 21:19:30 2002
***************
*** 10,15 ****
--- 10,19 ----
  Note that BIND 8 is in "end-of-life", having been replaced by BIND 9.  See
  http://www.isc.org/ for more details.
  
+ BIND 8.2.6 Highlights
+ 	Security Fix in libbind.  All applications linked against libbind
+ 	need to relinked.
+ 
  BIND 8.2.5 Highlights
  	Bug Fixes.
  
Index: bind8/src/Version
diff -c bind8/src/Version:8.65.2.6 bind8/src/Version:8.65.2.6.2.1
*** bind8/src/Version:8.65.2.6	Tue Sep  4 20:13:34 2001
--- bind8/src/Version	Wed Jun 26 21:19:32 2002
***************
*** 1 ****
! 8.2.5-REL
--- 1 ----
! 8.2.6-REL
Index: bind8/src/bin/named/ns_resp.c
diff -c bind8/src/bin/named/ns_resp.c:8.152.2.4 bind8/src/bin/named/ns_resp.c:8.152.2.4.2.1
*** bind8/src/bin/named/ns_resp.c:8.152.2.4	Mon Aug 20 00:18:09 2001
--- bind8/src/bin/named/ns_resp.c	Wed Jun 26 21:15:00 2002
***************
*** 306,311 ****
--- 306,312 ----
  	u_char sig[TSIG_SIG_SIZE];
  	time_t tsig_time;
  	DST_KEY *key;
+ 	int expect_cname;
  
  	nameserIncr(from.sin_addr, nssRcvdR);
  	nsp[0] = NULL;
***************
*** 916,921 ****
--- 917,923 ----
  	} else
  		flushset = NULL;
  
+ 	expect_cname = 1;
  	for (i = 0; i < count; i++) {
  		struct databuf *dp;
  		int type;
***************
*** 947,952 ****
--- 949,967 ----
  		type = dp->d_type;
  		if (i < ancount) {
  			/* Answer section. */
+ 			/*
+ 			 * Check for attempts to overflow the buffer in
+ 			 * getnameanswer.
+ 			 */
+ 			if (type == ns_t_cname && !expect_cname) {
+ 				ns_warning(ns_log_security,
+ 			     "late CNAME in answer section for %s %s from %s",
+ 					   *qname ? qname : ".", p_type(qtype),
+ 					   sin_ntoa(from));
+ 					   
+ 			} else if (type != ns_t_cname && type != ns_t_dname &&
+ 				   type != ns_t_sig)
+ 				expect_cname = 0;
  			if (externalcname || ns_samename(name, aname) != 1) {
  				if (!externalcname)
  					ns_info(ns_log_resp_checks,
Index: bind8/src/lib/irs/dns_ho.c
diff -c bind8/src/lib/irs/dns_ho.c:1.28.2.1 bind8/src/lib/irs/dns_ho.c:1.28.2.1.2.2
*** bind8/src/lib/irs/dns_ho.c:1.28.2.1	Sun Jul  1 18:27:16 2001
--- bind8/src/lib/irs/dns_ho.c	Wed Jun 26 21:15:02 2002
***************
*** 74,79 ****
--- 74,80 ----
  #include <resolv.h>
  #include <stdio.h>
  #include <string.h>
+ #include <syslog.h>
  
  #include <isc/memcluster.h>
  #include <irs.h>
***************
*** 139,145 ****
  				   void (*free_res)(void *));
  
  static void		map_v4v6_hostent(struct hostent *hp, char **bp,
! 					 int *len);
  static void		addrsort(res_state, char **, int);
  static struct hostent *	gethostans(struct irs_ho *this,
  				   const u_char *ansbuf, int anslen,
--- 140,146 ----
  				   void (*free_res)(void *));
  
  static void		map_v4v6_hostent(struct hostent *hp, char **bp,
! 					 char *ep);
  static void		addrsort(res_state, char **, int);
  static struct hostent *	gethostans(struct irs_ho *this,
  				   const u_char *ansbuf, int anslen,
***************
*** 385,397 ****
  	   int af, int size)
  {
  	struct pvt *pvt = (struct pvt *)this->private;
! 	int type, class, buflen, ancount, qdcount, n, haveanswer, had_error;
  	int (*name_ok)(const char *);
  	const HEADER *hp;
  	const u_char *eom;
  	const u_char *cp;
  	const char *tname, **tap;
! 	char *bp, **ap, **hap;
  	char tbuf[MAXDNAME+1];
  
  	tname = qname;
--- 386,398 ----
  	   int af, int size)
  {
  	struct pvt *pvt = (struct pvt *)this->private;
! 	int type, class, ancount, qdcount, n, haveanswer, had_error;
  	int (*name_ok)(const char *);
  	const HEADER *hp;
  	const u_char *eom;
  	const u_char *cp;
  	const char *tname, **tap;
! 	char *bp, *ep, **ap, **hap;
  	char tbuf[MAXDNAME+1];
  
  	tname = qname;
***************
*** 423,435 ****
  	ancount = ntohs(hp->ancount);
  	qdcount = ntohs(hp->qdcount);
  	bp = pvt->hostbuf;
! 	buflen = sizeof pvt->hostbuf;
  	cp = ansbuf + HFIXEDSZ;
  	if (qdcount != 1) {
  		RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
  		return (NULL);
  	}
! 	n = dn_expand(ansbuf, eom, cp, bp, buflen);
  	if (n < 0 || !maybe_ok(pvt->res, bp, name_ok)) {
  		RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
  		return (NULL);
--- 424,436 ----
  	ancount = ntohs(hp->ancount);
  	qdcount = ntohs(hp->qdcount);
  	bp = pvt->hostbuf;
! 	ep = pvt->hostbuf + sizeof(pvt->hostbuf);
  	cp = ansbuf + HFIXEDSZ;
  	if (qdcount != 1) {
  		RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
  		return (NULL);
  	}
! 	n = dn_expand(ansbuf, eom, cp, bp, ep - bp);
  	if (n < 0 || !maybe_ok(pvt->res, bp, name_ok)) {
  		RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
  		return (NULL);
***************
*** 451,457 ****
  		}
  		pvt->host.h_name = bp;
  		bp += n;
- 		buflen -= n;
  		/* The qname can be abbreviated, but h_name is now absolute. */
  		qname = pvt->host.h_name;
  	}
--- 452,457 ----
***************
*** 464,470 ****
  	haveanswer = 0;
  	had_error = 0;
  	while (ancount-- > 0 && cp < eom && !had_error) {
! 		n = dn_expand(ansbuf, eom, cp, bp, buflen);
  		if (n < 0 || !maybe_ok(pvt->res, bp, name_ok)) {
  			had_error++;
  			continue;
--- 464,470 ----
  	haveanswer = 0;
  	had_error = 0;
  	while (ancount-- > 0 && cp < eom && !had_error) {
! 		n = dn_expand(ansbuf, eom, cp, bp, ep - bp);
  		if (n < 0 || !maybe_ok(pvt->res, bp, name_ok)) {
  			had_error++;
  			continue;
***************
*** 483,488 ****
--- 483,497 ----
  			continue;
  		}
  		if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
+ 			if (haveanswer) {
+ 				int level = LOG_CRIT;
+ #ifdef LOG_SECURITY
+ 				level |= LOG_SECURITY;
+ #endif
+ 				syslog(level,
+  "gethostans: possible attempt to exploit buffer overflow while looking up %s",
+ 				       *qname ? qname : ".");
+ 			}
  			if (ap >= &pvt->host_aliases[MAXALIASES-1])
  				continue;
  			n = dn_expand(ansbuf, eom, cp, tbuf, sizeof tbuf);
***************
*** 495,511 ****
  			*ap++ = bp;
  			n = strlen(bp) + 1;	/* for the \0 */
  			bp += n;
- 			buflen -= n;
  			/* Get canonical name. */
  			n = strlen(tbuf) + 1;	/* for the \0 */
! 			if (n > buflen || n > MAXHOSTNAMELEN) {
  				had_error++;
  				continue;
  			}
  			strcpy(bp, tbuf);
  			pvt->host.h_name = bp;
  			bp += n;
- 			buflen -= n;
  			continue;
  		}
  		if (qtype == T_PTR && type == T_CNAME) {
--- 504,518 ----
  			*ap++ = bp;
  			n = strlen(bp) + 1;	/* for the \0 */
  			bp += n;
  			/* Get canonical name. */
  			n = strlen(tbuf) + 1;	/* for the \0 */
! 			if (n > (ep - bp) || n > MAXHOSTNAMELEN) {
  				had_error++;
  				continue;
  			}
  			strcpy(bp, tbuf);
  			pvt->host.h_name = bp;
  			bp += n;
  			continue;
  		}
  		if (qtype == T_PTR && type == T_CNAME) {
***************
*** 517,530 ****
  			cp += n;
  			/* Get canonical name. */
  			n = strlen(tbuf) + 1;	/* for the \0 */
! 			if (n > buflen) {
  				had_error++;
  				continue;
  			}
  			strcpy(bp, tbuf);
  			tname = bp;
  			bp += n;
- 			buflen -= n;
  			continue;
  		}
  		if (type != qtype) {
--- 524,536 ----
  			cp += n;
  			/* Get canonical name. */
  			n = strlen(tbuf) + 1;	/* for the \0 */
! 			if (n > (ep - bp)) {
  				had_error++;
  				continue;
  			}
  			strcpy(bp, tbuf);
  			tname = bp;
  			bp += n;
  			continue;
  		}
  		if (type != qtype) {
***************
*** 537,543 ****
  				cp += n;
  				continue;
  			}
! 			n = dn_expand(ansbuf, eom, cp, bp, buflen);
  			if (n < 0 || !maybe_hnok(pvt->res, bp) ||
  			    n >= MAXHOSTNAMELEN) {
  				had_error++;
--- 543,549 ----
  				cp += n;
  				continue;
  			}
! 			n = dn_expand(ansbuf, eom, cp, bp, ep - bp);
  			if (n < 0 || !maybe_hnok(pvt->res, bp) ||
  			    n >= MAXHOSTNAMELEN) {
  				had_error++;
***************
*** 553,559 ****
  			if (n != -1) {
  				n = strlen(bp) + 1;	/* for the \0 */
  				bp += n;
- 				buflen -= n;
  			}
  			break;
  		case T_A:
--- 559,564 ----
***************
*** 577,583 ****
  				}
  				pvt->host.h_name = bp;
  				bp += nn;
- 				buflen -= nn;
  			}
  			/* Ensure alignment. */
  			bp += sizeof(align) - ((u_long)bp % sizeof(align));
--- 582,587 ----
***************
*** 619,633 ****
  			addrsort(pvt->res, pvt->h_addr_ptrs, haveanswer);
  		if (!pvt->host.h_name) {
  			n = strlen(qname) + 1;	/* for the \0 */
! 			if (n > buflen || n >= MAXHOSTNAMELEN)
  				goto no_recovery;
  			strcpy(bp, qname);
  			pvt->host.h_name = bp;
  			bp += n;
- 			buflen -= n;
  		}
  		if (pvt->res->options & RES_USE_INET6)
! 			map_v4v6_hostent(&pvt->host, &bp, &buflen);
  		RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS);
  		return (&pvt->host);
  	}
--- 623,636 ----
  			addrsort(pvt->res, pvt->h_addr_ptrs, haveanswer);
  		if (!pvt->host.h_name) {
  			n = strlen(qname) + 1;	/* for the \0 */
! 			if (n > (ep - bp) || n >= MAXHOSTNAMELEN)
  				goto no_recovery;
  			strcpy(bp, qname);
  			pvt->host.h_name = bp;
  			bp += n;
  		}
  		if (pvt->res->options & RES_USE_INET6)
! 			map_v4v6_hostent(&pvt->host, &bp, ep);
  		RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS);
  		return (&pvt->host);
  	}
***************
*** 637,643 ****
  }
  
  static void
! map_v4v6_hostent(struct hostent *hp, char **bpp, int *lenp) {
  	char **ap;
  
  	if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
--- 640,646 ----
  }
  
  static void
! map_v4v6_hostent(struct hostent *hp, char **bpp, char *ep) {
  	char **ap;
  
  	if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
***************
*** 647,663 ****
  	for (ap = hp->h_addr_list; *ap; ap++) {
  		int i = sizeof(align) - ((u_long)*bpp % sizeof(align));
  
! 		if (*lenp < (i + IN6ADDRSZ)) {
  			/* Out of memory.  Truncate address list here. */
  			*ap = NULL;
  			return;
  		}
  		*bpp += i;
- 		*lenp -= i;
  		map_v4v6_address(*ap, *bpp);
  		*ap = *bpp;
  		*bpp += IN6ADDRSZ;
- 		*lenp -= IN6ADDRSZ;
  	}
  }
  
--- 650,664 ----
  	for (ap = hp->h_addr_list; *ap; ap++) {
  		int i = sizeof(align) - ((u_long)*bpp % sizeof(align));
  
! 		if ((ep - *bpp) < (i + IN6ADDRSZ)) {
  			/* Out of memory.  Truncate address list here. */
  			*ap = NULL;
  			return;
  		}
  		*bpp += i;
  		map_v4v6_address(*ap, *bpp);
  		*ap = *bpp;
  		*bpp += IN6ADDRSZ;
  	}
  }
  
Index: bind8/src/lib/irs/dns_nw.c
diff -c bind8/src/lib/irs/dns_nw.c:1.19 bind8/src/lib/irs/dns_nw.c:1.19.6.1
*** bind8/src/lib/irs/dns_nw.c:1.19	Fri Oct 15 12:49:10 1999
--- bind8/src/lib/irs/dns_nw.c	Wed Jun 26 19:45:45 2002
***************
*** 277,284 ****
  	      int af, const char *name, const u_char *addr, int addrlen)
  {
  	struct pvt *pvt = (struct pvt *)this->private;
! 	int type, class, buflen, ancount, qdcount, haveanswer;
! 	char *bp, **ap;
  	u_char *cp, *eom;
  	HEADER *hp;
  
--- 277,284 ----
  	      int af, const char *name, const u_char *addr, int addrlen)
  {
  	struct pvt *pvt = (struct pvt *)this->private;
! 	int type, class, ancount, qdcount, haveanswer;
! 	char *bp, *ep, **ap;
  	u_char *cp, *eom;
  	HEADER *hp;
  
***************
*** 310,316 ****
  
  	/* Prepare a return structure. */
  	bp = pvt->buf;
! 	buflen = sizeof pvt->buf;
  	pvt->net.n_name = NULL;
  	pvt->net.n_aliases = pvt->ali;
  	pvt->net.n_addrtype = af;
--- 310,316 ----
  
  	/* Prepare a return structure. */
  	bp = pvt->buf;
! 	ep = pvt->buf + sizeof(pvt->buf);
  	pvt->net.n_name = NULL;
  	pvt->net.n_aliases = pvt->ali;
  	pvt->net.n_addrtype = af;
***************
*** 323,342 ****
  		if (name != NULL) {
  			int n = strlen(name) + 1;
  
! 			if (n > buflen) {
  				RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
  				return (NULL);
  			}
  			pvt->net.n_name = strcpy(bp, name);
  			bp += n;
- 			buflen -= n;
  		}
  		break;
  	case by_addr:
  		if (addr != NULL && addrlen != 0) {
  			int n = addrlen / 8 + ((addrlen % 8) != 0);
  
! 			if (INADDRSZ > buflen) {
  				RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
  				return (NULL);
  			}
--- 323,341 ----
  		if (name != NULL) {
  			int n = strlen(name) + 1;
  
! 			if (n > (ep - bp)) {
  				RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
  				return (NULL);
  			}
  			pvt->net.n_name = strcpy(bp, name);
  			bp += n;
  		}
  		break;
  	case by_addr:
  		if (addr != NULL && addrlen != 0) {
  			int n = addrlen / 8 + ((addrlen % 8) != 0);
  
! 			if (INADDRSZ > (ep - bp)) {
  				RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
  				return (NULL);
  			}
***************
*** 344,350 ****
  			memcpy(bp, addr, n);
  			pvt->net.n_addr = bp;
  			bp += INADDRSZ;
- 			buflen -= INADDRSZ;
  		}
  		break;
  	default:
--- 343,348 ----
***************
*** 355,361 ****
  	ap = pvt->ali;
  	haveanswer = 0;
  	while (--ancount >= 0 && cp < eom) {
! 		int n = dn_expand(ansbuf, eom, cp, bp, buflen);
  
  		cp += n;		/* Owner */
  		if (n < 0 || !maybe_dnok(pvt->res, bp) ||
--- 353,359 ----
  	ap = pvt->ali;
  	haveanswer = 0;
  	while (--ancount >= 0 && cp < eom) {
! 		int n = dn_expand(ansbuf, eom, cp, bp, ep - bp);
  
  		cp += n;		/* Owner */
  		if (n < 0 || !maybe_dnok(pvt->res, bp) ||
***************
*** 370,376 ****
  		if (class == C_IN && type == T_PTR) {
  			int nn;
  
! 			nn = dn_expand(ansbuf, eom, cp, bp, buflen);
  			if (nn < 0 || !maybe_hnok(pvt->res, bp) || nn != n) {
  				RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
  				return (NULL);
--- 368,374 ----
  		if (class == C_IN && type == T_PTR) {
  			int nn;
  
! 			nn = dn_expand(ansbuf, eom, cp, bp, ep - bp);
  			if (nn < 0 || !maybe_hnok(pvt->res, bp) || nn != n) {
  				RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
  				return (NULL);
***************
*** 386,392 ****
  					*ap++ = bp;
  				nn = strlen(bp) + 1;
  				bp += nn;
- 				buflen -= nn;
  				haveanswer++;
  				break;
  			    }
--- 384,389 ----
***************
*** 397,403 ****
  				    sscanf(bp, "%u.%u.%u.%u.in-addr.arpa",
  					   &b1, &b2, &b3, &b4) != 4)
  					break;
! 				if (buflen < INADDRSZ) {
  					RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
  					return (NULL);
  				}
--- 394,400 ----
  				    sscanf(bp, "%u.%u.%u.%u.in-addr.arpa",
  					   &b1, &b2, &b3, &b4) != 4)
  					break;
! 				if ((ep - bp) < INADDRSZ) {
  					RES_SET_H_ERRNO(pvt->res, NO_RECOVERY);
  					return (NULL);
  				}
***************
*** 406,412 ****
  				*bp++ = b3;
  				*bp++ = b2;
  				*bp++ = b1;
- 				buflen -= INADDRSZ;
  				pvt->net.n_length = INADDRSZ * 8;
  				haveanswer++;
  			    }
--- 403,408 ----
