diff options
Diffstat (limited to 'contrib/bind/named/named-xfer.c')
-rw-r--r-- | contrib/bind/named/named-xfer.c | 62 |
1 files changed, 52 insertions, 10 deletions
diff --git a/contrib/bind/named/named-xfer.c b/contrib/bind/named/named-xfer.c index 3b578e2..7ff2e5c 100644 --- a/contrib/bind/named/named-xfer.c +++ b/contrib/bind/named/named-xfer.c @@ -92,7 +92,7 @@ char copyright[] = #if !defined(lint) && !defined(SABER) static char sccsid[] = "@(#)named-xfer.c 4.18 (Berkeley) 3/7/91"; -static char rcsid[] = "$Id: named-xfer.c,v 8.23 1997/06/01 20:34:34 vixie Exp $"; +static char rcsid[] = "$Id: named-xfer.c,v 8.24 1998/04/07 04:59:45 vixie Exp $"; #endif /* not lint */ #include <sys/types.h> @@ -740,6 +740,10 @@ getzone(zp, serial_no, port) goto badsoa; } tmp += n; + if (tmp + 2 * INT16SZ > eom) { + badsoa_msg = "query error"; + goto badsoa; + } GETSHORT(type, tmp); GETSHORT(class, tmp); if (class != curclass || type != T_SOA || @@ -778,6 +782,10 @@ getzone(zp, serial_no, port) GETSHORT(class, cp4); GETLONG(ttl, cp4); GETSHORT(dlen, cp4); + if (cp4 + dlen > eom) { + badsoa_msg = "zinfo dlen too big"; + goto badsoa; + } if (type == T_SOA) break; /* Skip to next record, if any. */ @@ -1155,6 +1163,8 @@ soa_zinfo(zp, cp, eom) register int n; int type, class; u_long ttl; + u_int dlen; + u_char *rdatap; /* Are type, class, and ttl OK? */ if (eom - cp < 3 * INT16SZ + INT32SZ) @@ -1162,7 +1172,8 @@ soa_zinfo(zp, cp, eom) GETSHORT(type, cp); GETSHORT(class, cp); GETLONG(ttl, cp); - cp += INT16SZ; /* dlen */ + GETSHORT(dlen, cp); + rdatap = cp; if (type != T_SOA || class != curclass) return ("zinfo wrong typ/cla/ttl"); /* Skip master name and contact name, we can't validate them. */ @@ -1180,9 +1191,19 @@ soa_zinfo(zp, cp, eom) GETLONG(zp->z_retry, cp); GETLONG(zp->z_expire, cp); GETLONG(zp->z_minimum, cp); + if (cp != rdatap + dlen) + return ("bad soa dlen"); return (NULL); } +#define BOUNDS_CHECK(ptr, count) \ + do { \ + if ((ptr) + (count) > eom) { \ + hp->rcode = FORMERR; \ + return (-1); \ + } \ + } while (0) + /* * Parse the message, determine if it should be printed, and if so, print it * in .db file form. @@ -1202,7 +1223,7 @@ print_output(zp, serial_no, msg, msglen, rrp) int i, j, tab, result, class, type, dlen, n1, n; char data[BUFSIZ]; u_char *cp1, *cp2, *temp_ptr, *eom, *rr_type_ptr; - u_char *cdata; + u_char *cdata, *rdatap; char *origin, *proto, dname[MAXDNAME]; char *ignore = ""; const char *badsoa_msg; @@ -1216,10 +1237,13 @@ print_output(zp, serial_no, msg, msglen, rrp) } cp += n; rr_type_ptr = cp; + BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ); GETSHORT(type, cp); GETSHORT(class, cp); GETLONG(ttl, cp); GETSHORT(dlen, cp); + BOUNDS_CHECK(cp, dlen); + rdatap = cp; origin = strchr(dname, '.'); if (origin == NULL) @@ -1294,10 +1318,7 @@ print_output(zp, serial_no, msg, msglen, rrp) cp += n; cp1 += strlen((char *) cp1) + 1; if (type == T_SOA) { - if ((eom - cp) < (5 * INT32SZ)) { - hp->rcode = FORMERR; - return (-1); - } + BOUNDS_CHECK(cp, 5 * INT32SZ); temp_ptr = cp + 4 * INT32SZ; GETLONG(minimum_ttl, temp_ptr); n = 5 * INT32SZ; @@ -1311,24 +1332,31 @@ print_output(zp, serial_no, msg, msglen, rrp) case T_NAPTR: /* Grab weight and port. */ + BOUNDS_CHECK(cp, INT16SZ*2); bcopy(cp, data, INT16SZ*2); cp1 = (u_char *) (data + INT16SZ*2); cp += INT16SZ*2; /* Flags */ + BOUNDS_CHECK(cp, 1); n = *cp++; + BOUNDS_CHECK(cp, n); *cp1++ = n; bcopy(cp, cp1, n); cp += n; cp1 += n; /* Service */ - n = *cp++; + BOUNDS_CHECK(cp, 1); + n = *cp++; + BOUNDS_CHECK(cp, n); *cp1++ = n; bcopy(cp, cp1, n); cp += n; cp1 += n; /* Regexp */ - n = *cp++; + BOUNDS_CHECK(cp, 1); + n = *cp++; + BOUNDS_CHECK(cp, n); *cp1++ = n; bcopy(cp, cp1, n); cp += n; cp1 += n; @@ -1352,11 +1380,13 @@ print_output(zp, serial_no, msg, msglen, rrp) case T_RT: case T_SRV: /* grab preference */ + BOUNDS_CHECK(cp, INT16SZ); bcopy((char *)cp, data, INT16SZ); cp1 = (u_char *)data + INT16SZ; cp += INT16SZ; if (type == T_SRV) { + BOUNDS_CHECK(cp, INT16SZ); bcopy((char *)cp, cp1, INT16SZ*2); cp1 += INT16SZ*2; cp += INT16SZ*2; @@ -1378,6 +1408,7 @@ print_output(zp, serial_no, msg, msglen, rrp) case T_PX: /* grab preference */ + BOUNDS_CHECK(cp, INT16SZ); bcopy((char *)cp, data, INT16SZ); cp1 = (u_char *)data + INT16SZ; cp += INT16SZ; @@ -1408,6 +1439,7 @@ print_output(zp, serial_no, msg, msglen, rrp) /* first just copy over the type_covered, algorithm, */ /* labels, orig ttl, two timestamps, and the footprint */ + BOUNDS_CHECK(cp, 18); bcopy( cp, cp1, 18 ); cp += 18; cp1 += 18; @@ -1423,8 +1455,10 @@ print_output(zp, serial_no, msg, msglen, rrp) /* finally, we copy over the variable-length signature. Its size is the total data length, minus what we copied. */ n = dlen - (18 + n); - if (n > (sizeof data) - (cp1 - (u_char *)data)) + if (n > (int)((sizeof data) - (int)(cp1 - (u_char *)data))) { + hp->rcode = FORMERR; return (-1); /* out of room! */ + } bcopy(cp, cp1, n); cp += n; cp1 += n; @@ -1448,6 +1482,14 @@ print_output(zp, serial_no, msg, msglen, rrp) hp->rcode = FORMERR; return (-1); } + if (cp != rdatap + dlen) { + dprintf(1, (ddt, + "encoded rdata length is %u, but actual length was %u\n", + dlen, (u_int)(cp - rdatap))); + hp->rcode = FORMERR; + return (-1); + } + cdata = cp1; result = cp - rrp; |